Repository: visualpython/visualpython (language: python)

Issue:
gitlab to github v1.1.0 update

Ready to release v2.2.1
# Overall
1. Rollback block color
2. Fix Varselector's default data types to show

# Data Analysis
1. Subset
 - 'query' method added

# Machine Learning
1. Evaluation 
  - Add import code on generating evaluation codes
2. Model Info
  - Add ROC Curve, AUC options to classifier models

# Visualization
1. Preview image automatically changes on its popup size
2. Some style options added (color, grid color ...)
 
# Bug fix
1. File - file navigation on write page generated wrong path. Fixed
3. Subset - add scrollbar on column list box


Discussion / hints:

Fix patch:
diff --git a/css/boardFrame.css b/css/boardFrame.css
index 0614f1da..afa80bbb 100644
--- a/css/boardFrame.css
+++ b/css/boardFrame.css
@@ -49,7 +49,7 @@
 .vp-board-title input:focus {
     transition: 0.7s;
     border: 0.5px solid var(--highlight-color) !important;
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-board-title input::selection {
 	background-color: #FDEFDD;
@@ -141,7 +141,7 @@
     float: none;
 }
 .vp-board-header-button-inner ul li:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     /* background-color: var(--light-gray-color); */
 }
 
@@ -164,7 +164,7 @@
     font-family: 'AppleSDGothicNeo';
     
 }
-.vp-block.vp-block-group {
+.vp-board-body .vp-block.vp-block-group:not(:first-child) {
     margin-top: 15px;
 }
 .vp-block-header {
@@ -239,18 +239,18 @@
     background-color: rgb(253, 177, 133);
 }
 .vp-block.visualization .vp-block-header {
-    background-color: rgb(249, 227, 214);
+    background-color: #E8ECD0;
 }
 .vp-block.visualization.vp-focus .vp-block-header,
 .vp-block.visualization.vp-focus-child .vp-block-header {
-    background-color: rgb(253, 177, 133);
+    background-color: #C6CE94;
 }
 .vp-block.machine_learning .vp-block-header {
-    background-color: #E8ECD0;
+    background-color: #E5EEF8;
 }
 .vp-block.machine_learning.vp-focus .vp-block-header,
 .vp-block.machine_learning.vp-focus-child .vp-block-header {
-    background-color: #C6CE94;
+    background-color: #BFD5F0;
 }
 .vp-block.logic-define .vp-block-header {
     background-color: rgb(213, 231, 222);
@@ -347,7 +347,7 @@
     font-size: 14px;
 }
 .vp-block-menu-item:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     cursor: pointer;
 }
 #vp_block_menu_delete:hover {    
diff --git a/css/component/dataSelector.css b/css/component/dataSelector.css
index ac006dd7..7c51ee20 100644
--- a/css/component/dataSelector.css
+++ b/css/component/dataSelector.css
@@ -1,4 +1,47 @@
 /* Code Preview */
+.vp-dataselector {
+    position: absolute;
+    top: calc(50% - 200px);
+    left: calc(50% - 200px);
+    width: 400px;
+    height: 400px;
+    background: white;
+    border: 1px solid var(--border-gray-color);
+    z-index: 999;
+    /* font */
+    font-family: AppleSDGothicNeo;
+    font-size: 14px;
+    color: var(--font-primary);
+}
+.vp-ds-variable-box {
+    border: 1px solid var(--border-gray-color);
+    height: 100px;
+    grid-row-gap: 0px;
+}
+.vp-ds-var-item {
+    height: 25px;
+    border-bottom: 1px solid var(--border-gray-color);
+}
+.vp-ds-var-item:hover {
+    background: var(--light-gray-color);
+    color: var(--font-highlight);
+    cursor: pointer;
+}
+.vp-ds-var-item.selected {
+    background: var(--light-gray-color);
+    color: var(--font-highlight);
+    font-weight: bold;
+}
+.vp-ds-var-data {
+    padding-left: 5px;
+}
+.vp-ds-var-type {
+    border-left: 1px solid var(--border-gray-color);
+    padding-left: 5px;
+}
+.vp-ds-option-box {
+
+}
 .vp-ds-preview {
     width: 100%;
     height: 35px;
diff --git a/css/fileNavigation.css b/css/component/fileNavigation.css
similarity index 99%
rename from css/fileNavigation.css
rename to css/component/fileNavigation.css
index b730f0e9..8e7fa2a5 100644
--- a/css/fileNavigation.css
+++ b/css/component/fileNavigation.css
@@ -31,7 +31,7 @@
     padding-top: 10px;
 }
 .fnp-sidebar-menu.selected {
-    color: var(--font-hightlight)
+    color: var(--font-highlight)
 }
 .fnp-sidebar-menu {
     padding: 5px 0px 5px 15px;
diff --git a/css/component/instanceEditor.css b/css/component/instanceEditor.css
index 4f321f65..3e67e062 100644
--- a/css/component/instanceEditor.css
+++ b/css/component/instanceEditor.css
@@ -8,7 +8,7 @@
 }
 .vp-ins-select-title {
     font-weight: bold;
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     padding: 5px 5px 5px 0px;
 }
 .vp-ins-select-container input.vp-ins-search {
@@ -52,7 +52,7 @@
     border-bottom: 0.25px solid var(--light-gray-color);
 }
 .vp-ins-select-item.selected {
-    color : var(--font-hightlight);
+    color : var(--font-highlight);
     background: var(--light-gray-color);
 }
 .vp-ins-select-item span {
@@ -86,7 +86,7 @@
     margin-top: 5px;
 }
 .vp-ins-select-container .vp-create-var {
-    width: 100%;
+    width: 100% !important;
 }
 .vp-ins-select-container .vp-create-var-btn {
     position: absolute;
diff --git a/css/component/modal.css b/css/component/modal.css
index 53f55845..1930f6ab 100644
--- a/css/component/modal.css
+++ b/css/component/modal.css
@@ -33,7 +33,7 @@
 	overflow: hidden;
 }
 #vp_multiButtonModal .vp-multi-button-modal-message span {
-	color: var(--font-hightlight);
+	color: var(--font-highlight);
 }
 #vp_multiButtonModal .vp-multi-button-modal-message-inner {
 	display: flex;
diff --git a/css/component/multiSelector.css b/css/component/multiSelector.css
index 77ee3fd0..e23915b5 100644
--- a/css/component/multiSelector.css
+++ b/css/component/multiSelector.css
@@ -39,7 +39,7 @@
     background-color: #E4E4E4;
 }
 .vp-cs-select-item.selected {
-    color:  var(--font-hightlight);
+    color:  var(--font-highlight);
     background-color: #F5F5F5;
 }
 /* Item Sorting FIXME: change span to class */
diff --git a/css/popupComponent.css b/css/component/popupComponent.css
similarity index 90%
rename from css/popupComponent.css
rename to css/component/popupComponent.css
index 3fff2c90..0adce053 100644
--- a/css/popupComponent.css
+++ b/css/component/popupComponent.css
@@ -63,9 +63,9 @@
 }
 .vp-popup-frame.vp-focused .vp-popup-title {
     font-family: 'AppleSDGothicNeo';
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
-.vp-popup-toggle {
+.vp-popup-maximize {
     position: absolute;
     width: 15px;
     height: 20px;
@@ -77,6 +77,31 @@
     cursor: pointer;
     color: var(--gray-color);
 }
+.vp-popup-return {
+    position: absolute;
+    width: 15px;
+    height: 20px;
+    top: 4px;
+    right: 32px;
+    z-index: 3;
+    line-height: 20px;
+    text-align: center;
+    cursor: pointer;
+    color: var(--gray-color);
+    display: none;
+}
+.vp-popup-toggle {
+    position: absolute;
+    width: 15px;
+    height: 20px;
+    top: 4px;
+    right: 58px;
+    z-index: 3;
+    line-height: 20px;
+    text-align: center;
+    cursor: pointer;
+    color: var(--gray-color);
+}
 .vp-popup-close {
     position: absolute;
     width: 20px;
@@ -94,6 +119,10 @@
     padding: 15px;
     overflow: auto;
 }
+.vp-popup-content {
+    min-height: calc(100% - 30px);
+    height: 100%;
+}
 .vp-popup-footer {
     position: relative;
     height: 50px;
@@ -169,7 +198,7 @@
     color: var(--font-primary);
 }
 .vp-popup-detail-button:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     background: var(--light-gray-color);
 }
 .vp-popup-save-button {
@@ -233,7 +262,7 @@
 	width: 15px;
 	height: 15px;
 	text-align: center;
-	background: url(../img/checkbox_unchecked.svg);
+	background: url(../../img/checkbox_unchecked.svg);
 	background-size: 15px 15px;
 	background-repeat: no-repeat;
 	border: none;
@@ -247,7 +276,7 @@
 	top: 0;
 	width: 15px;
 	height: 15px;
-	background: url(../img/checkbox_checked.svg);
+	background: url(../../img/checkbox_checked.svg);
 	background-size: 14px 14px;
 	background-repeat: no-repeat;
 	border: none;
@@ -261,7 +290,7 @@
 	top: 0;
 	width: 15px;
 	height: 15px;
-	background: url(../img/checkbox_unchecked.svg);
+	background: url(../../img/checkbox_unchecked.svg);
 	background-size: 14px 14px;
 	background-repeat: no-repeat;
 	border: none;
@@ -295,7 +324,7 @@
 	font-size: 14px;
 	line-height: 16px;
 	padding: 5px 16px 3px 9px;
-	background: url(../img/unfold_more.svg), var(--light-gray-color);
+	background: url(../../img/unfold_more.svg), var(--light-gray-color);
 	background-position: 97% 50%;
 	background-size: 11px 11px;
 	background-repeat: no-repeat;
@@ -460,7 +489,7 @@
     margin-bottom: 5px;
 }
 .vp-popup-body-top-bar-item:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-popup-body-top-bar-item img {
     -moz-box-sizing: border-box;
@@ -471,26 +500,26 @@
     margin-bottom: 5px;
 }
 .vp-popup-body-top-bar-item[data-type="install"] img {
-    background: url(../../visualpython/img/import.svg) no-repeat;
+    background: url(../../img/import.svg) no-repeat;
 }  
 .vp-popup-body-top-bar-item[data-type="install"]:hover img {
-    background: url(../../visualpython/img/import_activated.svg) no-repeat;
+    background: url(../../img/import_activated.svg) no-repeat;
 }   
 .vp-popup-body-top-bar-item[data-type="import"] {
     margin-left: 10px;
 }
 .vp-popup-body-top-bar-item[data-type="import"] img {
-    background: url(../../visualpython/img/import.svg) no-repeat;
+    background: url(../../img/import.svg) no-repeat;
 }  
 .vp-popup-body-top-bar-item[data-type="import"]:hover img {
-    background: url(../../visualpython/img/import_activated.svg) no-repeat;
+    background: url(../../img/import_activated.svg) no-repeat;
 }   
 .vp-popup-body-top-bar-item[data-type="package"] {
     margin-left: 10px;
 }
 .vp-popup-body-top-bar-item[data-type="package"] img {
-    background: url(../../visualpython/img/setting.svg) no-repeat;
+    background: url(../../img/setting.svg) no-repeat;
 }
 .vp-popup-body-top-bar-item[data-type="package"]:hover img {
-    background: url(../../visualpython/img/setting_activated.svg) no-repeat;
+    background: url(../../img/setting_activated.svg) no-repeat;
 }
\ No newline at end of file
diff --git a/css/component/successMessage.css b/css/component/successMessage.css
index 27140e6a..d9d16efa 100644
--- a/css/component/successMessage.css
+++ b/css/component/successMessage.css
@@ -1,7 +1,7 @@
 .vp-successMessage {
     position: relative;
     background-color: white;
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     min-width: 150px;
     padding: 15px;
     margin-bottom: 20px;
@@ -22,7 +22,7 @@
 }
 .vp-successMessage-icon {
     margin-left: 15px;
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 #vp_successMessage {
     position: absolute;
diff --git a/css/m_apps/import.css b/css/m_apps/import.css
index 8e7ad7c0..e724adeb 100644
--- a/css/m_apps/import.css
+++ b/css/m_apps/import.css
@@ -8,6 +8,6 @@
     cursor: pointer;
 }
 .vp-tab-button.vp-tab-selected {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     border-bottom: 2px solid var(--highlight-color);
 }
\ No newline at end of file
diff --git a/css/m_apps/snippets.css b/css/m_apps/snippets.css
index 9f00f262..72dc3061 100644
--- a/css/m_apps/snippets.css
+++ b/css/m_apps/snippets.css
@@ -90,7 +90,7 @@
     cursor: pointer;
 }
 .vp-sn-menu-item:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-sn-search-box {
     position: relative;
@@ -138,7 +138,7 @@
     cursor: pointer;
 }
 .vp-sn-sort-menu-item:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-sn-func-export-mode {
     display: none;
@@ -214,7 +214,7 @@
     cursor: pointer;
 }
 .vp-sn-item-header.selected input.vp-sn-item-title {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-sn-item-header input.vp-sn-item-title:focus {
     transition: 0.7s;
diff --git a/css/m_apps/subset.css b/css/m_apps/subset.css
index 1468d11c..91e1bfad 100644
--- a/css/m_apps/subset.css
+++ b/css/m_apps/subset.css
@@ -3,6 +3,7 @@
 }
 .vp-ds-body > table {
     width: 100%;
+    table-layout: fixed;
 }
 .vp-ds-body > table tr td {
     padding-bottom: 5px;
@@ -71,7 +72,7 @@
     cursor: pointer;
 }
 .vp-ds-tab-selector-btn.selected {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     background-color: white;
     border: 0.25px solid #E4E4E4;
     border-bottom: 2px solid #FFCF73;
@@ -179,7 +180,7 @@
     background-color: #E4E4E4;
 }
 .vp-ds-select-item.selected {
-    color:  var(--font-hightlight);
+    color:  var(--font-highlight);
     background-color: #F5F5F5;
 }
 /* Item Sorting FIXME: change span to class */
diff --git a/css/m_apps/variable.css b/css/m_apps/variable.css
index 8dfa969c..aa94e6a2 100644
--- a/css/m_apps/variable.css
+++ b/css/m_apps/variable.css
@@ -3,7 +3,7 @@
 }
 #vp_var_variableBox table tbody tr:hover,
 #vp_var_variableBox table tbody tr.vp-selected {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     background-color: #F5F5F5;
 }
 #vp_var_variableBox table tbody tr td:hover {
diff --git a/css/m_ml/__init__.py b/css/m_ml/__init__.py
new file mode 100644
index 00000000..1e8c9919
--- /dev/null
+++ b/css/m_ml/__init__.py
@@ -0,0 +1,1 @@
+print('Visual Python')
diff --git a/css/m_ml/fitPredict.css b/css/m_ml/fitPredict.css
new file mode 100644
index 00000000..adc5b916
--- /dev/null
+++ b/css/m_ml/fitPredict.css
@@ -0,0 +1,44 @@
+.vp-model-select-box {
+    grid-column-gap: 5px;
+}
+.vp-ins-select-title {
+    font-weight: bold;
+    color: var(--font-highlight);
+}
+.vp-ins-select-container input.vp-ins-search {
+    width: 100%;
+}
+.vp-ins-select-container .vp-ins-search-icon {
+    position: absolute;
+    color: #C4C4C4;
+    right: 7px;
+    top: 7px;
+}
+.vp-ins-select-box {
+    border: 0.25px solid var(--border-gray-color);
+}
+.vp-ins-select-list {
+    height: 145px;
+    width: 100%;
+    list-style: none;
+    margin: 0px;
+    padding: 0px 5px 0px 5px;
+    color: #696969;
+    overflow: auto;
+}
+.vp-ins-select-item {
+    padding-top: 3px;
+    padding-bottom: 3px;
+    cursor: pointer;
+    border-bottom: 0.25px solid var(--light-gray-color);
+}
+.vp-ins-select-item.selected {
+    color: var(--font-highlight);
+    background: var(--light-gray-color);
+}
+.vp-ins-select-item:hover {
+    background: var(--light-gray-color);
+}
+.vp-ins-parameter-box {
+    grid-column: 1/3;
+}
diff --git a/css/m_ml/modelInfo.css b/css/m_ml/modelInfo.css
new file mode 100644
index 00000000..e644f9ff
--- /dev/null
+++ b/css/m_ml/modelInfo.css
@@ -0,0 +1,41 @@
+.vp-ins-select-title {
+    font-weight: bold;
+    color: var(--font-highlight);
+}
+.vp-ins-select-container input.vp-ins-search {
+    width: 100%;
+}
+.vp-ins-select-container .vp-ins-search-icon {
+    position: absolute;
+    color: #C4C4C4;
+    right: 7px;
+    top: 7px;
+}
+.vp-ins-select-box {
+    border: 0.25px solid var(--border-gray-color);
+}
+.vp-ins-select-list {
+    height: 145px;
+    width: 100%;
+    list-style: none;
+    margin: 0px;
+    padding: 0px 5px 0px 5px;
+    color: #696969;
+    overflow: auto;
+}
+.vp-ins-select-item {
+    padding-top: 3px;
+    padding-bottom: 3px;
+    cursor: pointer;
+    border-bottom: 0.25px solid var(--light-gray-color);
+}
+.vp-ins-select-item.selected {
+    color: var(--font-highlight);
+    background: var(--light-gray-color);
+}
+.vp-ins-select-item:hover {
+    background: var(--light-gray-color);
+}
+.vp-ins-parameter-box {
+    grid-column: 1/3;
+}
diff --git a/css/m_apps/chart.css b/css/m_visualize/chart.css
similarity index 98%
rename from css/m_apps/chart.css
rename to css/m_visualize/chart.css
index c4838414..755cf24d 100644
--- a/css/m_apps/chart.css
+++ b/css/m_visualize/chart.css
@@ -169,7 +169,7 @@
     border: 2px solid  var(--highlight-color);
 }
 .vp-plot-item.selected .vp-plot-name {
-    color:  var(--font-hightlight) !important;
+    color:  var(--font-highlight) !important;
 }
 .vp-plot-item .vp-plot-thumb {
     width: 100%;
@@ -244,7 +244,7 @@
     cursor: pointer;
 }
 .vp-var-view-box .vp-var-view-list tbody tr.selected {
-    color:  var(--font-hightlight);
+    color:  var(--font-highlight);
 }
 .vp-var-view-box .var-view-footer {
     margin-top: 7px;
@@ -268,7 +268,7 @@
 }
 .vp-column-select-item.selected,
 .vp-method-select-item.selected {
-    color:  var(--font-hightlight);
+    color:  var(--font-highlight);
     background: var(--light-gray-color);
 }
 
diff --git a/css/m_visualize/seaborn.css b/css/m_visualize/seaborn.css
index 36f84855..b08a8f84 100644
--- a/css/m_visualize/seaborn.css
+++ b/css/m_visualize/seaborn.css
@@ -4,6 +4,9 @@
     padding-right: 5px;
     cursor: pointer;
 }
+.vp-chart-setting:hover {
+    color: var(--font-highlight);
+}
 .vp-create-subplot-btn {
     float: right;
 }
@@ -26,28 +29,39 @@
     text-align: center;
 }
 .vp-tab-item.vp-focus {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     background: white;
     border-bottom: 3px solid #FFCF73;
 }
 .vp-tab-page {
     width: 100%;
+    height: 100%;
+}
+.vp-tab-page-box.figure {
+    height: calc(100% - 30px);
+    align-content: baseline;
+    grid-template-rows: 1fr;
 }
 .vp-tab-page-box.plot {
     height: calc(100% - 30px);
+    min-height: 352px;
     align-content: baseline;
 }
 .vp-chart-plot-box {
+    height: 100%;
+}
+.vp-chart-body {
     display: grid;
     grid-template-columns: calc(50% - 8px) calc(50% - 8px);
+    grid-template-rows: 1fr;
     grid-row-gap: 5px;
     grid-column-gap: 15px;
     align-items: baseline;
     align-content: center;
+    height: 100%;
 }
 .vp-chart-left-box {
-    display: grid;
-    grid-row-gap: 3px;
+
 }
 .vp-chart-left-box > label {
     margin-bottom: 0px;
@@ -64,6 +78,19 @@
     padding-right: 5px;
 }
 .vp-chart-preview-box {
-    min-height: 150px;
+    min-height: 352px;
+    width: 100%;
+    height: calc(100% - 30px);
+}
+.vp-chart-preview-box img {
     width: 100%;
+    height: 100%;
+}
+.vp-tab-page label {
+    margin-bottom: 0px;
+}
+.vp-chart-setting-footer {
+    position: absolute;
+    left: 20px;
+    bottom: 15px;
 }
\ No newline at end of file
diff --git a/css/menuFrame.css b/css/menuFrame.css
index f8bcdbf3..ef5ec05a 100644
--- a/css/menuFrame.css
+++ b/css/menuFrame.css
@@ -146,7 +146,7 @@
     float: none;
 }
 #vp_headerExtraMenu .vp-header-extra-menu-list li:hover {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 /* resizing handle */
 .vp-menu-frame .ui-resizable-handle {
@@ -230,13 +230,16 @@
     background: #E56139;
 }
 .vp-menuitem.apps.vp-color-apps5 {
-    background: #BEB727;
+    background: #97AA4E;
 }
 .vp-menuitem.apps.vp-color-apps6 {
-    background: #91A541;
+    background: #88B4E9;
 }
 .vp-menuitem.apps.vp-color-apps7 {
-    background: #718E41;
+    background: #6C9BD1;
+}
+.vp-menuitem.apps.vp-color-apps8 {
+    background: #578BC7;
 }
 .vp-menuitem.apps.vp-color-preparing {
     background: var(--gray-color);
@@ -285,7 +288,7 @@
     border-radius: 2px 2px 0px 0px;
 }
 .vp-menu-task-item.vp-focus{
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     background: white;
     border-bottom: 3px solid #FFCF73;
 }
diff --git a/css/root.css b/css/root.css
index 567a75ef..19fbd343 100644
--- a/css/root.css
+++ b/css/root.css
@@ -15,7 +15,7 @@
     --light-gray-color: #F5F5F5;
     --highlight-color: #F6AD55;
     --gray-color: #C4C4C4;
-    --font-hightlight: #F38504;
+    --font-highlight: #F38504;
     --font-primary: #696969;
     --logo-url: url(../../visualpython/img/logo.png);
 }
@@ -39,10 +39,10 @@
 }
 /* font style */
 .vp-primary {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-orange-text {
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
 }
 .vp-gray-text {
     color: var(--gray-color);
@@ -336,6 +336,9 @@ hr.vp-extra-menu-line {
     width: 10px !important;
 }
 /* temporary margin */
+.mt5 {
+    margin-top: 5px;
+}
 .mb5 {
     margin-bottom: 5px;
 }
@@ -414,7 +417,7 @@ hr.vp-extra-menu-line {
 	padding: 2px 5px 2px 16px;
 }
 .vp-option-vertical-table-layout.vp-th-highlight th {
-	color: var(--font-hightlight);
+	color: var(--font-highlight);
 } 
 .vp-option-vertical-table-layout td {
 	min-width: 200px;
@@ -441,7 +444,7 @@ hr.vp-extra-menu-line {
 	padding: 2px 5px 2px 5px;
 }
 .vp-option-horizontal-table-layout.vp-th-highlight th {
-	color: var(--font-hightlight);
+	color: var(--font-highlight);
 } 
 .vp-option-horizontal-table-layout td {
 	min-width: 200px;
@@ -486,6 +489,6 @@ hr.vp-extra-menu-line {
 }
 .vp-vs-item:hover {
     background: var(--light-gray-color);
-    color: var(--font-hightlight);
+    color: var(--font-highlight);
     cursor: pointer;
 }
\ No newline at end of file
diff --git a/data/libraries.json b/data/libraries.json
index 22985d2d..eefddfce 100644
--- a/data/libraries.json
+++ b/data/libraries.json
@@ -2860,14 +2860,14 @@
                                 "file": "m_matplotlib/import"
                             },
                             {
-                                "id": "mp_plot",
+                                "id": "mp_chart",
                                 "type": "function",
                                 "level": 2,
                                 "name": "Create chart",
                                 "path": "visualpython - library - matplotlib - plot",
                                 "desc": "",
                                 "tag": "MATPLOTLIB, PLOT, CHART",
-                                "file": "m_matplotlib/plot"
+                                "file": "m_visualize/Chart"
                             },
                             {
                                 "id": "mp_figure",
@@ -3047,20 +3047,6 @@
                             "icon": "apps/apps_markdown.svg"
                         }
                     },
-                    {
-                        "id"   : "visualize_chart",
-                        "type" : "function",
-                        "level": 1,
-                        "name" : "Chart",
-                        "tag"  : "MATPLOTLIB,CHART,VISUALIZATION,VISUALIZE",
-                        "path" : "visualpython - visualization - matplotlib",
-                        "desc" : "Matplotlib chart creation",
-                        "file" : "m_apps/Chart",
-                        "apps" : {
-                            "color": 3,
-                            "icon": "apps/apps_chart.svg"
-                        }
-                    },
                     {
                         "id"   : "apps_pdf",
                         "type" : "function",
@@ -3071,7 +3057,7 @@
                         "desc" : "PDF",
                         "file" : "m_apps/PDF",
                         "apps" : {
-                            "color": 4,
+                            "color": 3,
                             "icon": "apps/apps_pymupdf.svg"
                         }
                     },
@@ -3091,6 +3077,46 @@
                     }
                 ]
             },
+            {
+                "id"   : "pkg_visualize",
+                "type" : "package",
+                "level": 0,
+                "name" : "Visualization",
+                "path" : "visualpython - visualization",
+                "desc" : "Visualization modules",
+                "open" : true,
+                "grid" : true,
+                "item" : [
+                    {
+                        "id"   : "visualize_chartStyle",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Chart Style",
+                        "tag"  : "CHART STYLE SETTING,IMPORT CHART,VISUALIZATION,VISUALIZE",
+                        "path" : "visualpython - visualization - chartsstyle",
+                        "desc" : "Chart style setting",
+                        "file" : "m_visualize/ChartSetting",
+                        "apps" : {
+                            "color": 5,
+                            "icon": "apps/apps_style.svg"
+                        }
+                    },
+                    {
+                        "id"   : "visualize_seaborn",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Seaborn",
+                        "tag"  : "SEABORN,CHART,VISUALIZATION,VISUALIZE",
+                        "path" : "visualpython - visualization - seaborn",
+                        "desc" : "Seaborn chart creation",
+                        "file" : "m_visualize/Seaborn",
+                        "apps" : {
+                            "color": 5,
+                            "icon": "apps/apps_visualize.svg"
+                        }
+                    }
+                ]
+            },
             {
                 "id"   : "pkg_ml",
                 "type" : "package",
@@ -3111,10 +3137,24 @@
                         "desc" : "Data sets for machine learning",
                         "file" : "m_ml/DataSets",
                         "apps" : {
-                            "color": 5,
+                            "color": 6,
                             "icon": "apps/apps_dataset.svg"
                         }
                     },
+                    {
+                        "id"   : "ml_dataSplit",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Data Split",
+                        "tag"  : "DATA SPLIT,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - data split",
+                        "desc" : "Data split for machine learning",
+                        "file" : "m_ml/dataSplit",
+                        "apps" : {
+                            "color": 6,
+                            "icon": "apps/apps_datasplit.svg"
+                        }
+                    },
                     {
                         "id"   : "ml_dataPrep",
                         "type" : "function",
@@ -3125,22 +3165,22 @@
                         "desc" : "Data preparation for machine learning",
                         "file" : "m_ml/DataPrep",
                         "apps" : {
-                            "color": 5,
+                            "color": 6,
                             "icon": "apps/apps_dataprep.svg"
                         }
                     },
                     {
-                        "id"   : "ml_dataSplit",
+                        "id"   : "ml_autoML",
                         "type" : "function",
                         "level": 1,
-                        "name" : "Data Split",
-                        "tag"  : "DATA SPLIT,MACHINE LEARNING,ML",
-                        "path" : "visualpython - machine_learning - data split",
-                        "desc" : "Data split for machine learning",
-                        "file" : "m_ml/dataSplit",
+                        "name" : "AutoML",
+                        "tag"  : "AUTO ML,MODEL,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - automl",
+                        "desc" : "AutoML model for machine learning",
+                        "file" : "m_ml/AutoML",
                         "apps" : {
-                            "color": 5,
-                            "icon": "apps/apps_datasplit.svg"
+                            "color": 6,
+                            "icon": "apps/apps_automl.svg"
                         }
                     },
                     {
@@ -3153,7 +3193,7 @@
                         "desc" : "Regression model for machine learning",
                         "file" : "m_ml/Regression",
                         "apps" : {
-                            "color": 5,
+                            "color": 7,
                             "icon": "apps/apps_regression.svg"
                         }
                     },
@@ -3167,7 +3207,7 @@
                         "desc" : "Classification model for machine learning",
                         "file" : "m_ml/Classification",
                         "apps" : {
-                            "color": 6,
+                            "color": 7,
                             "icon": "apps/apps_classification.svg"
                         }
                     },
@@ -3181,7 +3221,7 @@
                         "desc" : "Clustering model for machine learning",
                         "file" : "m_ml/Clustering",
                         "apps" : {
-                            "color": 6,
+                            "color": 7,
                             "icon": "apps/apps_clustering.svg"
                         }
                     },
@@ -3195,22 +3235,36 @@
                         "desc" : "Dimension reduction model for machine learning",
                         "file" : "m_ml/DimensionReduction",
                         "apps" : {
-                            "color": 6,
+                            "color": 7,
                             "icon": "apps/apps_dimension.svg"
                         }
                     },
                     {
-                        "id"   : "ml_autoML",
+                        "id"   : "ml_fitPredict",
                         "type" : "function",
                         "level": 1,
-                        "name" : "AutoML",
-                        "tag"  : "AUTO ML,MODEL,MACHINE LEARNING,ML",
-                        "path" : "visualpython - machine_learning - automl",
-                        "desc" : "AutoML model for machine learning",
-                        "file" : "m_ml/AutoML",
+                        "name" : "Fit/Predict",
+                        "tag"  : "FIT,PREDICT,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - fit_predict",
+                        "desc" : "Model fit/predict for machine learning",
+                        "file" : "m_ml/FitPredict",
                         "apps" : {
-                            "color": 6,
-                            "icon": "apps/apps_automl.svg"
+                            "color": 8,
+                            "icon": "apps/apps_fit.svg"
+                        }
+                    },
+                    {
+                        "id"   : "ml_modelInfo",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Model Info",
+                        "tag"  : "MODEL INFO,INFORMATION,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - model_info",
+                        "desc" : "Model information for machine learning",
+                        "file" : "m_ml/ModelInfo",
+                        "apps" : {
+                            "color": 8,
+                            "icon": "apps/apps_predict.svg"
                         }
                     },
                     {
@@ -3223,7 +3277,7 @@
                         "desc" : "Performance evaluation for machine learning",
                         "file" : "m_ml/evaluation",
                         "apps" : {
-                            "color": 7,
+                            "color": 8,
                             "icon": "apps/apps_evaluate.svg"
                         }
                     }
diff --git a/data/m_library/pandasLibrary.js b/data/m_library/pandasLibrary.js
index 2052798e..744ec874 100644
--- a/data/m_library/pandasLibrary.js
+++ b/data/m_library/pandasLibrary.js
@@ -102,7 +102,7 @@ define([
                     type: 'bool',
                     label: 'Copy',
                     component: 'bool_checkbox',
-                    default: false
+                    default: 'False'
                 },
                 {
                     name: 'name',
@@ -113,7 +113,7 @@ define([
                     name: 'tupleize_cols',
                     type: 'bool',
                     label: 'Create Multiindex',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 }
             ],
@@ -176,7 +176,7 @@ define([
                 {
                     name:'header',
                     type:'int',
-                    label: 'Header Index'
+                    label: 'Header'
                 },
                 {
                     name: 'sep',
@@ -220,16 +220,17 @@ define([
             ],
             variable: [
                 {
-                    name:'header',
-                    type:['bool', 'list'],
-                    label: 'Header Index',
-                    default: 'True'
+                    name: 'header',
+                    type: ['bool', 'list'],
+                    label: 'Header',
+                    default: 'True',
+                    component: 'bool_checkbox'
                 },
                 {
                     name: 'index',
                     type: 'bool',
                     label: 'Show Index',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
@@ -458,14 +459,14 @@ define([
                     name:'ascending',
                     type:'bool',
                     label: 'Ascending Sort',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
                     name:'inplace',
                     type:'bool',
                     label: 'Inplace',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -528,7 +529,7 @@ define([
                     label: 'Remove Index',
                     help: 'same as reset_index()',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 }
             ]
         },
@@ -1016,7 +1017,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name: 'level',
@@ -1061,7 +1062,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name: 'level',
@@ -1106,7 +1107,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name: 'level',
@@ -1151,7 +1152,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name: 'level',
@@ -1196,7 +1197,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name: 'level',
@@ -1241,7 +1242,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
 
                 },
                 {
@@ -1296,7 +1297,7 @@ define([
                     type: 'bool',
                     label: 'Skip Na Value',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name: 'level',
@@ -1501,14 +1502,14 @@ define([
                     type:'bool',
                     label: 'Ascending',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 },
                 {
                     name:'inplace',
                     type:'bool',
                     label: 'Inplace',
                     component: 'bool_checkbox',
-                    default: false
+                    default: 'False'
                 },
                 {
                     name: 'kind',
@@ -2226,7 +2227,7 @@ define([
                     name: 'allow_duplicates',
                     label: 'Allow Duplicates',
                     type: 'bool',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 }
             ],
@@ -2402,21 +2403,21 @@ define([
                     name: 'drop',
                     type: 'bool',
                     label: 'Drop',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'append',
                     type: 'bool',
                     label: 'Append',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'inplace',
                     type: 'bool',
                     label: 'Inplace',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 }
             ],
@@ -2454,14 +2455,14 @@ define([
                     name: 'drop',
                     type: 'bool',
                     label: 'Drop',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'inplace',
                     type: 'bool',
                     label: 'Inplace',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 }
             ],
@@ -2845,7 +2846,7 @@ define([
                     name: 'deep',
                     type: 'bool',
                     label: 'Deep',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 }
             ],
@@ -3067,7 +3068,7 @@ define([
                     name: 'dropna',
                     type: 'bool',
                     label: 'Drop Na',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 }
             ]
@@ -3282,7 +3283,7 @@ define([
                     name: 'raw',
                     type: 'bool',
                     label: 'Raw',
-                    default: false,
+                    default: 'False',
                     component: 'option_select',
                     options: ['False', 'True'],
                     options_label: ['Series', 'ndarray']
@@ -3354,7 +3355,7 @@ define([
                     name: 'right',
                     type: 'bool',
                     label: 'Include Right',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3448,7 +3449,7 @@ define([
                     name: 'replace',
                     type: 'bool',
                     label: 'Replace Duplicates',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3511,7 +3512,7 @@ define([
                     name: 'dummy_na',
                     type: 'bool',
                     label: 'Dummy NA',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3523,7 +3524,7 @@ define([
                     name: 'drop_first',
                     type: 'bool',
                     label: 'Drop First Column',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 }
             ]
@@ -3587,7 +3588,7 @@ define([
                     name: 'skipna',
                     type: 'bool',
                     label: 'Skip Na',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3647,7 +3648,7 @@ define([
                     name: 'skipna',
                     type: 'bool',
                     label: 'Skip Na',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3865,14 +3866,14 @@ define([
                     name: 'margins',
                     type: 'bool',
                     label: 'Margins',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'dropna',
                     type: 'bool',
                     label: 'Drop Na',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3938,7 +3939,7 @@ define([
                     name: 'margins',
                     type: 'bool',
                     label: 'Margins',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -3951,14 +3952,14 @@ define([
                     name: 'dropna',
                     type: 'bool',
                     label: 'Drop Na',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'normalize',
                     type: 'bool',
                     label: 'Normalize Rate',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 }
             ]
@@ -3999,14 +4000,14 @@ define([
                     name: 'dayfirst',
                     type: 'bool',
                     label: 'Day First',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'yearfirst',
                     type: 'bool',
                     label: 'Year First',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -4271,7 +4272,7 @@ define([
                     type: 'bool',
                     label: 'Copy',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 }
             ]
         },
@@ -4329,7 +4330,7 @@ define([
                     type: 'bool',
                     label: 'Copy',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 }
             ]
         },
@@ -4491,7 +4492,7 @@ define([
                     type: 'bool',
                     label: 'Normalize',
                     component: 'bool_checkbox',
-                    default: false
+                    default: 'False'
                 },
                 {
                     name: 'fill_value',
@@ -4545,7 +4546,7 @@ define([
                     type: 'bool',
                     label: 'Copy',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 }
             ]
         },
@@ -4601,7 +4602,7 @@ define([
                     type: 'bool',
                     label: 'Copy',
                     component: 'bool_checkbox',
-                    default: true
+                    default: 'True'
                 }
             ]
         },
@@ -4632,7 +4633,7 @@ define([
                     type: 'bool',
                     label: 'Deep Copy',
                     component: 'bool_checkbox',
-                    default: false
+                    default: 'False'
                 },
                 {
                     name: 'freq',
@@ -4725,7 +4726,7 @@ define([
                     name: 'center',
                     type: 'bool',
                     label: 'Center',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -4805,14 +4806,14 @@ define([
                     name: 'adjust',
                     type: 'bool',
                     label: 'Adjust',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'ignore_na',
                     type: 'bool',
                     label: 'Ignore NA',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -4959,7 +4960,7 @@ define([
                     name: 'drop',
                     type: 'bool',
                     label: 'Drop Empty',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -5067,14 +5068,14 @@ define([
                     type: 'bool',
                     label: 'Show Grid',
                     component: 'bool_checkbox',
-                    default: false
+                    default: 'False'
                 },
                 {
                     name: 'legend',
                     type: 'bool',
                     label: 'Show Legend',
                     component: 'bool_checkbox',
-                    default: false
+                    default: 'False'
                 },
                 {
                     name: 'rot',
@@ -5136,7 +5137,7 @@ define([
                     name: 'subplots',
                     type: 'bool',
                     label: 'Subplots Per Column',
-                    default: false,
+                    default: 'False',
                     component: 'bool_checkbox'
                 },
                 {
@@ -5149,14 +5150,14 @@ define([
                     name: 'use_index',
                     type: 'bool',
                     label: 'Use Index On X Ticks',
-                    default: true,
+                    default: 'True',
                     component: 'bool_checkbox'
                 },
                 {
                     name: 'stacked',
                     type: 'bool',
                     label: 'Stacked',
-                    default: false,//true in area
+                    default: 'False',//true in area
                     component: 'bool_checkbox'
                 }
             ],
diff --git a/html/boardFrame.html b/html/boardFrame.html
index 38f9330b..467e579c 100644
--- a/html/boardFrame.html
+++ b/html/boardFrame.html
@@ -43,9 +43,7 @@
         <div id="vp_boardLoading" class="vp-board-loading">
             <i class="fa fa-spinner fa-spin"></i>
         </div>
-        <div id="vp_boardBody" class="vp-board-body vp-scrollbar">
-
-        </div>
+        <div id="vp_boardBody" class="vp-board-body vp-scrollbar"></div>
         <!-- Board Footer -->
         <div id="vp_boardFooter" class="vp-board-footer">
             <div class="vp-board-footer-buttons"> 
diff --git a/html/component/dataSelector.html b/html/component/dataSelector.html
index a11f498d..acafb388 100644
--- a/html/component/dataSelector.html
+++ b/html/component/dataSelector.html
@@ -1,16 +1,26 @@
 <body>
-    <div>
-        <div class="vp-grid-col-p50">
-            <label>Variable</label>
-            <label>Data Type</label>
+    <div class="vp-dataselector">
+        <div class="vp-inner-popup-header">
+            <label class="vp-inner-popup-title">Data Selector</label>
+            <img class="vp-inner-popup-close" src="/nbextensions/visualpython/img/close_big.svg" title="Close data selector"/>
         </div>
-        <div class="vp-variable-box">
-            <div class="vp-grid-box">
+        <div class="vp-inner-popup-body vp-scrollbar">
+            <div class="vp-grid-col-p50">
+                <label class="vp-bold">Data</label>
+                <label class="vp-bold">Type</label>
+            </div>
+            <div class="vp-ds-variable-box vp-grid-box vp-scrollbar">
                 
             </div>
+            <div class="vp-ds-option-box">
+                Option Page
+            </div>
         </div>
-        <div class="vp-option-box">
-            
+        <div class="vp-inner-popup-footer">
+            <input type="text" /> <!-- CodeMirror needed -->
+            <div class="vp-inner-popup-button-box">
+                <button type="button" class="vp-button activated" id="vp_dsOk">OK</button>
+            </div>
         </div>
     </div>
 </body>
\ No newline at end of file
diff --git a/html/fileNavigation.html b/html/component/fileNavigation.html
similarity index 100%
rename from html/fileNavigation.html
rename to html/component/fileNavigation.html
diff --git a/html/popupComponent.html b/html/component/popupComponent.html
similarity index 95%
rename from html/popupComponent.html
rename to html/component/popupComponent.html
index 531b89dd..c606ebc1 100644
--- a/html/popupComponent.html
+++ b/html/component/popupComponent.html
@@ -46,6 +46,8 @@
                 <!-- Title -->
             </label>
             <img class="vp-popup-toggle" src="/nbextensions/visualpython/img/minimize.svg" title="Minimize this popup">
+            <img class="vp-popup-maximize" src="/nbextensions/visualpython/img/max_window.svg" title="Maximize this popup">
+            <img class="vp-popup-return" src="/nbextensions/visualpython/img/min_window.svg" title="Return size of this popup">
             <img class="vp-popup-close" src="/nbextensions/visualpython/img/close_big.svg" title="Close popup"/>
         </div>
         <div class="vp-popup-body vp-scrollbar">
diff --git a/html/m_apps/subset.html b/html/m_apps/subset.html
index aedc61a4..33d8da33 100644
--- a/html/m_apps/subset.html
+++ b/html/m_apps/subset.html
@@ -31,6 +31,7 @@
                             <option value="subset">subset</option>
                             <option value="loc">loc</option>
                             <option value="iloc">iloc</option>
+                            <option value="query">query</option>
                         </select>
                         <!-- to frame -->
                         <label style="display:none;"><input type="checkbox" class="vp-ds-to-frame"><span>To DataFrame</span></label>
diff --git a/html/m_ml/evaluation.html b/html/m_ml/evaluation.html
index c08859b7..88979916 100644
--- a/html/m_ml/evaluation.html
+++ b/html/m_ml/evaluation.html
@@ -1,23 +1,29 @@
 <body>
     <div class="vp-grid-box">
-        <div class="vp-grid-border-box vp-grid-col-95">
-            <label for="modelType" class="vp-orange-text">Model Type</label>
-            <select id="modelType" class="vp-select vp-state">
-                <option value="rgs">Regression</option>
-                <option value="clf">Classfication</option>
-                <option value="cls">Clustering</option>
-            </select>
-            <label for="targetData" class="vp-orange-text">Target Data</label>
-            <input type="text" class="vp-input vp-state" id="targetData" placeholder="Input target data" value="y_test"/>
-            <label for="predictData" class="vp-orange-text">Predict Data</label>
-            <input type="text" class="vp-input vp-state" id="predictData" placeholder="Input predict data" value="pred"/>
-            <label for="model" class="vp-ev-model vp-orange-text">Model</label>
-            <select id="model" class="vp-ev-model vp-select vp-state">
-                <!-- Auto create -->
-            </select>
+        <div class="vp-grid-border-box">
+            <div class="vp-grid-col-95">
+                <label for="modelType" class="vp-orange-text">Model Type</label>
+                <select id="modelType" class="vp-select vp-state">
+                    <option value="rgs">Regression</option>
+                    <option value="clf">Classfication</option>
+                    <option value="cls">Clustering</option>
+                </select>
+            </div>
+            <div class="vp-grid-col-95 vp-upper-box rgs clf">
+                <label for="targetData" class="vp-orange-text">Target Data</label>
+                <input type="text" class="vp-input vp-state" id="targetData" placeholder="Input target data" value="y_test"/>
+            </div>
+            <div class="vp-grid-col-95 vp-upper-box rgs clf">
+                <label for="predictData" class="vp-orange-text">Predict Data</label>
+                <input type="text" class="vp-input vp-state" id="predictData" placeholder="Input predict data" value="pred"/>
+            </div>
+            <div class="vp-grid-col-95 vp-upper-box cls">
+                <label for="clusteredIndex" class="vp-orange-text">Clustered Index</label>
+                <input type="text" class="vp-input vp-state" id="clusteredIndex" placeholder="Input predict data" value="clusters"/>
+            </div>
         </div>
         <div class="vp-grid-border-box">
-            <label for="featureData" class="vp-orange-text">Evaluation Metrics</label>
+            <label for="featureData">Evaluation Metrics</label>
             <div class="vp-grid-box vp-eval-box vp-eval-rgs">
                 <label><input type="checkbox" id="r_squared" class="vp-state" checked><span>R squared</span></label>
                 <label><input type="checkbox" id="mae" class="vp-state"><span>Mean Absolute Error</span></label>
@@ -33,13 +39,28 @@
                 <label><input type="checkbox" id="precision" class="vp-state"><span>Precision</span></label>
                 <label><input type="checkbox" id="recall" class="vp-state"><span>Recall</span></label>
                 <label><input type="checkbox" id="f1_score" class="vp-state"><span>F1-scorev</label>
-                <label><input type="checkbox" id="roc_curve" class="vp-eval-check vp-state"><span>ROC Curve</span></label>
-                <label><input type="checkbox" id="auc" class="vp-eval-check vp-state"><span>AUC</span></label>
+                <!-- <hr style="margin: 5px;"/> -->
+                <!-- <label><input type="checkbox" id="roc_curve" class="vp-eval-check vp-state" data-type="roc-auc"><span>ROC Curve</span></label>
+                <label><input type="checkbox" id="auc" class="vp-eval-check vp-state" data-type="roc-auc"><span>AUC</span></label> -->
+                <!-- <div class="vp-grid-col-95">
+                    <label for="model" class="vp-orange-text">Model</label>
+                    <select id="model" class="vp-select vp-state vp-ev-model roc-auc">
+                    </select>
+                </div> -->
             </div>
             <div class="vp-grid-box vp-eval-box vp-eval-cls">
-                <label><input type="checkbox" id="silhouetteScore" class="vp-state" checked><span>Silhouette score</span></label>
-                <label><input type="checkbox" id="ari" class="vp-state"><span>ARI</span></label>
-                <label><input type="checkbox" id="nm" class="vp-state"><span>NM</span></label>
+                <label><input type="checkbox" id="silhouetteScore" class="vp-eval-check vp-state" data-type="silhouette" checked><span>Silhouette score</span></label>
+                <div class="vp-grid-col-95">
+                    <label for="featureData2" class="vp-orange-text">Feature Data</label>
+                    <input type="text" class="vp-input vp-state vp-ev-model silhouette" id="featureData2" placeholder="Input feature data" value="X"/>
+                </div>
+                <hr style="margin: 5px;"/>
+                <label><input type="checkbox" id="ari" class="vp-eval-check vp-state" data-type="ari-nmi"><span>ARI (Adjusted Random Score)</span></label>
+                <label><input type="checkbox" id="nmi" class="vp-eval-check vp-state" data-type="ari-nmi"><span>NMI (Normalized Mutual Information)</span></label>
+                <div class="vp-grid-col-95">
+                    <label for="targetData2" class="vp-orange-text">Target Data</label>
+                    <input type="text" class="vp-input vp-state vp-ev-model ari-nmi" id="targetData2" placeholder="Input target data" value="y"/>
+                </div>
             </div>
         </div>
     </div>  
diff --git a/html/m_ml/fitPredict.html b/html/m_ml/fitPredict.html
new file mode 100644
index 00000000..280eb960
--- /dev/null
+++ b/html/m_ml/fitPredict.html
@@ -0,0 +1,46 @@
+<body>
+    <div class="vp-grid-box vp-model-box" data-type="selection">
+        <div class="vp-grid-border-box">
+            <div class="vp-multilang vp-ins-select-title">Model</div>
+            <!-- <select id="model" class="vp-select vp-state" style="width: 200px;">
+            </select> -->
+            <div class="vp-grid-col-p50 vp-model-select-box">
+                <!-- Model Categories -->
+                <div class="vp-ins-select-box category">
+                    <ul class="vp-ins-select-list category vp-scrollbar" style="height:100px">
+                        <!-- Auto Create -->
+                    </ul>
+                </div>
+                <!-- Model -->
+                <div class="vp-ins-select-box model">
+                    <ul class="vp-ins-select-list model vp-scrollbar" style="height:100px">
+                        <!-- Auto Create -->
+                    </ul>
+                </div>
+            </div>
+        </div>
+        <div class="vp-grid-border-box">
+            <input type="hidden" id="modelEditorType" class="vp-state" value="">
+            <input type="hidden" id="modelEditorName" class="vp-state" value="">
+            <div class="vp-grid-box vp-ins-select-container action">
+                <div class="vp-multilang vp-ins-select-title">Action</div>
+                <div style="position: relative;">
+                    <input class="vp-input vp-ins-search attr" type="text" placeholder="Search Action">
+                    <input class="vp-ins-type action" type="hidden">
+                    <i class="fa fa-search vp-ins-search-icon"></i>
+                </div>
+                <div class="vp-ins-select-box action">
+                    <ul class="vp-ins-select-list action vp-scrollbar" style="height:80px">
+                        <!-- Auto Create -->
+                    </ul>
+                </div>
+            </div>
+        </div>
+        <div class="vp-grid-border-box">
+            <div class="vp-multilang vp-ins-select-title">Options</div>
+            <div class="vp-ins-parameter-box vp-grid-col-95">
+
+            </div>
+        </div>
+    </div>
+</body>
\ No newline at end of file
diff --git a/html/m_ml/model.html b/html/m_ml/model.html
index 4c26c1c4..739aa2e0 100644
--- a/html/m_ml/model.html
+++ b/html/m_ml/model.html
@@ -1,9 +1,8 @@
 <body>
     <div class="vp-grid-box">
-        <select id="modelControlType" class="vp-big-select vp-state">
-            <option value="creation">Model Creation</option>
-            <option value="selection">Model Selection</option>
-        </select>
+        <div>
+            <label class="vp-bold">Model Creation</label>
+        </div>
         <div class="vp-grid-box vp-model-box" data-type="creation">
             <div class="vp-grid-border-box">
                 <div class="vp-grid-col-110">
@@ -24,27 +23,5 @@
                 <input type="text" class="vp-input vp-state" id="allocateToCreation" placeholder="New variable name" value="model"/>
             </div>
         </div>
-        <div class="vp-grid-box vp-model-box" data-type="selection">
-            <div class="vp-grid-border-box vp-grid-col-110">
-                <label for="model" class="vp-orange-text">Model</label>
-                <select id="model" class="vp-select vp-state" style="width: 200px;">
-                    <!-- Auto Create -->
-                </select>
-            </div>
-            <div class="vp-grid-border-box">
-                <div id="instanceEditor">
-                    <!-- instanceEditor -->
-                </div>
-            </div>
-            <div class="vp-grid-col-110 vp-model-instance-option-box">
-    
-            </div>
-            <!-- <div class="vp-grid-border-box vp-grid-col-110">
-                <label for="featureData" class="vp-orange-text">Feature data</label>
-                <input type="text" class="vp-input vp-state" id="featureData" placeholder="Select feature data" value="X_train"/>
-                <label for="targetData" class="vp-orange-text">Target data</label>
-                <input type="text" class="vp-input vp-state" id="targetData" placeholder="Select target data" value="y_train"/>
-            </div> -->
-        </div>
     </div>
 </body>
\ No newline at end of file
diff --git a/html/m_ml/modelInfo.html b/html/m_ml/modelInfo.html
new file mode 100644
index 00000000..9e1309b1
--- /dev/null
+++ b/html/m_ml/modelInfo.html
@@ -0,0 +1,46 @@
+<body>
+    <div class="vp-grid-box vp-model-box" data-type="selection">
+        <div class="vp-grid-border-box">
+            <div class="vp-multilang vp-ins-select-title">Model</div>
+            <!-- <select id="model" class="vp-select vp-state" style="width: 200px;">
+            </select> -->
+            <div class="vp-grid-col-p50 vp-model-select-box">
+                <!-- Model Categories -->
+                <div class="vp-ins-select-box category">
+                    <ul class="vp-ins-select-list category vp-scrollbar" style="height:100px">
+                        <!-- Auto Create -->
+                    </ul>
+                </div>
+                <!-- Model -->
+                <div class="vp-ins-select-box model">
+                    <ul class="vp-ins-select-list model vp-scrollbar" style="height:100px">
+                        <!-- Auto Create -->
+                    </ul>
+                </div>
+            </div>
+        </div>
+        <div class="vp-grid-border-box">
+            <input type="hidden" id="modelEditorType" class="vp-state" value="">
+            <input type="hidden" id="modelEditorName" class="vp-state" value="">
+            <div class="vp-grid-box vp-ins-select-container info">
+                <div class="vp-multilang vp-ins-select-title">Info</div>
+                <div style="position: relative;">
+                    <input class="vp-input vp-ins-search attr" type="text" placeholder="Search Information">
+                    <input class="vp-ins-type info" type="hidden">
+                    <i class="fa fa-search vp-ins-search-icon"></i>
+                </div>
+                <div class="vp-ins-select-box info">
+                    <ul class="vp-ins-select-list info vp-scrollbar" style="height:80px">
+                        <!-- Auto Create -->
+                    </ul>
+                </div>
+            </div>
+        </div>
+        <div class="vp-grid-border-box">
+            <div class="vp-multilang vp-ins-select-title">Options</div>
+            <div class="vp-ins-parameter-box vp-grid-col-95">
+
+            </div>
+        </div>
+    </div>
+</body>
\ No newline at end of file
diff --git a/html/m_apps/chart.html b/html/m_visualize/chart.html
similarity index 100%
rename from html/m_apps/chart.html
rename to html/m_visualize/chart.html
diff --git a/html/m_visualize/chartSetting.html b/html/m_visualize/chartSetting.html
index 0c95c13c..28f364d9 100644
--- a/html/m_visualize/chartSetting.html
+++ b/html/m_visualize/chartSetting.html
@@ -1,5 +1,5 @@
 <body>
-    <div class="vp-grid-border-box vp-grid-col-95">
+    <div class="vp-chart-setting-body vp-grid-border-box vp-grid-col-95">
         <label for="figureWidth" class="">Figure size</label>
         <div>
             <input type="number" id="figureWidth" class="vp-input m vp-state" placeholder="width" value="12">
@@ -12,4 +12,8 @@
         <label for="fontSize" class="">Font size</label>
         <input type="number" id="fontSize" class="vp-input vp-state" placeholder="size" value="10">
     </div>
+    <label class="mt5">
+        <input type="checkbox" id="setDefault">
+        <span title="Set chart setting to default.">Set Default</span>
+    </label>
 </body>
\ No newline at end of file
diff --git a/html/m_visualize/seaborn.html b/html/m_visualize/seaborn.html
index a8301186..01e7cef6 100644
--- a/html/m_visualize/seaborn.html
+++ b/html/m_visualize/seaborn.html
@@ -1,6 +1,6 @@
 <body>
-    <!-- Creating Subplots -->
-    <div>
+    <!-- Creating Subplots : Hide for next version -->
+    <!-- <div>
         <div>
             <label class="vp-bold">
                 Creating Subplots
@@ -35,119 +35,151 @@
                 </div>
             </div>
         </div>
-    </div>
-    <div class="vp-tab-bar figure" data-level="figure" style="margin-top:10px;">
-        <div class="vp-tab-item vp-focus" data-type="1">Plot 1</div>
-        <div class="vp-tab-item" data-type="2">Plot 2</div>
-        <div class="vp-tab-item" data-type="3">Plot 3</div>
-    </div>
-    <div class="vp-tab-page-box figure vp-grid-border-box">
-        <div class="vp-tab-page" data-type="1">
-            <div class="vp-chart-plot-box">
-                <!-- Chart & Data Selection Box-->
-                <div class="vp-chart-left-box">
-                    <div class="vp-italic">
-                        <span class="vp-orange-text">NOTE: </span>Options selected from this tab only apply to subplot 1.
-                    </div>
-                    <label for="chartType" class="vp-bold vp-orange-text">Chart Type</label>
-                    <select id="chartType" class="vp-select vp-state wp100">
+    </div> -->
+    <div class="vp-chart-body" style="margin-top:10px;">
+        <div class="vp-chart-left-box">
+            <div class="vp-tab-bar figure" data-level="figure">
+                <div class="vp-tab-item vp-focus" data-type="1">Plot</div>
+                <!-- Hide for next version -->
+                <!-- <div class="vp-tab-item" data-type="2">Plot 2</div>
+                <div class="vp-tab-item" data-type="3">Plot 3</div> -->
 
-                    </select>
-                    <label for="data" class="vp-bold vp-orange-text">Variable</label>
-                    <input type="text" id="data" class="vp-input vp-state"/>
-                    <div class="vp-grid-col-p50">
-                        <div>
-                            <label for="x" class="vp-bold vp-orange-text">X-axis Value</label>
-                            <select id="x" class="vp-select vp-state">
-    
-                            </select>
-                        </div>
-                        <div>
-                            <label for="y" class="vp-bold">Y-axis Value</label>
-                            <select id="y" class="vp-select vp-state">
-    
-                            </select>
-                        </div>
-                    </div>
-                    <label for="hue" class="vp-bold">Hue</label>
-                    <select id="hue" class="vp-select vp-state wp100">
+                <!-- Temporary position : Change its position after enabling Subplots -->
+                <span id="chartSetting" class="vp-chart-setting vp-no-selection">
+                    <i class="fa fa-gear"></i> Setting
+                </span>
+            </div>
+            <div class="vp-tab-page-box figure vp-grid-border-box vp-scrollbar">
+                <div class="vp-tab-page" data-type="1">
+                    <div class="vp-chart-plot-box">
+                        <!-- Chart & Data Selection & Tab option box -->
+                            <div class="vp-tab-bar plot" data-level="plot">
+                                <div class="vp-tab-item vp-focus" data-type="data">Data</div>
+                                <div class="vp-tab-item" data-type="info">Info</div>
+                                <div class="vp-tab-item" data-type="style">Style</div>
+                                <div class="vp-tab-item" data-type="setting">Setting</div>
+                            </div>
+                            <div class="vp-tab-page-box plot vp-grid-border-box vp-scrollbar">
+                                <div class="vp-tab-page vp-grid-box" data-type="data">
+                                    <div class="vp-italic">
+                                        <span class="vp-orange-text">NOTE: </span>Options selected from this tab only apply to subplot 1.
+                                    </div>
+                                    <label for="chartType" class="vp-bold vp-orange-text">Chart Type</label>
+                                    <select id="chartType" class="vp-select vp-state wp100">
+                
+                                    </select>
+                                    <label for="data" class="vp-bold">Data</label>
+                                    <div class="vp-grid-col-p50">
+                                        <input type="text" id="data" class="vp-input vp-state"/>
+                                        <label><input type="checkbox" id="setXY" class="vp-state"><span>Set X and Y indivisually</span></label>
+                                    </div>
+                                    <div class="vp-grid-col-p50">
+                                        <div class="vp-grid-box">
+                                            <label for="x" class="vp-bold">X-axis Value</label>
+                                            <select id="x" class="vp-select vp-state">
+                    
+                                            </select>
+                                        </div>
+                                        <div class="vp-grid-box">
+                                            <label for="y" class="vp-bold">Y-axis Value</label>
+                                            <select id="y" class="vp-select vp-state">
+                    
+                                            </select>
+                                        </div>
+                                    </div>
+                                    <label for="hue" class="vp-bold">Hue</label>
+                                    <select id="hue" class="vp-select vp-state">
+                
+                                    </select>
+                                    <label for="userOption" class="vp-bold">User Option</label>
+                                    <input type="text" id="userOption" class="vp-input vp-state wp100" placeholder="key=value, ..."/>
+                                </div>
+                                <div class="vp-tab-page vp-grid-box" data-type="info" style="display: none;">
+                                    <label for="title" class="vp-bold">Title</label>
+                                    <input type="text" id="title" class="vp-input vp-state wp100" placeholder="Title for the chart" />
+                                    <div class="vp-grid-col-p50">
+                                        <div class="vp-grid-box">
+                                            <label for="x_label" class="vp-bold">X Label</label>
+                                            <input type="text" id="x_label" class="vp-input vp-state" placeholder="Type X Label" />
+                                        </div>
+                                        <div class="vp-grid-box">
+                                            <label for="y_label" class="vp-bold">Y Label</label>
+                                            <input type="text" id="y_label" class="vp-input vp-state" placeholder="Type Y Label" />
+                                        </div>
+                                    </div>
+                                    
+                                    <label for="useLegend" class="vp-bold">Legend</label>
+                                    <div class="vp-grid-col-p50">
+                                        <select id="legendPos" class="vp-select vp-state">
+                                            <!-- Legend Position FIXME: -->
 
-                    </select>
-                </div>
-                <!-- Tab Option Box -->
-                <div class="vp-chart-right-box">
-                    <div class="vp-tab-bar plot" data-level="plot">
-                        <div class="vp-tab-item vp-focus" data-type="info">Info</div>
-                        <div class="vp-tab-item" data-type="style">Style</div>
-                        <div class="vp-tab-item" data-type="setting">Setting</div>
-                    </div>
-                    <div class="vp-tab-page-box plot vp-grid-border-box vp-scrollbar">
-                        <div class="vp-tab-page vp-grid-box" data-type="info">
-                            <label for="title">Title</label>
-                            <input type="text" id="title" class="vp-input vp-state wp100" placeholder="Title for the chart" />
-                            <div class="vp-grid-col-p50">
-                                <div>
-                                    <label for="x_label">X Label</label>
-                                    <input type="text" id="x_label" class="vp-input vp-state" placeholder="Type X Label" />
+                                        </select>
+                                    </div>
                                 </div>
-                                <div>
-                                    <label for="y_label">Y Label</label>
-                                    <input type="text" id="y_label" class="vp-input vp-state" placeholder="Type Y Label" />
+                                <div class="vp-tab-page vp-grid-box" data-type="style" style="display: none;">
+                                    <!-- STYLE: grid / marker / color -->
+                                    <label for="color" class="vp-bold">Color</label>
+                                    <input type="color" id="color" class="vp-state"/>
+                                    <label for="useGrid" class="vp-bold">Grid</label>
+                                    <div>
+                                        <select id="useGrid" class="vp-select vp-state">
+                                            <option value="">Select option...</option>
+                                            <option value="True">True</option>
+                                            <option value="False">False</option>
+                                        </select>
+                                        <input type="color" id="gridColor" class="vp-state"/>
+                                    </div>
+                                    <label for="useMarker" class="vp-bold">Marker</label>
+                                    <div class="vp-grid-col-p50">
+                                        <select id="markerStyle" class="vp-select vp-state">
+                                            <!-- TODO: -->
+                                            <option></option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="vp-tab-page vp-grid-col-95" data-type="setting" style="display: none;">
+                                    <!-- SETTING : axis limit / tick interval / rotate tick labels ... -->
+                                    <label for="x_limit_from" class="vp-bold">X Limit</label>
+                                    <div class="vp-grid-col-p50">
+                                        <input type="text" id="x_limit_from" class="vp-input m vp-state" placeholder="From" />
+                                        <input type="text" id="x_limit_to" class="vp-input m vp-state" placeholder="To" />
+                                    </div>
+                                    <label for="y_limit_from" class="vp-bold">Y Limit</label>
+                                    <div class="vp-grid-col-p50">
+                                        <input type="text" id="y_limit_from" class="vp-input m vp-state" placeholder="From" />
+                                        <input type="text" id="y_limit_to" class="vp-input m vp-state" placeholder="To" />
+                                    </div>
                                 </div>
                             </div>
-                            
-                            <label for="useLegend">Legend</label>
-                            <div class="vp-grid-col-p50">
-                                <select id="useLegend" class="vp-select vp-state">
-                                    <option value="False">False</option>
-                                    <option value="True">True</option>
-                                </select>
-                                <select id="legendPos" class="vp-select vp-state">
-                                    <!-- Legend Position FIXME: -->
-
-                                </select>
-                            </div>
-                        </div>
-                        <div class="vp-tab-page vp-grid-col-95" data-type="style" style="display: none;">
-                            STYLE : grid / marker / color
-                        </div>
-                        <div class="vp-tab-page vp-grid-col-95" data-type="setting" style="display: none;">
-                            <!-- SETTING : axis limit / tick interval / rotate tick labels ... -->
-                            <label for="x_limit_from">X Limit</label>
-                            <div class="vp-grid-col-p50">
-                                <input type="text" id="x_limit_from" class="vp-input m vp-state" placeholder="From" />
-                                <input type="text" id="x_limit_to" class="vp-input m vp-state" placeholder="To" />
-                            </div>
-                            <label for="y_limit_from">Y Limit</label>
-                            <div class="vp-grid-col-p50">
-                                <input type="text" id="y_limit_from" class="vp-input m vp-state" placeholder="From" />
-                                <input type="text" id="y_limit_to" class="vp-input m vp-state" placeholder="To" />
-                            </div>
-                        </div>
                     </div>
                 </div>
             </div>
         </div>
-    </div>
-    <div style="margin-top:10px;">
-        <div class="vp-bold">
-            <span class="vp-chart-preview-title">Chart Preview</span> 
-            <span class="vp-chart-preview-option vp-no-selection">
-                <label><input type="checkbox" id="useSampling" class="vp-state" checked><span>Sampling</span></label>
-                <select id="sampleCount" class="vp-select s vp-state">
-
-                </select>
-                <label><input type="checkbox" id="autoRefresh" class="vp-state" checked><span>Auto Refresh</span></label>
-                <span id="previewRefresh" class="vp-cursor">
-                    <img src="/nbextensions/visualpython/img/refresh.svg"/>
+        <div class="vp-chart-right-box">
+            <div class="vp-bold">
+                <span class="vp-chart-preview-title">Chart Preview</span> 
+                <span class="vp-chart-preview-option vp-no-selection">
+                    <label><input type="checkbox" id="useSampling" class="vp-state" checked><span>Sampling</span></label>
+                    <select id="sampleCount" class="vp-select s vp-state">
+    
+                    </select>
+                    <label style="margin-left:10px;"><input type="checkbox" id="autoRefresh" class="vp-state" checked><span>Auto Refresh</span></label>
+                    <span id="previewRefresh" class="vp-cursor">
+                        <img src="/nbextensions/visualpython/img/refresh.svg"/>
+                    </span>
                 </span>
-            </span>
-        </div>
-        <div class="vp-chart-preview-box vp-grid-border-box">
-            <span></span>
-            <div id="chartPreview" class="vp-center">
-
             </div>
+            <div class="vp-chart-preview-box vp-grid-border-box">
+                <span></span>
+                <div id="chartPreview" class="vp-center">
+    
+                </div>
+            </div>
+            <!-- <div class="vp-chart-preview-size-box vp-grid-col-95 mt5">
+                <label>Preview Size</label>
+                <input type="range" id="previewSize" max="5" min="-5" value="0"/>
+            </div> -->
         </div>
     </div>
+    
 </body>
\ No newline at end of file
diff --git a/img/apps/apps_visualize.svg b/img/apps/apps_visualize.svg
new file mode 100644
index 00000000..28711332
--- /dev/null
+++ b/img/apps/apps_visualize.svg
@@ -0,0 +1,8 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M24 0H0V24H24V0Z" fill="white" fill-opacity="0.01"/>
+<path d="M3 3V21H21" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M7 15V17" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M11 11V17" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M15 3V17" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M19 7V17" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/img/max_window.svg b/img/max_window.svg
new file mode 100644
index 00000000..b2aa45e8
--- /dev/null
+++ b/img/max_window.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 1H2C1.44772 1 1 1.44772 1 2V12C1 12.5523 1.44772 13 2 13H12C12.5523 13 13 12.5523 13 12V2C13 1.44772 12.5523 1 12 1Z" stroke="#C4C4C4" stroke-width="1.5"/>
+</svg>
diff --git a/img/min_window.svg b/img/min_window.svg
new file mode 100644
index 00000000..f7578948
--- /dev/null
+++ b/img/min_window.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.60209 0C4.79454 0 4.13989 0.65465 4.13989 1.4622V3.89868H5.43989V1.4622C5.43989 1.37262 5.51251 1.3 5.60209 1.3H13.7241C13.8137 1.3 13.8863 1.37261 13.8863 1.4622V9.58419C13.8863 9.67378 13.8137 9.74639 13.7241 9.74639H10.7462V11.0464H13.7241C14.5316 11.0464 15.1863 10.3918 15.1863 9.58419V1.4622C15.1863 0.654657 14.5317 0 13.7241 0H5.60209Z" fill="#C4C4C4"/>
+<path d="M9.93419 3.89868H1.8122C1.36364 3.89868 1 4.26232 1 4.71088V12.8329C1 13.2814 1.36364 13.6451 1.8122 13.6451H9.93419C10.3828 13.6451 10.7464 13.2814 10.7464 12.8329V4.71088C10.7464 4.26232 10.3828 3.89868 9.93419 3.89868Z" stroke="#C4C4C4" stroke-width="1.4"/>
+</svg>
diff --git a/js/board/Block.js b/js/board/Block.js
index 24d4c2d0..725eb9c9 100644
--- a/js/board/Block.js
+++ b/js/board/Block.js
@@ -199,10 +199,11 @@ define([
                 this.focusItem();
             }
 
+            // Deprecated: show markdown as other DA blocks
             // if markdown, set its height to fit-content
-            if (this.id == 'apps_markdown') {
-                $(this.wrapSelector()).addClass('vp-block-markdown');
-            }
+            // if (this.id == 'apps_markdown') {
+            //     $(this.wrapSelector()).addClass('vp-block-markdown');
+            // }
 
             // if viewDepthNumber, show it
             let viewDepthNumber = this.prop.parent.state.viewDepthNumber;
@@ -304,9 +305,10 @@ define([
             if (this._getMenuGroupRootType() == 'logic') {
                 header = this.task.generateCode();
             }
-            if (this.id == 'apps_markdown') {
-                header = this.task.getPreview();
-            }
+            // Deprecated: show markdown as other blocks
+            // if (this.id == 'apps_markdown') {
+            //     header = this.task.getPreview();
+            // }
             this.state.header = header;
             return header;
         }
diff --git a/js/board/BoardFrame.js b/js/board/BoardFrame.js
index f366c6a9..96c2d817 100644
--- a/js/board/BoardFrame.js
+++ b/js/board/BoardFrame.js
@@ -724,9 +724,6 @@ define([
             this.clearBoard();
         }
         clearBoard() {
-            // TODO: alert before clearing
-            let that = this;
-
             // clear board
             this.blockList.forEach(block => {
                 block.popup.remove();
diff --git a/js/com/com_Config.js b/js/com/com_Config.js
index 127ac6e4..5d7253f9 100644
--- a/js/com/com_Config.js
+++ b/js/com/com_Config.js
@@ -437,6 +437,10 @@ define([
             })
         }
 
+        getDataTypes() {
+            return Config.DATA_TYPES;
+        }
+
         getMLDataDict(key = '') {
             if (key == '') {
                 return Config.ML_DATA_DICT;
@@ -448,6 +452,10 @@ define([
             return Config.ML_DATA_TYPES;
         }
 
+        getMLCategories() {
+            return Object.keys(Config.ML_DATA_DICT);
+        }
+
     }
 
     //========================================================================
@@ -462,7 +470,7 @@ define([
     /**
      * Version
      */
-    Config.version = "2.1.3";
+    Config.version = "2.2.1";
 
     /**
      * Type of mode
@@ -478,42 +486,60 @@ define([
     Config.MENU_BOARD_SPACING = 5;
     Config.VP_MIN_WIDTH = Config.MENU_MIN_WIDTH + Config.BOARD_MIN_WIDTH + Config.MENU_BOARD_SPACING; // = MENU_MIN_WIDTH + BOARD_MIN_WIDTH + MENU_BOARD_SPACING
     
+    /**
+     * Data types
+     */
+    Config.DATA_TYPES = [
+        // pandas object
+        'DataFrame', 'Series', 'Index', 'Period', 'GroupBy', 'Timestamp'
+        // Index type object
+        , 'RangeIndex', 'CategoricalIndex', 'MultiIndex', 'IntervalIndex', 'DatetimeIndex', 'TimedeltaIndex', 'PeriodIndex', 'Int64Index', 'UInt64Index', 'Float64Index'
+        // GroupBy type object
+        , 'DataFrameGroupBy', 'SeriesGroupBy'
+        // Plot type
+        , 'Figure', 'AxesSubplot'
+        // Numpy
+        , 'ndarray'
+        // Python variable
+        , 'str', 'int', 'float', 'bool', 'dict', 'list', 'tuple'
+    ]
+
     /**
      * Data types using for searching model variables
      */
     Config.ML_DATA_DICT = {
+        'Data Preparation': [
+            /** Encoding */
+            'OneHotEncoder', 'LabelEncoder', 'OrdinalEncoder', 'TargetEncoder', 'SMOTE',
+            /** Scaling */
+            'StandardScaler', 'RobustScaler', 'MinMaxScaler', 'Normalizer', 'FunctionTransformer', 'PolynomialFeatures', 'KBinsDiscretizer',
+            /** ETC */
+            'ColumnTransformer'
+        ],
         'Regression': [
             'LinearRegression', 'Ridge', 'Lasso', 'ElasticNet', 'SVR', 'DecisionTreeRegressor', 'RandomForestRegressor', 'GradientBoostingRegressor', 'XGBRegressor', 'LGBMRegressor', 'CatBoostRegressor',
         ],
         'Classification': [
             'LogisticRegression', 'BernoulliNB', 'MultinomialNB', 'GaussianNB', 'SVC', 'DecisionTreeClassifier', 'RandomForestClassifier', 'GradientBoostingClassifier', 'XGBClassifier', 'LGBMClassifier', 'CatBoostClassifier',
         ],
-        'Auto ML': [
-            'AutoSklearnRegressor', 'AutoSklearnClassifier', 'TPOTRegressor', 'TPOTClassifier'
-        ],
         'Clustering': [
             'KMeans', 'AgglomerativeClustering', 'GaussianMixture', 'DBSCAN',
         ],
         'Dimension Reduction': [
             'PCA', 'LinearDiscriminantAnalysis', 'TruncatedSVD', 'NMF', 'TSNE'
         ],
-        'Data Preparation': [
-            /** Encoding */
-            'OneHotEncoder', 'LabelEncoder', 'OrdinalEncoder', 'TargetEncoder', 'SMOTE',
-            /** Scaling */
-            'StandardScaler', 'RobustScaler', 'MinMaxScaler', 'Normalizer', 'FunctionTransformer', 'PolynomialFeatures', 'KBinsDiscretizer',
-            /** ETC */
-            'ColumnTransformer'
+        'Auto ML': [
+            'AutoSklearnRegressor', 'AutoSklearnClassifier', 'TPOTRegressor', 'TPOTClassifier'
         ]
     };
 
     Config.ML_DATA_TYPES = [
+        ...Config.ML_DATA_DICT['Data Preparation'],
         ...Config.ML_DATA_DICT['Regression'],
         ...Config.ML_DATA_DICT['Classification'],
-        ...Config.ML_DATA_DICT['Auto ML'],
         ...Config.ML_DATA_DICT['Clustering'],
         ...Config.ML_DATA_DICT['Dimension Reduction'],
-        ...Config.ML_DATA_DICT['Data Preparation']
+        ...Config.ML_DATA_DICT['Auto ML']
     ];
 
     return Config;
diff --git a/js/com/com_Const.js b/js/com/com_Const.js
index ed3a48f6..adec12b7 100644
--- a/js/com/com_Const.js
+++ b/js/com/com_Const.js
@@ -19,7 +19,7 @@ define ([
     class Constants { }
 
     Constants.TOOLBAR_BTN_INFO = {
-        HELP: "Visual Python 2.1.3"
+        HELP: "Visual Python 2.2.1"
         , ICON: "vp-main-icon"
         , ID: "vpBtnToggle"
         , NAME: "toggle-vp"
diff --git a/js/com/com_generator.js b/js/com/com_generator.js
index 2239886c..2bffe0de 100644
--- a/js/com/com_generator.js
+++ b/js/com/com_generator.js
@@ -18,6 +18,11 @@ define([
      */
     var _VP_SHOW_RESULT = true;
 
+    const _VP_BOOL_OPTIONS = [
+        { label: 'True', value: 'True' },
+        { label: 'False', value: 'False' }
+    ]
+
      /**
      * Generate page interface based on package configuration
      * @param {*} package 
@@ -107,11 +112,31 @@ define([
         // create as component type
         switch (obj.component) {
             case 'bool_checkbox':
-                // FIXME: True False select box
-                var select = $(`<select id="${obj.name}" class="vp-select vp-state"><option value="">Default</option></select>`);
-                select.append($('<option value="True">True</option>'))
-                    .append($('<option value="False">False</option>'));
-                $(tblInput).append(select);
+                // True False select box
+                var optSlct = $(`<select id="${obj.name}" class="vp-select vp-state"></select>`);
+                _VP_BOOL_OPTIONS.forEach((opt, idx) => {
+                    var option = $(`<option>${opt.label}${obj.default==opt.value?' (default)':''}</option>`).attr({
+                        // 'id':opt,
+                        'index':obj.index,
+                        'name':obj.name,
+                        'value':(obj.default==opt.value?'':opt.value)
+                    });
+                    // cell metadata test
+                    if (getValue && obj.value != undefined) {
+                        // set as saved value
+                        if (obj.value == opt) {
+                            $(option).attr({
+                                'selected':'selected'
+                            });
+                        }
+                    } else if (obj.default == opt.value) {
+                        $(option).attr({
+                            'selected':'selected'
+                        });
+                    }
+                    optSlct.append(option);
+                });
+                $(tblInput).append(optSlct);
                 break;
             case 'option_select':
                 var optSlct = document.createElement('select');
diff --git a/js/com/com_generatorV2.js b/js/com/com_generatorV2.js
index 4881a316..92356462 100644
--- a/js/com/com_generatorV2.js
+++ b/js/com/com_generatorV2.js
@@ -656,12 +656,14 @@ define([
      * @param {object} target 
      * @param {array} columnInputIdList 
      * @param {string} tagType input / select (tag type)
+     * @param {array/boolean} columnWithEmpty boolean array or value to decide whether select tag has empty space
+     * @param {array/boolean} columnWithIndex boolean array or value to decide whether select tag has index option
      * Usage : 
      *  $(document).on('change', this.wrapSelector('#dataframe_tag_id'), function() {
-     *      pdGen.vp_bindColumnSource(that.wrapSelector(), this, ['column_input_id']);
+     *      pdGen.vp_bindColumnSource(that.wrapSelector(), this, ['column_input_id'], 'select', [true, true, true]);
      *  });
      */
-    var vp_bindColumnSource = function(selector, target, columnInputIdList, tagType="input") {
+    var vp_bindColumnSource = function(selector, target, columnInputIdList, tagType="input", columnWithEmpty=false, columnWithIndex=false) {
         var varName = '';
         if ($(target).length > 0) {
             varName = $(target).val();
@@ -701,8 +703,36 @@ define([
                 let { result, type, msg } = resultObj;
                 var varResult = JSON.parse(result);
 
+                // check if it needs to add index option
+                let addIndex = false;
+                if (Array.isArray(columnWithIndex)) {
+                    addIndex = columnWithIndex[idx];
+                } else {
+                    addIndex = columnWithIndex;
+                }
+                if (addIndex == true) {
+                    varResult = [
+                        {value: varName + '.index', label: 'index'},
+                        ...varResult
+                    ]
+                }
+
+                // check if it needs to add empty option
+                let addEmpty = false;
+                if (Array.isArray(columnWithEmpty)) {
+                    addEmpty = columnWithEmpty[idx];
+                } else {
+                    addEmpty = columnWithEmpty;
+                }
+                if (addEmpty == true) {
+                    varResult = [
+                        {value: '', label: 'Select option...'},
+                        ...varResult
+                    ]
+                }
+
                 // columns using suggestInput
-                columnInputIdList && columnInputIdList.forEach(columnInputId => {
+                columnInputIdList && columnInputIdList.forEach((columnInputId, idx) => {
                     let defaultValue = $(selector + ' #' + columnInputId).val();
                     if (defaultValue == null || defaultValue == undefined) {
                         defaultValue = '';
@@ -724,6 +754,7 @@ define([
                             'id': columnInputId,
                             'class': 'vp-select vp-state'
                         });
+                        // make tag
                         varResult.forEach(listVar => {
                             var option = document.createElement('option');
                             $(option).attr({
diff --git a/js/com/component/DataSelector.js b/js/com/component/DataSelector.js
index 8f0c63f9..0bc90693 100644
--- a/js/com/component/DataSelector.js
+++ b/js/com/component/DataSelector.js
@@ -23,33 +23,94 @@ define([
     class DataSelector extends Component {
 
         /**
-         * 
-         * @param {string} frameSelector        query for parent component
-         * @param {Object} config  parent:[], selectedList=[], includeList=[]
+         * Constructor
+         * @param {Object} state  { type, ... }
          */
-        constructor(frameSelector, config) {
-            super(frameSelector, config, {});
+        constructor(state) {
+            super($('#site'), state);
         }
 
         _init() {
-            this.frameSelector = this.$target;
+            super._init();
 
-            // configuration
-            this.config = this.state;
+            this.state = {
+                type: 'data',   // selector type : data / column
+                target: null,   // target jquery object
+                finish: null,   // callback after selection
+                data: '',
+                dataType: '',
+                ...this.state
+            }
 
-            var { mode, type, parent, selectedList=[], includeList=[], excludeList=[] } = this.config;
-            this.mode = mode;
-            this.parent = parent;
-            this.selectedList = selectedList;
-            this.includeList = includeList;
-            this.excludeList = excludeList;
+        }
+
+        _bindEvent() {
+            let that = this;
+
+            // Click X to close
+            $(that.wrapSelector('.vp-inner-popup-close')).on('click', function() {
+                that.close();
+            });
+
+            // Click ok
+            $(that.wrapSelector('#vp_dsOk')).on('click', function() {
+                // TODO: set target value
+                let newValue = that.state.data;
+
+                $(that.state.target).val(newValue);
+                $(that.state.target).data('type', that.state.dataType);
+                that.state.finish(newValue);
+                that.close();
+            });
+
+        }
+
+        /**
+         * Bind event for items created dynamically
+         */
+        _bindEventForItem() {
+            let that = this;
 
+            // Click variable item
+            $(that.wrapSelector('.vp-ds-var-item')).off('click');
+            $(that.wrapSelector('.vp-ds-var-item')).on('click', function() {
+                $(that.wrapSelector('.vp-ds-var-item')).removeClass('selected');
+                $(this).addClass('selected');
 
+                let data = $(this).find('.vp-ds-var-data').text();
+                let dataType = $(this).find('.vp-ds-var-type').text();
+                that.state.data = data;
+                that.state.dataType = dataType;
+
+                // TODO: load preview
+            });
         }
 
-        load() {
-            $(this.frameSelector).html(this.render());
-            this.bindEvent();
+        loadVariables() {
+            let that = this;
+            // Searchable variable types
+            let types = [
+                ...vpConfig.getDataTypes(),
+                // ML Data types
+                ...vpConfig.getMLDataTypes()
+            ];
+            
+            vpKernel.getDataList(types).then(function(resultObj) {
+                var varList = JSON.parse(resultObj.result);
+
+                let varTags = new com_String();
+                varList && varList.forEach((varObj, idx) => {
+                    varTags.appendFormatLine('<div class="{0} {1}">', 'vp-ds-var-item', 'vp-grid-col-p50');
+                    varTags.appendFormatLine('<div class="{0}">{1}</div>', 'vp-ds-var-data', varObj.varName);
+                    varTags.appendFormatLine('<div class="{0}">{1}</div>', 'vp-ds-var-type', varObj.varType);
+                    varTags.appendLine('</div>');
+                });
+
+                $(that.wrapSelector('.vp-ds-variable-box')).html(varTags.toString());
+
+                that._bindEventForItem();
+
+            });
         }
 
         template() {
@@ -57,13 +118,17 @@ define([
         }
 
         render() {
-            
-        }
+            super.render();
 
-        bindEvent() {
-            let that = this;
+            this.loadVariables();
+        }
 
+        open() {
+            $(this.wrapSelector()).show();
+        }
 
+        close() {
+            $(this.wrapSelector()).remove();
         }
     }
 
diff --git a/js/com/component/FileNavigation.js b/js/com/component/FileNavigation.js
index 17d5d963..6b41aad2 100644
--- a/js/com/component/FileNavigation.js
+++ b/js/com/component/FileNavigation.js
@@ -13,8 +13,8 @@
 // [CLASS] FileNavigation
 //============================================================================
 define([
-    'text!vp_base/html/fileNavigation.html!strip',
-    'css!vp_base/css/fileNavigation.css',
+    'text!vp_base/html/component/fileNavigation.html!strip',
+    'css!vp_base/css/component/fileNavigation.css',
     'vp_base/js/com/com_String',
     'vp_base/js/com/com_util',
     'vp_base/js/com/component/Component'
@@ -75,7 +75,7 @@ define([
                 extensions: [],     // extensions list ex) png, jpg, gif
                 multiSelect: false, // multi selection
                 showAll: false,     // show other extension files also
-                finsh: null,        // callback after selection
+                finish: null,        // callback after selection
                 ...this.state
             };
             
@@ -380,7 +380,7 @@ define([
                 if (filePath == '') {
                     filePath = './' + fileName;
                 }
-                that.setSelectedFile(fileName, filePath);
+                that.handleSelectFile(filePath, fileName);
             });
             // bind save cancel event
             $(this.wrapSelector('.vp-filenavi-btn')).on('click', function() {
diff --git a/js/com/component/ModelEditor.js b/js/com/component/ModelEditor.js
index 9b6fa738..2eee09cf 100644
--- a/js/com/component/ModelEditor.js
+++ b/js/com/component/ModelEditor.js
@@ -883,8 +883,13 @@ define([
             });
         }
 
+        /**
+         * Show Model Editor
+         * @param {*} showType all / action / info 
+         */
         show() {
             $(this.wrapSelector()).show();
+
             this.reload();
         }
 
diff --git a/js/com/component/PopupComponent.js b/js/com/component/PopupComponent.js
index 4c5dbac7..036cf448 100644
--- a/js/com/component/PopupComponent.js
+++ b/js/com/component/PopupComponent.js
@@ -13,8 +13,8 @@
 // [CLASS] PopupComponent
 //============================================================================
 define([
-    'text!vp_base/html/popupComponent.html!strip',
-    'css!vp_base/css/popupComponent.css',
+    'text!vp_base/html/component/popupComponent.html!strip',
+    'css!vp_base/css/component/popupComponent.css',
     '../com_util',
     '../com_Const',
     '../com_String',
@@ -251,12 +251,44 @@ define([
             });
             // Toggle operation (minimize)
             $(this.wrapSelector('.vp-popup-toggle')).on('click', function(evt) {
-                // that.toggle();
                 $(that.eventTarget).trigger({
                     type: 'close_option_page',
                     component: that
                 });
             });
+            // Maximize operation
+            $(this.wrapSelector('.vp-popup-maximize')).on('click', function(evt) {
+                // save position
+                that.config.position = $(that.wrapSelector()).position();
+                // save size
+                that.config.size = {
+                    width: $(that.wrapSelector()).width(),
+                    height: $(that.wrapSelector()).height()
+                }
+                // maximize popup
+                $(that.wrapSelector()).css({
+                    width: '100%',
+                    height: '100%',
+                    top: 0,
+                    left: 0
+                });
+                // show / hide buttons
+                $(this).hide();
+                $(that.wrapSelector('.vp-popup-return')).show();
+            });
+            // Return operation
+            $(this.wrapSelector('.vp-popup-return')).on('click', function(evt) {
+                // return size
+                $(that.wrapSelector()).css({
+                    width: that.config.size.width + 'px',
+                    height: that.config.size.height + 'px',
+                    top: that.config.position.top,
+                    left: that.config.position.left
+                });
+                // show / hide buttons
+                $(this).hide();
+                $(that.wrapSelector('.vp-popup-maximize')).show();
+            });
 
             // Click install package
             $(this.wrapSelector('#popupInstall')).on('click', function() {
@@ -270,14 +302,16 @@ define([
             // Click import library
             $(this.wrapSelector('#popupImport')).on('click', function() {
                 // add import codes
-                var code = that.generateImportCode();
-                // create block and run it
-                $('#vp_wrapper').trigger({
-                    type: 'create_option_page', 
-                    blockType: 'block',
-                    menuId: 'lgExe_code',
-                    menuState: { taskState: { code: code } },
-                    afterAction: 'run'
+                var codes = that.generateImportCode();
+                codes && codes.forEach(code => {
+                    // create block and run it
+                    $('#vp_wrapper').trigger({
+                        type: 'create_option_page', 
+                        blockType: 'block',
+                        menuId: 'lgExe_code',
+                        menuState: { taskState: { code: code } },
+                        afterAction: 'run'
+                    });
                 });
             });
 
@@ -297,45 +331,7 @@ define([
 
             // save state values
             $(document).on('change', this.wrapSelector('.vp-state'), function() {
-                let id = $(this)[0].id;
-                let customKey = $(this).data('key');
-                let tagName = $(this).prop('tagName'); // returns with UpperCase
-                let newValue = '';
-                switch(tagName) {
-                    case 'INPUT':
-                        let inputType = $(this).prop('type');
-                        if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') {
-                            newValue = $(this).val();
-                            break;
-                        }
-                        if (inputType == 'checkbox') {
-                            newValue = $(this).prop('checked');
-                            break;
-                        }
-                        break;
-                    case 'TEXTAREA':
-                    case 'SELECT':
-                    default:
-                        newValue = $(this).val();
-                        if (!newValue) {
-                            newValue = '';
-                        }
-                        break;
-                }
-                
-                // if custom key is available, use it
-                if (customKey && customKey != '') {
-                    // allow custom key until level 2
-                    let customKeys = customKey.split('.');
-                    if (customKeys.length == 2) {
-                        that.state[customKeys[0]][customKeys[1]] = newValue;
-                    } else {
-                        that.state[customKey] = newValue;
-                    }
-                } else {
-                    that.state[id] = newValue;
-                }
-                vpLog.display(VP_LOG_TYPE.DEVELOP, 'saved state : ' + id+ '/'+tagName+'/'+newValue);
+                that._saveSingleState($(this)[0]);
             });
 
             // Click buttons
@@ -423,7 +419,7 @@ define([
             });
 
             // click on data selector input filter
-            $(this.wrapSelector('.vp-data-selector ')).on('click', function(evt) {
+            $(this.wrapSelector('.vp-data-selector')).on('click', function(evt) {
 
             });
         }
@@ -458,8 +454,14 @@ define([
         }
 
         _bindResizable() {
+            let that = this;
             $(this.wrapSelector()).resizable({
-                handles: 'all'
+                handles: 'all',
+                start: function(evt, ui) {
+                    // show / hide buttons
+                    $(that.wrapSelector('.vp-popup-return')).hide();
+                    $(that.wrapSelector('.vp-popup-maximize')).show();
+                }
             });
         }
 
@@ -598,7 +600,7 @@ define([
 
         generateImportCode() {
             /** Implementation needed - Generated on clicking Import Library button */
-            return '';
+            return [];
         }
 
         generateCode() {
@@ -618,46 +620,48 @@ define([
             /** Implementation needed */
             let that = this;
             $(this.wrapSelector('.vp-state')).each((idx, tag) => {
-                let id = tag.id;
-                let customKey = $(tag).data('key');
-                let tagName = $(tag).prop('tagName'); // returns with UpperCase
-                let newValue = '';
-                switch(tagName) {
-                    case 'INPUT':
-                        let inputType = $(tag).prop('type');
-                        if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') {
-                            newValue = $(tag).val();
-                            break;
-                        }
-                        if (inputType == 'checkbox') {
-                            newValue = $(tag).prop('checked');
-                            break;
-                        }
-                        break;
-                    case 'TEXTAREA':
-                    case 'SELECT':
-                    default:
-                        newValue = $(tag).val();
-                        if (!newValue) {
-                            newValue = '';
-                        }
-                        break;
-                }
-                
-                // if custom key is available, use it
-                if (customKey && customKey != '') {
-                    // allow custom key until level 2
-                    let customKeys = customKey.split('.');
-                    if (customKeys.length == 2) {
-                        that.state[customKeys[0]][customKeys[1]] = newValue;
+                that._saveSingleState(tag);
+            }); 
+            vpLog.display(VP_LOG_TYPE.DEVELOP, 'savedState', that.state);   
+        }
+
+        _saveSingleState(tag) {
+            let id = tag.id;
+            let customKey = $(tag).data('key');
+            let tagName = $(tag).prop('tagName'); // returns with UpperCase
+            let newValue = '';
+            switch(tagName) {
+                case 'INPUT':
+                    let inputType = $(tag).prop('type');
+                    if (inputType == 'checkbox') {
+                        newValue = $(tag).prop('checked');
                     } else {
-                        that.state[customKey] = newValue;
+                        // inputType == 'text' || inputType == 'number' || inputType == 'hidden' || inputType == 'color' || inputType == 'range'
+                        newValue = $(tag).val();
+                    }
+                    break;
+                case 'TEXTAREA':
+                case 'SELECT':
+                default:
+                    newValue = $(tag).val();
+                    if (!newValue) {
+                        newValue = '';
                     }
+                    break;
+            }
+            
+            // if custom key is available, use it
+            if (customKey && customKey != '') {
+                // allow custom key until level 2
+                let customKeys = customKey.split('.');
+                if (customKeys.length == 2) {
+                    this.state[customKeys[0]][customKeys[1]] = newValue;
                 } else {
-                    that.state[id] = newValue;
+                    this.state[customKey] = newValue;
                 }
-            }); 
-            vpLog.display(VP_LOG_TYPE.DEVELOP, 'savedState', that.state);   
+            } else {
+                this.state[id] = newValue;
+            }
         }
 
         run(execute=true, addcell=true) {
diff --git a/js/com/component/VarSelector2.js b/js/com/component/VarSelector2.js
index 1c80e58c..2decd620 100644
--- a/js/com/component/VarSelector2.js
+++ b/js/com/component/VarSelector2.js
@@ -8,7 +8,7 @@ define([
      * @constructor
      */
      class VarSelector extends Component{
-        constructor(parentTag, dataTypes=[], defaultType='', showOthers=true, showFilterbox=true) {
+        constructor(parentTag, dataTypes=['DataFrame', 'Series', 'ndarray', 'list', 'dict'], defaultType='', showOthers=true, showFilterbox=true) {
             super(null, {parentTag: parentTag, dataTypes: dataTypes, defaultType: defaultType, showOthers: showOthers, showFilterbox: showFilterbox});
         }
 
@@ -234,8 +234,12 @@ define([
                     }
                     
                 }
+            } else {
+                dataTypes = [];
             }
 
+            vpLog.display(VP_LOG_TYPE.DEVELOP, 'VarSelector2 - reload ', dataTypes, excludeTypes);
+
             return new Promise(function(resolve, reject) {
                 vpKernel.getDataList(dataTypes, excludeTypes).then(function (resultObj) {
                     try {
diff --git a/js/m_apps/File.js b/js/m_apps/File.js
index c744627b..a456a6f1 100644
--- a/js/m_apps/File.js
+++ b/js/m_apps/File.js
@@ -270,6 +270,7 @@ define([
             }
     
             // render interface
+            // pdGen.vp_showInterfaceOnPage(this.wrapSelector('#vp_file' + pageType), thisPkg);
             pdGen.vp_showInterfaceOnPage(this.wrapSelector('#vp_file' + pageType), thisPkg);
     
             // prepend file type selector
diff --git a/js/m_apps/PDF.js b/js/m_apps/PDF.js
index 15f3bd78..cac45e19 100644
--- a/js/m_apps/PDF.js
+++ b/js/m_apps/PDF.js
@@ -30,6 +30,37 @@ import fitz
 import nltk
 nltk.download('punkt')`;
 
+    const PDF_FUNC = `def vp_pdf_get_sentence(fname_lst):
+    '''
+    Get sentence from pdf file by PyMuPDF
+    '''
+    df = pd.DataFrame()
+    for fname in fname_lst:
+        if fname.split('.')[-1] != 'pdf': continue
+        try:
+            doc = fitz.open(fname)
+            sentence_lst = []
+            for page in doc:
+                block_lst = page.get_text('blocks')
+        
+                text_lst = [block[4] for block in block_lst if block[6] == 0]
+                text = '\\n'.join(text_lst)
+        
+                sentence_lst.extend([sentence for sentence in nltk.sent_tokenize(text)])
+                
+            doc.close()
+        except Exception as e:
+            print(e)
+            continue
+            
+        df_doc = pd.DataFrame({
+            'fname': fname.split('/')[-1],
+            'sentence': sentence_lst
+        })
+        df = pd.concat([df,df_doc])
+        
+    return df.reset_index().drop('index', axis=1)`;
+
     const PDF_CMD = 'df = vp_pdf_get_sentence(pdf_lst)\ndf'
     /**
      * PDF
@@ -93,7 +124,10 @@ nltk.download('punkt')`;
         }
 
         generateImportCode() {
-            return PDF_IMPORT;
+            return [
+                PDF_IMPORT,
+                PDF_FUNC
+            ];
         }
 
         generateCode() {
diff --git a/js/m_apps/Profiling.js b/js/m_apps/Profiling.js
index 5e82048b..c57442d7 100644
--- a/js/m_apps/Profiling.js
+++ b/js/m_apps/Profiling.js
@@ -147,7 +147,9 @@ define([
         }
 
         generateImportCode() {
-            return 'from pandas_profiling import ProfileReport';
+            return [
+                'from pandas_profiling import ProfileReport'
+            ];
         }
 
         generateCode() {
diff --git a/js/m_apps/SampleApp.js b/js/m_apps/SampleApp.js
index 864678e9..b497c82b 100644
--- a/js/m_apps/SampleApp.js
+++ b/js/m_apps/SampleApp.js
@@ -16,8 +16,9 @@ define([
     'vp_base/js/com/com_util',
     'vp_base/js/com/com_Const',
     'vp_base/js/com/com_String',
-    'vp_base/js/com/component/PopupComponent'
-], function(com_util, com_Const, com_String, PopupComponent) {
+    'vp_base/js/com/component/PopupComponent',
+    'vp_base/js/com/component/DataSelector'
+], function(com_util, com_Const, com_String, PopupComponent, DataSelector) {
 
     /**
      * SampleApp
@@ -32,22 +33,29 @@ define([
             super._bindEvent();
             /** Implement binding events */
             var that = this;
-            this.$target.on('click', function(evt) {
-                var target = evt.target;
-                if ($(that.wrapSelector()).find(target).length > 0) {
-                    // Sample : getDataList from Kernel
-                    vpKernel.getDataList().then(function(resultObj) {
-                        vpLog.display(VP_LOG_TYPE.DEVELOP, resultObj);
-                    }).catch(function(err) {
-                        vpLog.display(VP_LOG_TYPE.DEVELOP, err);
-                    });
-                }
+            
+            $(this.wrapSelector('#sample')).on('click', function() {
+                let dataSelector = new DataSelector({
+                    type: 'data',
+                    target: $(that.wrapSelector('#sample')),
+                    finish: function() {
+                        
+                    }
+                });
+                dataSelector.open();
             });
         }
 
         templateForBody() {
             /** Implement generating template */
-            return 'This is sample.';
+            return `This is sample.
+            <input type="text" id="sample" class="vp-state vp-input" placeholder="Click to edit" readonly="" />`;
+        }
+
+        render() {
+            super.render();
+
+
         }
 
         generateCode() {
diff --git a/js/m_apps/Subset.js b/js/m_apps/Subset.js
index 74ad9cac..6b80f0ac 100644
--- a/js/m_apps/Subset.js
+++ b/js/m_apps/Subset.js
@@ -59,9 +59,7 @@ define([
 
                 useCopy: false,
                 toFrame: false,
-                subsetType: 'loc',
-
-                tabPage: 'subset',
+                subsetType: 'loc', // subset / loc / iloc / query
 
                 rowType: 'condition',
                 rowList: [],
@@ -139,6 +137,21 @@ define([
                 $(this.targetSelector).parent().append(buttonTag.toString());
             }
         }
+        renderSubsetType(dataType) {
+            var subsetType = this.state.subsetType;
+
+            var tag = new com_String();
+            tag.appendFormatLine('<select class="{0} {1}">', VP_DS_SUBSET_TYPE, 'vp-select');
+            tag.appendFormatLine('<option value="{0}" {1}>{2}</option>', 'subset', subsetType == 'subset'?'selected':'', 'subset');
+            tag.appendFormatLine('<option value="{0}" {1}>{2}</option>', 'loc', subsetType == 'loc'?'selected':'', 'loc');
+            tag.appendFormatLine('<option value="{0}" {1}>{2}</option>', 'iloc', subsetType == 'iloc'?'selected':'', 'iloc');
+            if (dataType == 'DataFrame') {
+                tag.appendFormatLine('<option value="{0}" {1}>{2}</option>', 'query', subsetType == 'query'?'selected':'', 'query');
+            }
+            tag.appendLine('</select>');
+
+            return tag.toString();
+        }
         renderRowSubsetType(subsetType, timestamp = false) {
             var tag = new com_String();
             tag.appendFormatLine('<select class="{0} {1}">', VP_DS_ROWTYPE, 'vp-select m');
@@ -146,7 +159,7 @@ define([
                 tag.appendFormatLine('<option value="{0}">{1}</option>', 'indexing', 'Indexing');
             }
             tag.appendFormatLine('<option value="{0}">{1}</option>', 'slicing', 'Slicing');
-            if (subsetType == 'subset' || subsetType == 'loc') {
+            if (subsetType == 'subset' || subsetType == 'loc' || subsetType == 'query') {
                 tag.appendFormatLine('<option value="{0}">{1}</option>', 'condition', 'Condition');
             }
             if ((subsetType == 'subset' || subsetType == 'loc') && timestamp) {
@@ -198,7 +211,7 @@ define([
             vpSearchSuggest.setNormalFilter(true);
             tag.appendLine(vpSearchSuggest.toTagString());
 
-            tag.appendFormatLine('<div class="{0} {1} {2} {3}"></div>', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'no-selection');
+            tag.appendFormatLine('<div class="{0} {1} {2} {3}"></div>', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'vp-scrollbar no-selection');
             tag.appendLine('</div>'); // VP_DS_SELECT_LEFT
 
             // row select - buttons
@@ -213,7 +226,7 @@ define([
 
             // row select - right
             tag.appendFormatLine('<div class="{0}">', VP_DS_SELECT_RIGHT);
-            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'right', VP_DS_DROPPABLE, 'no-selection');
+            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'right', VP_DS_DROPPABLE, 'vp-scrollbar no-selection');
             tag.appendLine('</div>'); // VP_DS_SELECT_BOX
             tag.appendLine('</div>'); // VP_DS_SELECT_RIGHT
             tag.appendLine('</div>'); // VP_DS_SELECT_CONTAINER
@@ -229,7 +242,7 @@ define([
          */
         renderRowSelectionBox(rowList) {
             var tag = new com_String();
-            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'no-selection');
+            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'vp-scrollbar no-selection');
 
             // get row data and make draggable items
             rowList.forEach((row, idx) => {
@@ -313,7 +326,7 @@ define([
             tag.appendLine(vpSearchSuggest.toTagString());
             tag.appendFormatLine('<i class="fa fa-search search-icon"></i>');
 
-            tag.appendFormatLine('<div class="{0} {1} {2} {3}"></div>', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'no-selection');
+            tag.appendFormatLine('<div class="{0} {1} {2} {3}"></div>', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'vp-scrollbar no-selection');
             tag.appendLine('</div>'); // VP_DS_SELECT_LEFT
 
             // col select - buttons
@@ -328,7 +341,7 @@ define([
 
             // col select - right
             tag.appendFormatLine('<div class="{0}">', VP_DS_SELECT_RIGHT);
-            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'right', VP_DS_DROPPABLE, 'no-selection');
+            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'right', VP_DS_DROPPABLE, 'vp-scrollbar no-selection');
             tag.appendLine('</div>'); // VP_DS_SELECT_BOX
             tag.appendLine('</div>'); // VP_DS_SELECT_RIGHT
             tag.appendLine('</div>'); // VP_DS_SELECT_CONTAINER
@@ -344,7 +357,7 @@ define([
          */
         renderColumnSelectionBox(colList) {
             var tag = new com_String();
-            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'no-selection');
+            tag.appendFormatLine('<div class="{0} {1} {2} {3}">', VP_DS_SELECT_BOX, 'left', VP_DS_DROPPABLE, 'vp-scrollbar no-selection');
             // get col data and make draggable items
             colList.forEach((col, idx) => {
                 // col.array parsing
@@ -638,12 +651,18 @@ define([
                 return that.renderSubsetType(dataType);
             });
         }
+        /**
+         * Load Row & Column option page based on subsetType
+         * @param {string} subsetType subset / loc / iloc / query
+         * @param {boolean} timestamp use timestamp? true / false
+         */
         loadRowColumnSubsetType(subsetType, timestamp = false) {
             var that = this;
             // get current subset type of row & column
             var rowSubset = this.state.rowType;
             var colSubset = this.state.colType;
 
+            // render row & column option page
             that.renderRowSubsetType(subsetType, timestamp);
             that.renderColumnSubsetType(subsetType);
 
@@ -997,7 +1016,7 @@ define([
                     return;
                 }
 
-                // that.loadSubsetType(that.state.dataType);
+                that.loadSubsetType(that.state.dataType);
                 if (that.state.dataType == 'DataFrame') {
                     // get result and load column list
                     vpKernel.getColumnList(varName).then(function (resultObj) {
@@ -1073,13 +1092,6 @@ define([
                 that.state.subsetType = subsetType;
 
                 that.reloadSubsetData();
-                // that.loadRowColumnSubsetType(subsetType, that.state.isTimestamp);
-                // // data page
-                // if (that.state.tabPage == 'data') {
-                //     that.loadDataPage();
-                // } else {
-                //     that.generateCode();
-                // }
             });
 
             // to frame
@@ -1398,6 +1410,7 @@ define([
          *  1) subset - rowSelection & colSelection using 'indexing' type
          *  2) loc - subset type 'loc'
          *  3) iloc - subset type 'iloc'
+         *  4) query - subset type 'query'
          * - consider use copy option
          */
         generateCodeForSubset(allocation = true, applyPreview = true) {
@@ -1461,13 +1474,16 @@ define([
                         rowSelection.append(connector);
                     }
 
-                    if (varType == 'DataFrame') {
-                        rowSelection.appendFormat('({0}', varName);
-                        if (colName && colName != '') {
-                            if (colName == '.index') {
-                                rowSelection.appendFormat('{0}', colName);
+                    if (this.state.subsetType == 'query') {
+                        if (condList.length > 1) {
+                            rowSelection.append('(');
+                        }
+                        let colValue = colTag.find('.vp-col-list').val();
+                        if (colValue && colValue != '') {
+                            if (colValue == '.index') {
+                                rowSelection.append('index');
                             } else {
-                                rowSelection.appendFormat('[{0}]', colName);
+                                rowSelection.appendFormat('{0}', colValue);
                             }
                         }
                         oper && rowSelection.appendFormat(' {0}', oper);
@@ -1479,23 +1495,45 @@ define([
                                 rowSelection.appendFormat(" {0}", cond);
                             }
                         }
-                        rowSelection.append(')');
+                        if (condList.length > 1) {
+                            rowSelection.append(')');
+                        }
                     } else {
-                        rowSelection.appendFormat('({0}', varName);
-                        oper && rowSelection.appendFormat(' {0}', oper);
-                        if (cond) {
-                            // condition value as text
-                            if (useText) {
-                                rowSelection.appendFormat(" '{0}'", cond);
-                            } else {
-                                rowSelection.appendFormat(" {0}", cond);
+                        if (varType == 'DataFrame') {
+                            rowSelection.appendFormat('({0}', varName);
+                            if (colName && colName != '') {
+                                if (colName == '.index') {
+                                    rowSelection.appendFormat('{0}', colName);
+                                } else {
+                                    rowSelection.appendFormat('[{0}]', colName);
+                                }
+                            }
+                            oper && rowSelection.appendFormat(' {0}', oper);
+                            if (cond) {
+                                // condition value as text
+                                if (useText) {
+                                    rowSelection.appendFormat(" '{0}'", cond);
+                                } else {
+                                    rowSelection.appendFormat(" {0}", cond);
+                                }
+                            }
+                            rowSelection.append(')');
+                        } else {
+                            rowSelection.appendFormat('({0}', varName);
+                            oper && rowSelection.appendFormat(' {0}', oper);
+                            if (cond) {
+                                // condition value as text
+                                if (useText) {
+                                    rowSelection.appendFormat(" '{0}'", cond);
+                                } else {
+                                    rowSelection.appendFormat(" {0}", cond);
+                                }
                             }
+                            rowSelection.append(')');
                         }
-                        rowSelection.append(')');
                     }
                     useCondition = true;
                 }
-
                 if (rowSelection.toString() == '') {
                     rowSelection.append(':');
                 }
@@ -1572,6 +1610,13 @@ define([
                 } else {
                     code.appendFormat('.iloc[{0}]', rowSelection.toString());
                 }
+            } else if (this.state.subsetType == 'query') {
+                if (rowSelection.toString() != ':' && rowSelection.toString() != '') {
+                    code.appendFormat('.query("{0}")', rowSelection.toString());
+                }
+                if (colSelection.toString() != ':' && colSelection.toString() != '') {
+                    code.appendFormat('[{0}]', colSelection.toString());
+                }
             }
 
             // use copy
diff --git a/js/m_apps/Variable.js b/js/m_apps/Variable.js
index 09c42b80..6d0e175a 100644
--- a/js/m_apps/Variable.js
+++ b/js/m_apps/Variable.js
@@ -66,20 +66,9 @@ define([
     
             // Searchable variable types
             var types = [
-                // pandas object
-                'DataFrame', 'Series', 'Index', 'Period', 'GroupBy', 'Timestamp'
-                // Index type object
-                , 'RangeIndex', 'CategoricalIndex', 'MultiIndex', 'IntervalIndex', 'DatetimeIndex', 'TimedeltaIndex', 'PeriodIndex', 'Int64Index', 'UInt64Index', 'Float64Index'
-                // GroupBy type object
-                , 'DataFrameGroupBy', 'SeriesGroupBy'
-                // Plot type
-                , 'Figure', 'AxesSubplot'
-                // Numpy
-                , 'ndarray'
-                // Python variable
-                , 'str', 'int', 'float', 'bool', 'dict', 'list', 'tuple'
+                ...vpConfig.getDataTypes(),
                 // ML Data types
-                , ...vpConfig.getMLDataTypes()
+                ...vpConfig.getMLDataTypes()
             ];
     
             var tagTable = this.wrapSelector('#vp_var_variableBox table tbody');
diff --git a/js/m_ml/AutoML.js b/js/m_ml/AutoML.js
index 614c82cf..88d2b4d7 100644
--- a/js/m_ml/AutoML.js
+++ b/js/m_ml/AutoML.js
@@ -138,13 +138,13 @@ define([
             // render option page
             $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
 
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
diff --git a/js/m_ml/Classification.js b/js/m_ml/Classification.js
index b8aa9529..b53d5257 100644
--- a/js/m_ml/Classification.js
+++ b/js/m_ml/Classification.js
@@ -138,13 +138,13 @@ define([
             // render option page
             $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
 
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
diff --git a/js/m_ml/Clustering.js b/js/m_ml/Clustering.js
index efc469c0..a636bfc5 100644
--- a/js/m_ml/Clustering.js
+++ b/js/m_ml/Clustering.js
@@ -141,13 +141,13 @@ define([
             // render option page
             $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
 
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
diff --git a/js/m_ml/DataPrep.js b/js/m_ml/DataPrep.js
index 32f8a36f..0cc70917 100644
--- a/js/m_ml/DataPrep.js
+++ b/js/m_ml/DataPrep.js
@@ -197,13 +197,13 @@ define([
             // render option page
             $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
 
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
diff --git a/js/m_ml/DimensionReduction.js b/js/m_ml/DimensionReduction.js
index 642f12c9..f11a82b9 100644
--- a/js/m_ml/DimensionReduction.js
+++ b/js/m_ml/DimensionReduction.js
@@ -137,13 +137,13 @@ define([
             // render option page
             $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
 
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
diff --git a/js/m_ml/FitPredict.js b/js/m_ml/FitPredict.js
new file mode 100644
index 00000000..b6afc1ef
--- /dev/null
+++ b/js/m_ml/FitPredict.js
@@ -0,0 +1,692 @@
+/*
+ *    Project Name    : Visual Python
+ *    Description     : GUI-based Python code generator
+ *    File Name       : FitPredict.js
+ *    Author          : Black Logic
+ *    Note            : Model fit / predict
+ *    License         : GNU GPLv3 with Visual Python special exception
+ *    Date            : 2022. 04. 20
+ *    Change Date     :
+ */
+
+//============================================================================
+// [CLASS] FitPredict
+//============================================================================
+define([
+    'text!vp_base/html/m_ml/fitPredict.html!strip',
+    'css!vp_base/css/m_ml/fitPredict.css',
+    'vp_base/js/com/com_util',
+    'vp_base/js/com/com_String',
+    'vp_base/js/com/com_generatorV2',
+    'vp_base/data/m_ml/mlLibrary',
+    'vp_base/js/com/component/PopupComponent',
+    'vp_base/js/com/component/VarSelector2',
+    'vp_base/js/com/component/SuggestInput'
+], function(msHtml, msCss, com_util, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, SuggestInput) {
+
+    /**
+     * FitPredict
+     */
+    class FitPredict extends PopupComponent {
+        _init() {
+            super._init();
+            this.config.sizeLevel = 2;
+            this.config.dataview = false;
+
+            this.state = {
+                // model selection
+                category: 'All',
+                model: '',
+                modelType: '',
+                method: '',
+                action: {},
+                optionConfig: {},
+                userOption: '',
+                ...this.state
+            }
+
+            // categories : Data Preparation / Regression / Classification / Clustering / Dimension Reduction / Auto ML
+            this.modelCategories = [
+                'All',
+                ...vpConfig.getMLCategories()
+            ]
+
+            this.modelConfig = ML_LIBRARIES;
+
+            this.loaded = false;
+
+        }
+
+        _bindEvent() {
+            super._bindEvent();
+            /** Implement binding events */
+            var that = this;
+        
+            // click category
+            $(this.wrapSelector('.vp-ins-select-list.category .vp-ins-select-item')).on('click', function() {
+                let category = $(this).data('var-name');
+
+                that.state.category = category;
+
+                $(that.wrapSelector('.vp-ins-select-list.category .vp-ins-select-item')).removeClass('selected');
+                $(this).addClass('selected');
+
+                // load model list for this category
+                that.loadModelList(category);
+            });
+        }
+
+        templateForBody() {
+            let page = $(msHtml);
+            
+            let that = this;
+
+            //================================================================
+            // Model selection
+            //================================================================
+            // set model category list
+            let modelCategoryTag = new com_String();
+            this.modelCategories.forEach(category => {
+                let selected = '';
+                if (category == that.state.category) {
+                    selected = 'selected';
+                }
+                modelCategoryTag.appendFormatLine('<li class="{0} {1}" data-var-name="{2}" data-var-type="{3}" title="{4}">{5}</li>',
+                'vp-ins-select-item', selected, category, 'category', category, category);
+            });
+            $(page).find('.vp-ins-select-list.category').html(modelCategoryTag.toString());
+
+            //================================================================
+            // Load state
+            //================================================================
+            Object.keys(this.state).forEach(key => {
+                let tag = $(page).find('#' + key);
+                let tagName = $(tag).prop('tagName'); // returns with UpperCase
+                let value = that.state[key];
+                if (value == undefined) {
+                    return;
+                }
+                switch(tagName) {
+                    case 'INPUT':
+                        let inputType = $(tag).prop('type');
+                        if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') {
+                            $(tag).val(value);
+                            break;
+                        }
+                        if (inputType == 'checkbox') {
+                            $(tag).prop('checked', value);
+                            break;
+                        }
+                        break;
+                    case 'TEXTAREA':
+                    case 'SELECT':
+                    default:
+                        $(tag).val(value);
+                        break;
+                }
+            });
+
+            return page;
+        }
+
+        templateForOption(modelType) {
+            let optionConfig = this.modelConfig[modelType];
+            let state = this.state;
+
+            let optBox = new com_String();
+            // render tag
+            optionConfig.options.forEach(opt => {
+                optBox.appendFormatLine('<label for="{0}" title="{1}">{2}</label>'
+                    , opt.name, opt.name, com_util.optionToLabel(opt.name));
+                let content = com_generator.renderContent(this, opt.component[0], opt, state);
+                optBox.appendLine(content[0].outerHTML);
+            });
+            // render user option
+            optBox.appendFormatLine('<label for="{0}">{1}</label>', 'userOption', 'User option');
+            optBox.appendFormatLine('<input type="text" class="vp-input vp-state" id="{0}" placeholder="{1}" value="{2}"/>',
+                                        'userOption', 'key=value, ...', this.state.userOption);
+            return optBox.toString();
+        }
+
+        render() {
+            super.render();
+
+            this.loadModelList(this.state.category);
+        }
+
+        loadModelList(category='') {
+            // reset page
+            try {
+                $(this.wrapSelector('.vp-ins-search')).autocomplete("destroy");
+            } catch { ; }
+            $(this.wrapSelector('.vp-ins-select-list.action')).html('');
+            $(this.wrapSelector('.vp-ins-parameter-box')).html('');
+
+            if (category == 'All') {
+                category = '';
+            }
+            // set model list
+            let that = this;
+            let modelOptionTag = new com_String();
+            vpKernel.getModelList(category).then(function(resultObj) {
+                let { result } = resultObj;
+                var modelList = JSON.parse(result);
+                modelList && modelList.forEach((model, idx) => {
+                    let selectFlag = '';
+                    // if this item is pre-selected model or first item of model list
+                    if ((model.varName == that.state.model)
+                        || (that.state.model == '' && idx == 0)) {
+                        selectFlag = 'selected';
+                        that.state.model = model.varName;
+                        that.state.modelType = model.varType;
+                    }
+                    modelOptionTag.appendFormatLine('<li class="{0} {1}" data-var-name="{2}" data-var-type="{3}" title="{4}">{5} ({6})</li>',
+                    'vp-ins-select-item', selectFlag, model.varName, model.varType, model.varName, model.varName, model.varType);
+                });
+                $(that.wrapSelector('.vp-ins-select-list.model')).html(modelOptionTag.toString());
+
+                // click model event
+                $(that.wrapSelector('.vp-ins-select-list.model .vp-ins-select-item')).on('click', function() {
+                    let model = $(this).data('var-name');
+                    let modelType = $(this).data('var-type');
+
+                    that.state.model = model;
+                    that.state.modelType = modelType;
+                    
+                    $(that.wrapSelector('.vp-ins-select-list.model .vp-ins-select-item')).removeClass('selected');
+                    $(this).addClass('selected');
+
+                    that.reload();
+                });
+
+                that.reload();
+            });
+        }
+
+        /**
+         * Load options for selected model
+         */
+        reload() {
+            // reset option page
+            try {
+                $(this.wrapSelector('.vp-ins-search')).autocomplete("destroy");
+            } catch { ; }
+            $(this.wrapSelector('.vp-ins-select-list.action')).html('');
+            $(this.wrapSelector('.vp-ins-parameter-box')).html('');
+            
+            let model = this.state.model;
+            let modelType = this.state.modelType;
+            
+            let actions = this.getAction(modelType);
+            this.state.action = { ...actions };
+            
+            var actListTag = new com_String();
+            
+            Object.keys(actions).forEach(actKey => {
+                let titleText = actions[actKey].description;
+                if (actions[actKey].name != actions[actKey].label) {   
+                    titleText = actions[actKey].name + ': ' + titleText;
+                }
+                actListTag.appendFormatLine('<li class="{0}" data-var-name="{1}" data-var-type="{2}" title="{3}">{4}</li>',
+                'vp-ins-select-item', actKey, 'action', titleText, actions[actKey].label);
+            });
+            
+            $(this.wrapSelector('.vp-ins-select-list.action')).html(actListTag.toString());
+            
+            let that = this;
+            // action search suggest
+            var suggestInput = new SuggestInput();
+            suggestInput.addClass('vp-input');
+            suggestInput.addClass('vp-ins-search');
+            suggestInput.setPlaceholder("Search Action");
+            suggestInput.setSuggestList(function () { return Object.keys(actions); });
+            suggestInput.setSelectEvent(function (value, item) {
+                $(this.wrapSelector()).val(value);
+                $(that.wrapSelector('.vp-ins-type.action')).val(value);
+
+                $(that.wrapSelector('.vp-ins-select-item[data-var-name="' + value + '"]')).click();
+            });
+            $(that.wrapSelector('.vp-ins-search')).replaceWith(function () {
+                return suggestInput.toTagString();
+            });
+
+            // bind event
+            // click option
+            $(this.wrapSelector('.vp-ins-select-list.action .vp-ins-select-item')).on('click', function() {
+                let name = $(this).data('var-name');
+                let type = $(this).data('var-type');
+                
+                that.renderOptionPage(type, name);
+            });
+
+            // load once on initializing page
+            if (this.loaded == false) {
+                let { modelEditorType, modelEditorName } = this.state;
+                if (modelEditorType != '' && modelEditorName != '') {
+                    // render option page for saved state
+                    that.renderOptionPage(modelEditorType, modelEditorName);
+                }
+                // set loaded true
+                this.loaded = true;
+            }
+        }
+
+        /**
+         * Render option page for selected option
+         * @param {String} type action / info
+         * @param {String} name option name (ex. fit/predict/...)
+         */
+        renderOptionPage(type, name) {
+            if (this.state[type] != undefined && this.state[type][name] != undefined) {
+                let optionConfig = this.state[type][name];
+                let optBox = new com_String();
+                // render tag
+                optionConfig && optionConfig.options && optionConfig.options.forEach(opt => {
+                    let label = opt.name;
+                    if (opt.label != undefined) {
+                        label = opt.label;
+                    }
+                    // fix label
+                    label = com_util.optionToLabel(label);
+                    optBox.appendFormatLine('<label for="{0}" title="{1}">{2}</label>'
+                        , opt.name, opt.name, label);
+                    let content = com_generator.renderContent(this, opt.component[0], opt, this.state);
+                    optBox.appendLine(content[0].outerHTML);
+                });
+                // replace option box
+                $(this.wrapSelector('.vp-ins-parameter-box')).html(optBox.toString());
+    
+                this.state.optionConfig = optionConfig;
+    
+                // add selection
+                let typeClass = '.vp-ins-select-list.' + type;
+                let nameClass = '.vp-ins-select-item[data-var-name="' + name + '"]';
+                $(this.wrapSelector(typeClass + ' ' + '.vp-ins-select-item')).removeClass('selected');
+                $(this.wrapSelector(typeClass + ' ' + nameClass)).addClass('selected');
+                // set state
+                $(this.wrapSelector('#modelEditorType')).val(type);
+                $(this.wrapSelector('#modelEditorName')).val(name);
+                this.state.modelEditorType = type;
+                this.state.modelEditorName = name;
+            }
+        }
+
+        generateCode() {
+            let { model } = this.state;
+            let code = new com_String();
+            let replaceDict = {'${model}': model};
+
+            if (this.state.optionConfig.import != undefined) {
+                code.appendLine(this.state.optionConfig.import);
+                code.appendLine();
+            }
+            let modelCode = com_generator.vp_codeGenerator(this, this.state.optionConfig, this.state);
+            if (modelCode) {
+                Object.keys(replaceDict).forEach(key => {
+                    modelCode = modelCode.replace(key, replaceDict[key]);
+                });
+                code.append(modelCode);
+    
+                let allocateIdx = modelCode.indexOf(' = ');
+                if (allocateIdx >= 0) {
+                    let allocateCode = modelCode.substr(0, allocateIdx);
+                    code.appendLine();
+                    code.append(allocateCode);
+                }
+            }
+
+            return code.toString();
+        }
+
+        getModelCategory(modelType) {
+            let mlDict = vpConfig.getMLDataDict();
+            let keys = Object.keys(mlDict);
+            let modelCategory = '';
+            for (let i = 0; i < keys.length; i++) {
+                let key = keys[i];
+                if (mlDict[key].includes(modelType)) {
+                    modelCategory = key;
+                    break;
+                }
+            }
+            return modelCategory;
+        }
+
+        getAction(modelType) {
+            let category = this.getModelCategory(modelType);
+            let defaultActions = {
+                'fit': {
+                    name: 'fit',
+                    label: 'Fit',
+                    code: '${model}.fit(${fit_featureData}, ${fit_targetData})',
+                    description: 'Perform modeling from features, or distance matrix.',
+                    options: [
+                        { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X_train' },
+                        { name: 'fit_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y_train' }
+                    ]
+                },
+                'predict': {
+                    name: 'predict',
+                    label: 'Predict',
+                    code: '${pred_allocate} = ${model}.predict(${pred_featureData})',
+                    description: 'Predict the closest target data X belongs to.',
+                    options: [
+                        { name: 'pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X_test' },
+                        { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                    ]
+                },
+                'predict_proba': {
+                    name: 'predict_proba',
+                    label: 'Predict probability',
+                    code: '${pred_prob_allocate} = ${model}.predict_proba(${pred_prob_featureData})',
+                    description: 'Predict class probabilities for X.',
+                    options: [
+                        { name: 'pred_prob_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X_test' },
+                        { name: 'pred_prob_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                    ]
+                },
+                'transform': {
+                    name: 'transform',
+                    label: 'Transform',
+                    code: '${trans_allocate} = ${model}.transform(${trans_featureData})',
+                    description: 'Apply dimensionality reduction to X.',
+                    options: [
+                        { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                        { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                    ]
+                }
+            };
+            let actions = {};
+            switch (category) {
+                case 'Data Preparation':
+                    actions = {
+                        'fit': {
+                            name: 'fit',
+                            label: 'Fit',
+                            code: '${model}.fit(${fit_featureData})',
+                            description: 'Fit Encoder/Scaler to X.',
+                            options: [
+                                { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }
+                            ]
+                        },
+                        'fit_transform': {
+                            name: 'fit_transform',
+                            label: 'Fit and transform',
+                            code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})',
+                            description: 'Fit Encoder/Scaler to X, then transform X.',
+                            options: [
+                                { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                            ]
+                        },
+                        'transform': {
+                            ...defaultActions['transform'],
+                            description: 'Transform labels to normalized encoding.'
+                        }
+                    }
+
+                    if (modelType != 'ColumnTransformer') {
+                        actions = {
+                            ...actions,
+                            'inverse_transform': {
+                                name: 'inverse_transform',
+                                label: 'Inverse transform',
+                                code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})',
+                                description: 'Transform binary labels back to multi-class labels.',
+                                options: [
+                                    { name: 'inverse_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' }
+                                ]
+                            }
+                        }
+                    }
+                    break;
+                case 'Regression':
+                    actions = {
+                        'fit': defaultActions['fit'],
+                        'predict': defaultActions['predict']
+                    }
+                    break;
+                case 'Classification':
+                    actions = {
+                        'fit': defaultActions['fit'],
+                        'predict': defaultActions['predict'],
+                        'predict_proba': defaultActions['predict_proba'],
+                    }
+                    if (['LogisticRegression', 'SVC', 'GradientBoostingClassifier'].includes(modelType)) {
+                        actions = {
+                            ...actions,
+                            'decision_function': {
+                                name: 'decision_function',
+                                label: 'Decision function',
+                                code: '${dec_allocate} = ${model}.decision_function(${dec_featureData})',
+                                description: 'Compute the decision function of X.',
+                                options: [
+                                    { name: 'dec_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'dec_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable' }
+                                ]
+                            }
+                        }
+                    }
+                    break;
+                case 'Auto ML':
+                    actions = {
+                        'fit': defaultActions['fit'],
+                        'predict': defaultActions['predict'],
+                        'fit_predict': {
+                            name: 'fit_predict',
+                            label: 'Fit and predict',
+                            code: '${fit_pred_allocate} = ${model}.fit_predict(${fit_pred_featureData})',
+                            description: 'Fit and predict.',
+                            options: [
+                                { name: 'fit_pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'fit_pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                            ]
+                        },
+                        'predict_proba': defaultActions['predict_proba']
+                    }
+                    break;
+                case 'Clustering':
+                    if (modelType == 'AgglomerativeClustering' 
+                        || modelType == 'DBSCAN') {
+                        actions = {
+                            'fit': {
+                                name: 'fit',
+                                label: 'Fit',
+                                code: '${model}.fit(${fit_featureData})',
+                                description: 'Perform clustering from features, or distance matrix.',
+                                options: [
+                                    { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }
+                                ]
+                            },
+                            'fit_predict': {
+                                name: 'fit_predict',
+                                label: 'Fit and predict',
+                                code: '${fit_pred_allocate} = ${model}.fit_predict(${fit_pred_featureData})',
+                                description: 'Compute clusters from a data or distance matrix and predict labels.',
+                                options: [
+                                    { name: 'fit_pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'fit_pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                                ]
+                            }
+                        }
+                        break;
+                    }
+                    actions = {
+                        'fit': {
+                            name: 'fit',
+                            label: 'Fit',
+                            code: '${model}.fit(${fit_featureData})',
+                            description: 'Compute clustering.',
+                            options: [
+                                { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }
+                            ]
+                        },
+                        'predict': {
+                            name: 'predict',
+                            label: 'Predict',
+                            code: '${pred_allocate} = ${model}.predict(${pred_featureData})',
+                            description: 'Predict the closest target data X belongs to.',
+                            options: [
+                                { name: 'pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                            ]
+                        },
+                        'fit_predict': {
+                            name: 'fit_predict',
+                            label: 'Fit and predict',
+                            code: '${fit_pred_allocate} = ${model}.fit_predict(${fit_pred_featureData})',
+                            description: 'Compute cluster centers and predict cluster index for each sample.',
+                            options: [
+                                { name: 'fit_pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'fit_pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                            ]
+                        }
+                    }
+                    if (modelType == 'KMeans') {
+                        actions = {
+                            ...actions,
+                            'fit_transform': {
+                                name: 'fit_transform',
+                                label: 'Fit and transform',
+                                code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})',
+                                description: 'Compute clustering and transform X to cluster-distance space.', 
+                                options: [
+                                    { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                                ]
+                            },
+                            'transform': {
+                                name: 'transform',
+                                label: 'Transform',
+                                code: '${trans_allocate} = ${model}.transform(${trans_featureData})',
+                                description: 'Transform X to a cluster-distance space.',
+                                options: [
+                                    { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                                ]
+                            }
+                        }
+                    }
+                    break;
+                case 'Dimension Reduction':
+                    if (modelType == 'TSNE') {
+                        actions = {
+                            'fit': {
+                                name: 'fit',
+                                label: 'Fit',
+                                code: '${model}.fit(${fit_featureData})',
+                                description: 'Fit X into an embedded space.',
+                                options: [
+                                    { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }
+                                ]
+                            },
+                            'fit_transform': {
+                                name: 'fit_transform',
+                                label: 'Fit and transform',
+                                code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})',
+                                description: 'Fit X into an embedded space and return that transformed output.', 
+                                options: [
+                                    { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                                ]
+                            }
+                        }
+                        break;
+                    }
+                    if (modelType == 'LinearDiscriminantAnalysis') { // LDA
+                        actions = {
+                            'fit': {
+                                name: 'fit',
+                                label: 'Fit',
+                                code: '${model}.fit(${fit_featureData}, ${fit_targetData})',
+                                description: 'Fit the Linear Discriminant Analysis model.',
+                                options: [
+                                    { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'fit_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' }
+                                ]
+                            },
+                            'fit_transform': {
+                                name: 'fit_transform',
+                                label: 'Fit and transform',
+                                code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData}${fit_trans_targetData})',
+                                description: 'Fit to data, then transform it.', 
+                                options: [
+                                    { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'fit_trans_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' },
+                                    { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                                ]
+                            },
+                            'predict': {
+                                name: 'predict',
+                                label: 'Predict',
+                                code: '${pred_allocate} = ${model}.predict(${pred_featureData})',
+                                description: 'Predict class labels for samples in X.',
+                                options: [
+                                    { name: 'pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' }
+                                ]
+                            },
+                            'transform': {
+                                name: 'transform',
+                                label: 'Transform',
+                                code: '${trans_allocate} = ${model}.transform(${trans_featureData})',
+                                description: 'Project data to maximize class separation.',
+                                options: [
+                                    { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                                ]
+                            }
+                        }
+                        break;
+                    }
+                    actions = {
+                        'fit': {
+                            name: 'fit',
+                            label: 'Fit',
+                            code: '${model}.fit(${fit_featureData})',
+                            description: 'Fit X into an embedded space.',
+                            options: [
+                                { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }
+                            ]
+                        },
+                        'fit_transform': {
+                            name: 'fit_transform',
+                            label: 'Fit and transform',
+                            code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})',
+                            description: 'Fit the model with X and apply the dimensionality reduction on X.', 
+                            options: [
+                                { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                            ]
+                        },
+                        'inverse_transform': {
+                            name: 'inverse_transform',
+                            label: 'Inverse transform',
+                            code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})',
+                            description: 'Transform data back to its original space.',
+                            options: [
+                                { name: 'inverse_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' }
+                            ]
+                        },
+                        'transform': {
+                            name: 'transform',
+                            label: 'Transform',
+                            code: '${trans_allocate} = ${model}.transform(${trans_featureData})',
+                            description: 'Apply dimensionality reduction to X.',
+                            options: [
+                                { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' }
+                            ]
+                        }
+                    }
+                    break;
+            }
+            return actions;
+        }
+
+    }
+
+    return FitPredict;
+});
\ No newline at end of file
diff --git a/js/m_ml/ModelInfo.js b/js/m_ml/ModelInfo.js
new file mode 100644
index 00000000..97d06a99
--- /dev/null
+++ b/js/m_ml/ModelInfo.js
@@ -0,0 +1,709 @@
+/*
+ *    Project Name    : Visual Python
+ *    Description     : GUI-based Python code generator
+ *    File Name       : ModelInfo.js
+ *    Author          : Black Logic
+ *    Note            : Model information
+ *    License         : GNU GPLv3 with Visual Python special exception
+ *    Date            : 2022. 04. 20
+ *    Change Date     :
+ */
+
+//============================================================================
+// [CLASS] ModelInfo
+//============================================================================
+define([
+    'text!vp_base/html/m_ml/modelInfo.html!strip',
+    'css!vp_base/css/m_ml/modelInfo.css',
+    'vp_base/js/com/com_util',
+    'vp_base/js/com/com_String',
+    'vp_base/js/com/com_generatorV2',
+    'vp_base/data/m_ml/mlLibrary',
+    'vp_base/js/com/component/PopupComponent',
+    'vp_base/js/com/component/VarSelector2',
+    'vp_base/js/com/component/SuggestInput'
+], function(msHtml, msCss, com_util, com_String, com_generator, ML_LIBRARIES, PopupComponent, VarSelector2, SuggestInput) {
+
+    /**
+     * ModelInfo
+     */
+    class ModelInfo extends PopupComponent {
+        _init() {
+            super._init();
+            this.config.sizeLevel = 2;
+            this.config.dataview = false;
+
+            this.state = {
+                // model selection
+                category: 'All',
+                model: '',
+                modelType: '',
+                method: '',
+                info: {},
+                optionConfig: {},
+                userOption: '',
+                ...this.state
+            }
+
+            // categories : Data Preparation / Regression / Classification / Clustering / Dimension Reduction / Auto ML
+            this.modelCategories = [
+                'All',
+                ...vpConfig.getMLCategories()
+            ]
+
+            this.modelConfig = ML_LIBRARIES;
+
+            this.loaded = false;
+
+        }
+
+        _bindEvent() {
+            super._bindEvent();
+            /** Implement binding events */
+            var that = this;
+        
+            // click category
+            $(this.wrapSelector('.vp-ins-select-list.category .vp-ins-select-item')).on('click', function() {
+                let category = $(this).data('var-name');
+
+                that.state.category = category;
+
+                $(that.wrapSelector('.vp-ins-select-list.category .vp-ins-select-item')).removeClass('selected');
+                $(this).addClass('selected');
+
+                // load model list for this category
+                that.loadModelList(category);
+            });
+        }
+
+        templateForBody() {
+            let page = $(msHtml);
+            
+            let that = this;
+
+            //================================================================
+            // Model selection
+            //================================================================
+            // set model category list
+            let modelCategoryTag = new com_String();
+            this.modelCategories.forEach(category => {
+                let selected = '';
+                if (category == that.state.category) {
+                    selected = 'selected';
+                }
+                modelCategoryTag.appendFormatLine('<li class="{0} {1}" data-var-name="{2}" data-var-type="{3}" title="{4}">{5}</li>',
+                'vp-ins-select-item', selected, category, 'category', category, category);
+            });
+            $(page).find('.vp-ins-select-list.category').html(modelCategoryTag.toString());
+
+            //================================================================
+            // Load state
+            //================================================================
+            Object.keys(this.state).forEach(key => {
+                let tag = $(page).find('#' + key);
+                let tagName = $(tag).prop('tagName'); // returns with UpperCase
+                let value = that.state[key];
+                if (value == undefined) {
+                    return;
+                }
+                switch(tagName) {
+                    case 'INPUT':
+                        let inputType = $(tag).prop('type');
+                        if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') {
+                            $(tag).val(value);
+                            break;
+                        }
+                        if (inputType == 'checkbox') {
+                            $(tag).prop('checked', value);
+                            break;
+                        }
+                        break;
+                    case 'TEXTAREA':
+                    case 'SELECT':
+                    default:
+                        $(tag).val(value);
+                        break;
+                }
+            });
+
+            return page;
+        }
+
+        templateForOption(modelType) {
+            let optionConfig = this.modelConfig[modelType];
+            let state = this.state;
+
+            let optBox = new com_String();
+            // render tag
+            optionConfig.options.forEach(opt => {
+                optBox.appendFormatLine('<label for="{0}" title="{1}">{2}</label>'
+                    , opt.name, opt.name, com_util.optionToLabel(opt.name));
+                let content = com_generator.renderContent(this, opt.component[0], opt, state);
+                optBox.appendLine(content[0].outerHTML);
+            });
+            // render user option
+            optBox.appendFormatLine('<label for="{0}">{1}</label>', 'userOption', 'User option');
+            optBox.appendFormatLine('<input type="text" class="vp-input vp-state" id="{0}" placeholder="{1}" value="{2}"/>',
+                                        'userOption', 'key=value, ...', this.state.userOption);
+            return optBox.toString();
+        }
+
+        render() {
+            super.render();
+
+            this.loadModelList(this.state.category);
+        }
+
+        loadModelList(category='') {
+            // reset page
+            try {
+                $(this.wrapSelector('.vp-ins-search')).autocomplete("destroy");
+            } catch { ; }
+            $(this.wrapSelector('.vp-ins-select-list.info')).html('');
+            $(this.wrapSelector('.vp-ins-parameter-box')).html('');
+
+            if (category == 'All') {
+                category = '';
+            }
+            // set model list
+            let that = this;
+            let modelOptionTag = new com_String();
+            vpKernel.getModelList(category).then(function(resultObj) {
+                let { result } = resultObj;
+                var modelList = JSON.parse(result);
+                modelList && modelList.forEach((model, idx) => {
+                    let selectFlag = '';
+                    // if this item is pre-selected model or first item of model list
+                    if ((model.varName == that.state.model)
+                        || (that.state.model == '' && idx == 0)) {
+                        selectFlag = 'selected';
+                        that.state.model = model.varName;
+                        that.state.modelType = model.varType;
+                    }
+                    modelOptionTag.appendFormatLine('<li class="{0} {1}" data-var-name="{2}" data-var-type="{3}" title="{4}">{5} ({6})</li>',
+                    'vp-ins-select-item', selectFlag, model.varName, model.varType, model.varName, model.varName, model.varType);
+                });
+                $(that.wrapSelector('.vp-ins-select-list.model')).html(modelOptionTag.toString());
+
+                // click model event
+                $(that.wrapSelector('.vp-ins-select-list.model .vp-ins-select-item')).on('click', function() {
+                    let model = $(this).data('var-name');
+                    let modelType = $(this).data('var-type');
+
+                    that.state.model = model;
+                    that.state.modelType = modelType;
+                    
+                    $(that.wrapSelector('.vp-ins-select-list.model .vp-ins-select-item')).removeClass('selected');
+                    $(this).addClass('selected');
+
+                    that.reload();
+                });
+
+                that.reload();
+            });
+        }
+
+        /**
+         * Load options for selected model
+         */
+        reload() {
+            // reset option page
+            try {
+                $(this.wrapSelector('.vp-ins-search')).autocomplete("destroy");
+            } catch { ; }
+            $(this.wrapSelector('.vp-ins-select-list.info')).html('');
+            $(this.wrapSelector('.vp-ins-parameter-box')).html('');
+            
+            let model = this.state.model;
+            let modelType = this.state.modelType;
+            
+            let infos = this.getInfo(modelType);
+            this.state.info = { ...infos };
+            
+            var infoListTag = new com_String();
+            
+            Object.keys(infos).forEach(infoKey => {
+                let titleText = infos[infoKey].description;
+                if (infos[infoKey].name != infos[infoKey].label) {   
+                    titleText = infos[infoKey].name + ': ' + titleText;
+                }
+                infoListTag.appendFormatLine('<li class="{0}" data-var-name="{1}" data-var-type="{2}" title="{3}">{4}</li>',
+                'vp-ins-select-item', infoKey, 'info', titleText, infos[infoKey].label);
+            });
+            
+            $(this.wrapSelector('.vp-ins-select-list.info')).html(infoListTag.toString());
+            
+            let that = this;
+            // info search suggest
+            let suggestInput = new SuggestInput();
+            suggestInput.addClass('vp-input');
+            suggestInput.addClass('vp-ins-search');
+            suggestInput.setPlaceholder("Search information");
+            suggestInput.setSuggestList(function () { return Object.keys(infos); });
+            suggestInput.setSelectEvent(function (value, item) {
+                $(this.wrapSelector()).val(value);
+                $(that.wrapSelector('.vp-ins-type.info')).val(value);
+
+                $(that.wrapSelector('.vp-ins-select-item[data-var-name="' + value + '"]')).click();
+            });
+            $(that.wrapSelector('.vp-ins-search')).replaceWith(function () {
+                return suggestInput.toTagString();
+            });
+
+            // bind event
+            // click option
+            $(this.wrapSelector('.vp-ins-select-list.info .vp-ins-select-item')).on('click', function() {
+                let name = $(this).data('var-name');
+                let type = $(this).data('var-type');
+                
+                that.renderOptionPage(type, name);
+            });
+
+            // load once on initializing page
+            if (this.loaded == false) {
+                let { modelEditorType, modelEditorName } = this.state;
+                if (modelEditorType != '' && modelEditorName != '') {
+                    // render option page for saved state
+                    that.renderOptionPage(modelEditorType, modelEditorName);
+                }
+                // set loaded true
+                this.loaded = true;
+            }
+        }
+
+        /**
+         * Render option page for selected option
+         * @param {String} type action / info
+         * @param {String} name option name (ex. fit/predict/...)
+         */
+        renderOptionPage(type, name) {
+            if (this.state[type] != undefined && this.state[type][name] != undefined) {
+                let optionConfig = this.state[type][name];
+                let optBox = new com_String();
+                // render tag
+                optionConfig && optionConfig.options && optionConfig.options.forEach(opt => {
+                    let label = opt.name;
+                    if (opt.label != undefined) {
+                        label = opt.label;
+                    }
+                    // fix label
+                    label = com_util.optionToLabel(label);
+                    optBox.appendFormatLine('<label for="{0}" title="{1}">{2}</label>'
+                        , opt.name, opt.name, label);
+                    let content = com_generator.renderContent(this, opt.component[0], opt, this.state);
+                    optBox.appendLine(content[0].outerHTML);
+                });
+                // replace option box
+                $(this.wrapSelector('.vp-ins-parameter-box')).html(optBox.toString());
+    
+                this.state.optionConfig = optionConfig;
+    
+                // add selection
+                let typeClass = '.vp-ins-select-list.' + type;
+                let nameClass = '.vp-ins-select-item[data-var-name="' + name + '"]';
+                $(this.wrapSelector(typeClass + ' ' + '.vp-ins-select-item')).removeClass('selected');
+                $(this.wrapSelector(typeClass + ' ' + nameClass)).addClass('selected');
+                // set state
+                $(this.wrapSelector('#modelEditorType')).val(type);
+                $(this.wrapSelector('#modelEditorName')).val(name);
+                this.state.modelEditorType = type;
+                this.state.modelEditorName = name;
+            }
+        }
+
+        generateCode() {
+            let { model } = this.state;
+            let code = new com_String();
+            let replaceDict = {'${model}': model};
+
+            if (this.state.optionConfig.import != undefined) {
+                code.appendLine(this.state.optionConfig.import);
+                code.appendLine();
+            }
+            let modelCode = com_generator.vp_codeGenerator(this, this.state.optionConfig, this.state);
+            if (modelCode) {
+                Object.keys(replaceDict).forEach(key => {
+                    modelCode = modelCode.replace(key, replaceDict[key]);
+                });
+                code.append(modelCode);
+    
+                let allocateIdx = modelCode.indexOf(' = ');
+                if (allocateIdx >= 0) {
+                    let allocateCode = modelCode.substr(0, allocateIdx);
+                    code.appendLine();
+                    code.append(allocateCode);
+                }
+            }
+
+            return code.toString();
+        }
+
+        getModelCategory(modelType) {
+            let mlDict = vpConfig.getMLDataDict();
+            let keys = Object.keys(mlDict);
+            let modelCategory = '';
+            for (let i = 0; i < keys.length; i++) {
+                let key = keys[i];
+                if (mlDict[key].includes(modelType)) {
+                    modelCategory = key;
+                    break;
+                }
+            }
+            return modelCategory;
+        }
+
+        getInfo(modelType) {
+            let category = this.getModelCategory(modelType);
+            let infos = {};
+            let defaultInfos = {
+                'score': {
+                    name: 'score',
+                    label: 'Score',
+                    code: '${score_allocate} = ${model}.score(${score_featureData}, ${score_targetData})',
+                    description: '',
+                    options: [
+                        { name: 'score_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                        { name: 'score_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' },
+                        { name: 'score_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' }
+                    ]
+                },
+                'get_params': {
+                    name: 'get_params',
+                    label: 'Get parameters',
+                    code: '${param_allocate} = ${model}.get_params(${deep})',
+                    description: 'Get parameters for this estimator.',
+                    options: [
+                        { name: 'deep', component: ['bool_select'], default: 'True', usePair: true },
+                        { name: 'param_allocate', label: 'Allocate to', component: ['input'], value: 'params' }
+                    ]  
+                },
+                'permutation_importance': {
+                    name: 'permutation_importance',
+                    label: 'Permutation importance',
+                    import: 'from sklearn.inspection import permutation_importance',
+                    code: '${importance_allocate} = permutation_importance(${model}, ${importance_featureData}, ${importance_targetData}${scoring}${random_state}${etc})',
+                    description: 'Permutation importance for feature evaluation.',
+                    options: [
+                        { name: 'importance_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X_train' },
+                        { name: 'importance_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y_train' },
+                        { name: 'scoring', component: ['input'], usePair: true },
+                        { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true },
+                        { name: 'importance_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'importances' }
+                    ]
+                }
+            }
+            switch (category) {
+                case 'Data Preparation':
+                    if (modelType == 'OneHotEncoder') {
+                        infos = {
+                            'categories_': { // TODO:
+                                name: 'categories_',
+                                label: 'Categories',
+                                code: '${categories_allocate} = ${model}.categories_',
+                                description: 'The categories of each feature determined during fitting',
+                                options: [
+                                    { name: 'categories_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'categories' }
+                                ]
+                            },
+                            'get_feature_names_out': {
+                                name: 'get_feature_names_out',
+                                label: 'Get feature names',
+                                code: '${feature_names_allocate} = ${model}.get_feature_names_out()',
+                                description: 'Get output feature names.',
+                                options: [
+                                    { name: 'feature_names_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'features' }
+                                ]
+                            }
+                        }
+                    }
+                    if (modelType == 'LabelEncoder') {
+                        infos = {
+                            'classes_': {
+                                name: 'classes_',
+                                label: 'Classes',
+                                code: '${classes_allocate} = ${model}.classes_',
+                                description: 'Holds the label for each class.',
+                                options: [
+                                    { name: 'classes_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'classes' }
+                                ]
+                            }
+                        }
+                    }
+                    if (modelType == 'KBinsDiscretizer') {
+                        infos = {
+                            'bin_edges': { // TODO:
+                                name: 'bin_edges',
+                                label: 'Bin edges',
+                                code: '${bin_edges_allocate} = ${model}.bin_edges_',
+                                description: 'The edges of each bin. Contain arrays of varying shapes',
+                                options: [
+                                    { name: 'bin_edges_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'bin_edges' }
+                                ]
+                            }
+                        }
+                    }
+                    if (modelType == 'ColumnTransformer') {
+                        infos = {
+                            'transformers_': {
+                                name: 'transformers_',
+                                label: 'Transformers_',
+                                code: '${transformers_allocate} = ${model}.transformers_',
+                                description: 'The collection of fitted transformers as tuples of (name, fitted_transformer, column).',
+                                options: [
+                                    { name: 'transformers_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'classes' }
+                                ]
+                            },
+                            'get_feature_names_out': {
+                                name: 'get_feature_names_out',
+                                label: 'Get feature names',
+                                code: '${feature_names_allocate} = ${model}.get_feature_names_out()',
+                                description: 'Get output feature names.',
+                                options: [
+                                    { name: 'feature_names_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'features' }
+                                ]
+                            }
+                        }
+                    }
+                    infos = {
+                        ...infos,
+                        'get_params': defaultInfos['get_params']
+                    }
+                    break;
+                case 'Regression':
+                    infos = {
+                        'score': {
+                            ...defaultInfos['score'],
+                            description: 'Return the coefficient of determination of the prediction.'
+                        },
+                        'cross_val_score': {
+                            name: 'cross_val_score',
+                            label: 'Cross validation score',
+                            import: 'from sklearn.model_selection import cross_val_score',
+                            code: '${cvs_allocate} = cross_val_score(${model}, ${cvs_featureData}, ${cvs_targetData}${scoring}${cv})',
+                            description: 'Evaluate a score by cross-validation.',
+                            options: [
+                                { name: 'cvs_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'cvs_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' },
+                                { name: 'scoring', component: ['option_select'], usePair: true, type: 'text',
+                                    options: [
+                                        '',
+                                        'explained_variance', 'max_error', 'neg_mean_absolute_error', 'neg_mean_squared_error', 'neg_root_mean_squared_error',
+                                        'neg_mean_squared_log_error', 'neg_median_absolute_error', 'r2', 'neg_mean_poisson_deviance', 'neg_mean_gamma_deviance',
+                                        'neg_mean_absolute_percentage_error'
+                                    ] },
+                                { name: 'cv', label: 'Cross Validation', component: ['input_number'], placeholder: '1 ~ 10', default: 5, usePair: true },
+                                { name: 'cvs_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' }
+                            ]
+                        },
+                        'permutation_importance': defaultInfos['permutation_importance'],
+                        'Coefficient': {
+                            name: 'coef_',
+                            label: 'Coefficient',
+                            code: '${coef_allocate} = ${model}.coef_',
+                            description: 'Weights assigned to the features.',
+                            options: [
+                                { name: 'coef_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'coef' }
+                            ]
+                        },
+                        'Intercept': {
+                            name: 'intercept_',
+                            label: 'Intercept',
+                            code: '${intercept_allocate} = ${model}.intercept_',
+                            description: 'Constants in decision function.',
+                            options: [
+                                { name: 'intercept_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'intercepts' }
+                            ]
+                        }
+                    }
+                    break;
+                case 'Classification':
+                    infos = {
+                        'score': {
+                            ...defaultInfos['score'],
+                            description: 'Return the mean accuracy on the given test data and labels.'
+                        },
+                        'cross_val_score': {
+                            name: 'cross_val_score',
+                            label: 'Cross validation score',
+                            import: 'from sklearn.model_selection import cross_val_score',
+                            code: '${cvs_allocate} = cross_val_score(${model}, ${cvs_featureData}, ${cvs_targetData}${scoring}${cv})',
+                            description: 'Evaluate a score by cross-validation.',
+                            options: [
+                                { name: 'cvs_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'cvs_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' },
+                                { name: 'scoring', component: ['option_select'], usePair: true, type: 'text', 
+                                    options: [
+                                        '',
+                                        'accuracy', 'balanced_accuracy', 'top_k_accuracy', 'average_precision', 'neg_brier_score',
+                                        'f1', 'f1_micro', 'f1_macro', 'f1_weighted', 'f1_samples', 'neg_log_loss', 'precision', 'recall', 'jaccard', 
+                                        'roc_auc', 'roc_auc_ovr', 'roc_auc_ovo', 'roc_auc_ovr_weighted', 'roc_auc_ovo_weighted'
+                                    ] },
+                                { name: 'cv', label: 'Cross Validation', component: ['input_number'], placeholder: '1 ~ 10', default: 5, usePair: true },
+                                { name: 'cvs_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' }
+                            ]
+                        },
+                        'roc_curve': {
+                            name: 'roc_curve',
+                            label: 'ROC Curve',
+                            import: 'from sklearn import metrics',
+                            code: "fpr, tpr, thresholds = metrics.roc_curve(${roc_targetData}, ${model}.predict_proba(${roc_featureData})[:, 1])\n\
+plt.plot(fpr, tpr, label='ROC Curve')\n\
+plt.xlabel('Sensitivity')\n\
+plt.ylabel('Specificity')\n\
+plt.show()",
+                            description: '',
+                            options: [
+                                { name: 'roc_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y_test' },
+                                { name: 'roc_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X_test' }
+                            ]
+                        },
+                        'auc': {
+                            name: 'auc',
+                            label: 'AUC',
+                            import: 'from sklearn import metrics',
+                            code: 'metrics.roc_auc_score(${auc_targetData}, ${model}.predict_proba(${auc_featureData})[:, 1])',
+                            description: '',
+                            options: [
+                                { name: 'auc_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y_test' },
+                                { name: 'auc_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X_test' }
+                            ]
+                        },
+                        'permutation_importance': defaultInfos['permutation_importance']
+                    }
+
+                    // use decision_function on ROC, AUC
+                    let decisionFunctionTypes = [
+                        'LogisticRegression', 'SVC', 'GradientBoostingClassifier'
+                    ];
+                    if (decisionFunctionTypes.includes(modelType)) {
+                        infos = {
+                            ...infos,
+                            'roc_curve': {
+                                ...infos['roc_curve'],
+                                code: "fpr, tpr, thresholds = metrics.roc_curve(${roc_targetData}, ${model}.decision_function(${roc_featureData}))\n\
+plt.plot(fpr, tpr, label='ROC Curve')\n\
+plt.xlabel('Sensitivity')\n\
+plt.ylabel('Specificity')\n\
+plt.show()"
+                            },
+                            'auc': {
+                                ...infos['auc'],
+                                code: 'metrics.roc_auc_score(${auc_targetData}, ${model}.decision_function(${auc_featureData}))',
+                            }
+                        }
+                    }
+                    break;
+                case 'Auto ML':
+                    infos = {
+                        'score': {
+                            ...defaultInfos['score'],
+                            description: 'Return the mean accuracy on the given test data and labels.'
+                        },
+                        'get_params': {
+                            ...defaultInfos['get_params']
+                        }
+                    }
+                    break;
+                case 'Clustering':
+                    infos = {
+                        'get_params': {
+                            ...defaultInfos['get_params']
+                        }
+                    }
+
+                    if (modelType == 'KMeans') {
+                        infos = {
+                            ...infos,
+                            'score': {
+                                ...defaultInfos['score'],
+                                description: 'Return the mean accuracy on the given test data and labels.'
+                            },
+                            'cluster_centers_': {
+                                name: 'cluster_centers',
+                                label: 'Cluster centers',
+                                code: '${centers_allocate} = ${model}.cluster_centers_',
+                                description: 'Coordinates of cluster centers.', 
+                                options: [
+                                    { name: 'centers_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'cluster_centers' }
+                                ]
+                            }
+                        }
+                    }
+
+                    if (modelType == 'AgglomerativeClustering') {
+                        infos = {
+                            ...infos,
+                            'Dendrogram': { // FIXME:
+                                name: 'dendrogram',
+                                label: 'Dendrogram',
+                                code: "# import\nfrom scipy.cluster.hierarchy import dendrogram, ward\n\nlinkage_array = ward(${dendro_data})\ndendrogram(linkage_array, p=3, truncate_mode='level', no_labels=True)\nplt.show()",
+                                description: 'Draw a dendrogram',
+                                options: [
+                                    { name: 'dendro_data', label: 'Data', component: ['var_select'], var_type: ['DataFrame'] }
+                                ]
+                            }
+                        }
+                    }
+
+                    if (modelType == 'GaussianMixture') {
+                        infos = {
+                            ...infos,
+                            'score': {
+                                ...defaultInfos['score'],
+                                description: 'Compute the per-sample average log-likelihood of the given data X.'
+                            }
+                        }
+                    }
+                    break;
+                case 'Dimension Reduction':
+                    if (modelType == 'LDA') {
+                        infos = {
+                            'score': {
+                                name: 'score',
+                                label: 'Score',
+                                code: '${score_allocate} = ${model}.score(${score_featureData}, ${score_targetData})',
+                                description: 'Return the average log-likelihood of all samples.',
+                                options: [
+                                    { name: 'score_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                    { name: 'score_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' },
+                                    { name: 'score_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' }
+                                ]
+                            }
+                        }
+                        break;
+                    }
+                    if (modelType == 'PCA') {
+                        infos = {
+                            'explained_variance_ratio_': {
+                                name: 'explained_variance_ratio_',
+                                label: 'Explained variance ratio',
+                                code: '${ratio_allocate} = ${model}.explained_variance_ratio_',
+                                description: 'Percentage of variance explained by each of the selected components.',
+                                options: [
+                                    { name: 'ratio_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'ratio' }
+                                ]
+                            }
+                        }
+                    }
+                    infos = {
+                        ...infos,
+                        'score': {
+                            name: 'score',
+                            label: 'Score',
+                            code: '${score_allocate} = ${model}.score(${score_featureData})',
+                            description: 'Return the average log-likelihood of all samples.',
+                            options: [
+                                { name: 'score_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' },
+                                { name: 'score_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' }
+                            ]
+                        }
+                    }
+                    break;
+            }
+            return infos;
+        }
+
+    }
+
+    return ModelInfo;
+});
\ No newline at end of file
diff --git a/js/m_ml/Regression.js b/js/m_ml/Regression.js
index a2c73291..4b46ccd4 100644
--- a/js/m_ml/Regression.js
+++ b/js/m_ml/Regression.js
@@ -138,13 +138,13 @@ define([
             // render option page
             $(page).find('.vp-model-option-box').html(this.templateForOption(this.state.modelType));
 
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
diff --git a/js/m_ml/dataSplit.js b/js/m_ml/dataSplit.js
index 0361f213..6005e748 100644
--- a/js/m_ml/dataSplit.js
+++ b/js/m_ml/dataSplit.js
@@ -102,21 +102,21 @@ define([
             $(page).find('#testSize').html(sizeOptions);
 
             // varselector TEST:
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('featureData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.featureData);
             varSelector.setPlaceholder('Select feature data');
             $(page).find('#featureData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
             varSelector.setPlaceholder('Select target data');
             $(page).find('#targetData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('stratify');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.stratify);
diff --git a/js/m_ml/evaluation.js b/js/m_ml/evaluation.js
index 41ab3be5..47cdd360 100644
--- a/js/m_ml/evaluation.js
+++ b/js/m_ml/evaluation.js
@@ -40,9 +40,11 @@ define([
                 // classification
                 confusion_matrix: true, report: true, 
                 accuracy: false, precision: false, recall: false, f1_score: false,
-                roc_curve: false, auc: false,
                 // clustering
-                silhouetteScore: true, ari: false, nm: false,
+                clusteredIndex: 'clusters',
+                silhouetteScore: true, ari: false, nmi: false,
+                featureData2: 'X',
+                targetData2: 'y',
                 ...this.state
             }
         }
@@ -62,26 +64,47 @@ define([
                 let modelType = $(this).val();
                 that.state.modelType = modelType;
 
+                $(that.wrapSelector('.vp-upper-box')).hide();
+                $(that.wrapSelector('.vp-upper-box.' + modelType)).show();
+
                 $(that.wrapSelector('.vp-eval-box')).hide();
                 $(that.wrapSelector('.vp-eval-'+modelType)).show();  
 
-                if (modelType == 'clf') {
+                if (modelType == 'rgs') {
+                    // Regression
+
+                } else if (modelType == 'clf') {
                     // Classification - model selection
-                    if (that.checkToShowModel() == true) {
-                        $(that.wrapSelector('.vp-ev-model')).show();
+                    // if (that.checkToShowSelector('roc-auc') == true) {
+                    //     $(that.wrapSelector('.vp-ev-model.roc-auc')).prop('disabled', false);
+                    // } else {
+                    //     $(that.wrapSelector('.vp-ev-model.roc-auc')).prop('disabled', true);
+                    // }
+                } else {
+                    // Clustering
+                    if (that.checkToShowSelector('silhouette') == true) {
+                        $(that.wrapSelector('.vp-ev-model.silhouette')).prop('disabled', false);
+                    } else {
+                        $(that.wrapSelector('.vp-ev-model.silhouette')).prop('disabled', true);
+                    }
+                    if (that.checkToShowSelector('ari-nmi') == true) {
+                        $(that.wrapSelector('.vp-ev-model.ari-nmi')).prop('disabled', false);
+                    } else {
+                        $(that.wrapSelector('.vp-ev-model.ari-nmi')).prop('disabled', true);
                     }
                 }
             });
 
-            // open model selection show
+            // check to enable/disable selector
             $(this.wrapSelector('.vp-eval-check')).on('change', function() {
                 let checked = $(this).prop('checked');
+                let type = $(this).data('type');
 
                 if (checked) {
-                    $(that.wrapSelector('.vp-ev-model')).show();
+                    $(that.wrapSelector('.vp-ev-model.' + type)).prop('disabled', false);
                 } else {
-                    if (that.checkToShowModel() == false) {
-                        $(that.wrapSelector('.vp-ev-model')).hide();
+                    if (that.checkToShowSelector(type) == false) {
+                        $(that.wrapSelector('.vp-ev-model.' + type)).prop('disabled', true);
                     }
                 }
             });
@@ -91,8 +114,8 @@ define([
          * Check if anything checked available ( > 0)
          * @returns 
          */
-        checkToShowModel() {
-            let checked = $(this.wrapSelector('.vp-eval-check:checked')).length;
+        checkToShowSelector(type) {
+            let checked = $(this.wrapSelector('.vp-eval-check[data-type="' + type + '"]:checked')).length;
             if (checked > 0) { 
                 return true;
             }
@@ -106,39 +129,36 @@ define([
             $(page).find('.vp-eval-'+this.state.modelType).show();
 
             // varselector
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('predictData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.predictData);
             $(page).find('#predictData').replaceWith(varSelector.toTagString());
 
-            varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'list', 'str']);
+            varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('targetData');
             varSelector.addClass('vp-state vp-input');
             varSelector.setValue(this.state.targetData);
             $(page).find('#targetData').replaceWith(varSelector.toTagString());
 
-            // model
-            // set model list
-            let modelOptionTag = new com_String();
-            vpKernel.getModelList('Classification').then(function(resultObj) {
-                let { result } = resultObj;
-                var modelList = JSON.parse(result);
-                modelList && modelList.forEach(model => {
-                    let selectFlag = '';
-                    if (model.varName == that.state.model) {
-                        selectFlag = 'selected';
-                    }
-                    modelOptionTag.appendFormatLine('<option value="{0}" data-type="{1}" {2}>{3} ({4})</option>', 
-                        model.varName, model.varType, selectFlag, model.varName, model.varType);
-                });
-                $(page).find('#model').html(modelOptionTag.toString());
-                $(that.wrapSelector('#model')).html(modelOptionTag.toString());
+            // Clustering - data selection
+            varSelector = new VarSelector2(this.wrapSelector());
+            varSelector.setComponentID('clusteredIndex');
+            varSelector.addClass('vp-state vp-input');
+            varSelector.setValue(this.state.clusteredIndex);
+            $(page).find('#clusteredIndex').replaceWith(varSelector.toTagString());
 
-                if (!that.state.model || that.state.model == '') {
-                    that.state.model = $(that.wrapSelector('#model')).val();
-                }
-            });
+            varSelector = new VarSelector2(this.wrapSelector());
+            varSelector.setComponentID('featureData2');
+            varSelector.addClass('vp-state vp-input vp-ev-model silhouette');
+            varSelector.setValue(this.state.featureData2);
+            $(page).find('#featureData2').replaceWith(varSelector.toTagString());
+
+            varSelector = new VarSelector2(this.wrapSelector());
+            varSelector.setComponentID('targetData2');
+            varSelector.addClass('vp-state vp-input vp-ev-model ari-nmi');
+            varSelector.setValue(this.state.targetData2);
+            $(page).find('#targetData2').replaceWith(varSelector.toTagString());
 
             // load state
             let that = this;
@@ -169,35 +189,48 @@ define([
                 }
             });
 
-            if (this.state.modelType == 'clf') {
-                if (this.state.roc_curve == true || this.state.auc == true) {
-                    $(page).find('.vp-ev-model').show();
-                } else {
-                    $(page).find('.vp-ev-model').hide();
-                }
+            $(page).find('.vp-upper-box').hide();
+            $(page).find('.vp-upper-box.' + this.state.modelType).show();
+
+            if (this.state.modelType == 'rgs') {
+                // Regression
+
+            } else if (this.state.modelType == 'clf') {
+                // Classification
+                // if (this.state.roc_curve == false && this.state.auc == false) {
+                //     $(page).find('.vp-ev-model.roc-auc').prop('disabled', true);
+                // }
             } else {
-                $(page).find('.vp-ev-model').hide();
+                // Clustering
+                if (this.state.silhouetteScore == false) {
+                    $(page).find('.vp-ev-model.silhouette').prop('disabled', true);
+                }
+                if (this.state.ari == false && this.state.nmi == false) {
+                    $(page).find('.vp-ev-model.ari-nmi').prop('disabled', true);
+                }
             }
 
             return page;
         }
         
         generateImportCode() {
-            return 'from sklearn import metrics';
+            return ['from sklearn import metrics'];
         }
 
         generateCode() {
-            let codeCells = [];
+            let codeCells = [
+                ...this.generateImportCode() // run import codes
+            ];
             let code = new com_String();
             let { 
                 modelType, predictData, targetData,
                 // classification
-                confusion_matrix, report, accuracy, precision, recall, f1_score, roc_curve, auc,
-                model,
+                confusion_matrix, report, accuracy, precision, recall, f1_score, 
                 // regression
                 coefficient, intercept, r_squared, mae, mape, rmse, scatter_plot,
                 // clustering
-                sizeOfClusters, silhouetteScore, ari, nm
+                sizeOfClusters, silhouetteScore, ari, nmi,
+                clusteredIndex, featureData2, targetData2
             } = this.state;
 
             //====================================================================
@@ -240,21 +273,21 @@ define([
                     code.appendFormat("metrics.f1_score({0}, {1}, average='weighted')", targetData, predictData);
                     codeCells.push(code.toString());
                 }
-                if (roc_curve) {
-                    code = new com_String();
-                    code.appendLine("# ROC Curve");
-                    code.appendFormatLine("fpr, tpr, thresholds = metrics.roc_curve({0}, {1}.decision_function({2}))", predictData, model, targetData);
-                    code.appendLine("plt.plot(fpr, tpr, label='ROC Curve')");
-                    code.appendLine("plt.xlabel('Sensitivity') ");
-                    code.append("plt.ylabel('Specificity') ")
-                    codeCells.push(code.toString());
-                }
-                if (auc) {
-                    code = new com_String();
-                    code.appendLine("# AUC");
-                    code.appendFormat("metrics.roc_auc_score({0}, {1}.decision_function({2}))", predictData, model, targetData);
-                    codeCells.push(code.toString());
-                }
+                // if (roc_curve) {
+                //     code = new com_String();
+                //     code.appendLine("# ROC Curve");
+                //     code.appendFormatLine("fpr, tpr, thresholds = metrics.roc_curve({0}, {1}.decision_function({2}))", predictData, model, targetData);
+                //     code.appendLine("plt.plot(fpr, tpr, label='ROC Curve')");
+                //     code.appendLine("plt.xlabel('Sensitivity') ");
+                //     code.append("plt.ylabel('Specificity') ")
+                //     codeCells.push(code.toString());
+                // }
+                // if (auc) {
+                //     code = new com_String();
+                //     code.appendLine("# AUC");
+                //     code.appendFormat("metrics.roc_auc_score({0}, {1}.decision_function({2}))", predictData, model, targetData);
+                //     codeCells.push(code.toString());
+                // }
             }
 
             //====================================================================
@@ -317,19 +350,19 @@ define([
                 if (silhouetteScore) {
                     code = new com_String();
                     code.appendLine("# Silhouette score");
-                    code.appendFormat("print(f'Silhouette score: {metrics.cluster.silhouette_score({0}, {1})}')", targetData, predictData);
+                    code.appendFormat("print(f'Silhouette score: {metrics.cluster.silhouette_score({0}, {1})}')", featureData2, clusteredIndex);
                     codeCells.push(code.toString());
                 }
                 if (ari) {
                     code = new com_String();
-                    code.appendLine("# ARI");
-                    code.appendFormat("print(f'ARI: {metrics.cluster.adjusted_rand_score({0}, {1})}')", targetData, predictData);
+                    code.appendLine("# ARI(Adjusted Rand score)");
+                    code.appendFormat("print(f'ARI: {metrics.cluster.adjusted_rand_score({0}, {1})}')", targetData2, clusteredIndex);
                     codeCells.push(code.toString());
                 }
-                if (nm) {
+                if (nmi) {
                     code = new com_String();
-                    code.appendLine("# NM");
-                    code.appendFormat("print(f'NM: {metrics.cluster.normalized_mutual_info_score({0}, {1})}')", targetData, predictData);
+                    code.appendLine("# NMI(Normalized Mutual Info Score)");
+                    code.appendFormat("print(f'NM: {metrics.cluster.normalized_mutual_info_score({0}, {1})}')", targetData2, clusteredIndex);
                     codeCells.push(code.toString());
                 }
             }
diff --git a/js/m_apps/Chart.js b/js/m_visualize/Chart.js
similarity index 99%
rename from js/m_apps/Chart.js
rename to js/m_visualize/Chart.js
index 76ed858e..bbaa0b36 100644
--- a/js/m_apps/Chart.js
+++ b/js/m_visualize/Chart.js
@@ -13,8 +13,8 @@
 // [CLASS] Chart
 //============================================================================
 define([
-    'text!vp_base/html/m_apps/chart.html!strip',
-    'css!vp_base/css/m_apps/chart.css',
+    'text!vp_base/html/m_visualize/chart.html!strip',
+    'css!vp_base/css/m_visualize/chart.css',
     'vp_base/js/com/com_String',
     'vp_base/js/com/com_Const',
     'vp_base/js/com/com_util',
@@ -775,7 +775,7 @@ define([
             }
             code.append("rcParams['axes.unicode_minus'] = False");
     
-            return code.toString();
+            return [code.toString()];
         }
     
 
diff --git a/js/m_visualize/ChartSetting.js b/js/m_visualize/ChartSetting.js
index ebcda860..6b13b7d8 100644
--- a/js/m_visualize/ChartSetting.js
+++ b/js/m_visualize/ChartSetting.js
@@ -31,7 +31,7 @@ define([
             this.state = {
                 figureWidth: 12,
                 figureHeight: 8,
-                styleSheet: '',
+                styleSheet: 'seaborn-darkgrid',
                 fontName: '',
                 fontSize: 10,
                 ...this.state
@@ -42,7 +42,18 @@ define([
             super._bindEvent();
 
             let that = this;
-            
+            // setting popup - set default
+            $(this.wrapSelector('#setDefault')).on('change', function() {
+                let checked = $(this).prop('checked');
+
+                if (checked) {
+                    // disable input
+                    $(that.wrapSelector('.vp-chart-setting-body input')).prop('disabled', true);
+                } else {
+                    // enable input
+                    $(that.wrapSelector('.vp-chart-setting-body input')).prop('disabled', false);
+                }
+            });
         }
 
         templateForBody() {
@@ -113,31 +124,40 @@ define([
         generateImportCode() {
             var code = new com_String();
             code.appendLine('import matplotlib.pyplot as plt');
-            code.append('import seaborn as sns');
-            return code.toString();
+            code.appendLine('import seaborn as sns');
+            code.append('%matplotlib inline');
+            return [code.toString()];
         }
 
         generateCode() {
             var code = new com_String();
     
             // get parameters
-            let { figureWidth, figureHeight, styleSheet, fontName, fontSize } = this.state;
-    
-            code.appendLine('import matplotlib.pyplot as plt');
-            code.appendFormatLine("plt.rc('figure', figsize=({0}, {1}))", figureWidth, figureHeight);
-            if (styleSheet && styleSheet.length > 0) {
-                code.appendFormatLine("plt.style.use('{0}')", styleSheet);
-            }
-            code.appendLine();
-    
-            code.appendLine('from matplotlib import rcParams');
-            if (fontName && fontName.length > 0) {
-                code.appendFormatLine("rcParams['font.family'] = '{0}'", fontName);
-            }
-            if (fontSize && fontSize.length > 0) {
-                code.appendFormatLine("rcParams['font.size'] = {0}", fontSize);
+            let setDefault = $(this.wrapSelector('#setDefault')).prop('checked');
+            if (setDefault == true) {
+                code.appendLine('from matplotlib import rcParams, rcParamsDefault');
+                code.append('rcParams.update(rcParamsDefault)');
+            } else {
+                // get parameters
+                let { figureWidth, figureHeight, styleSheet, fontName, fontSize } = this.state;
+        
+                code.appendLine('import matplotlib.pyplot as plt');
+                code.appendLine('import seaborn as sns');
+                code.appendFormatLine("plt.rc('figure', figsize=({0}, {1}))", figureWidth, figureHeight);
+                if (styleSheet && styleSheet.length > 0) {
+                    code.appendFormatLine("plt.style.use('{0}')", styleSheet);
+                }
+                code.appendLine();
+        
+                code.appendLine('from matplotlib import rcParams');
+                if (fontName && fontName.length > 0) {
+                    code.appendFormatLine("rcParams['font.family'] = '{0}'", fontName);
+                }
+                if (fontSize && fontSize.length > 0) {
+                    code.appendFormatLine("rcParams['font.size'] = {0}", fontSize);
+                }
+                code.append("rcParams['axes.unicode_minus'] = False");
             }
-            code.append("rcParams['axes.unicode_minus'] = False");
     
             return code.toString();
         }
diff --git a/js/m_visualize/Seaborn.js b/js/m_visualize/Seaborn.js
index 8135a90c..3efd8ed9 100644
--- a/js/m_visualize/Seaborn.js
+++ b/js/m_visualize/Seaborn.js
@@ -29,7 +29,7 @@ define([
             super._init();
 
             this.config.dataview = false;
-            this.config.sizeLevel = 3;
+            this.config.size = { width: 1064, height: 550 };
 
             this.state = {
                 chartType: 'scatterplot',
@@ -39,10 +39,27 @@ define([
                 figColumn: 0,
                 shareX: false,
                 shareY: false,
+                setXY: false,
                 data: '',
                 x: '',
                 y: '',
                 hue: '',
+                // info options
+                title: '',
+                x_label: '',
+                y_label: '',
+                legendPos: '',
+                // style options
+                color: '',
+                useGrid: '',
+                gridColor: '',
+                markerStyle: '',
+                // setting options
+                x_limit_from: '',
+                x_limit_to: '',
+                y_limit_from: '',
+                y_limit_to: '',
+                // preview options
                 useSampling: true,
                 sampleCount: 30,
                 autoRefresh: true,
@@ -52,17 +69,59 @@ define([
             this.chartConfig = CHART_LIBRARIES;
             this.chartTypeList = {
                 'Relational': [ 'scatterplot', 'lineplot' ],
-                'Distributions': [ 'histplot', 'kdeplot', 'ecdfplot', 'rugplot' ], // FIXME: ecdf : no module
+                'Distributions': [ 'histplot', 'kdeplot', 'rugplot' ], 
                 'Categorical': [ 'stripplot', 'swarmplot', 'boxplot', 'violinplot', 'pointplot', 'barplot' ],
-                'ETC': [ ]
+                // 'ETC': [ ]
             }
+
+            this.legendPosList = [
+                {label: 'Select option...', value: ''},
+                {label: 'best', value: 'best'},
+                {label: 'upper right', value: 'upper right'},
+                {label: 'upper left', value: 'upper left'},
+                {label: 'lower left', value: 'lower left'},
+                {label: 'lower right', value: 'lower right'},
+                {label: 'center left', value: 'center left'},
+                {label: 'center right', value: 'center right'},
+                {label: 'lower center', value: 'lower center'},
+                {label: 'upper center', value: 'upper center'},
+                {label: 'center', value: 'center'},
+            ];
+
+            this.markerList = [
+                // 'custom': { label: 'Custom', value: 'marker' },
+                { label: 'Select option...', value: '', title: 'select marker style'},
+                { label: '.', value: '.', title: 'point' }, 
+                { label: ',', value: ',', title: 'pixel' }, 
+                { label: 'o', value: 'o', title: 'circle' }, 
+                { label: '▼', value: 'v', title: 'triangle_down' }, 
+                { label: '▲', value: '^', title: 'triangle_up' }, 
+                { label: '◀', value: '<', title: 'triangle_left' }, 
+                { label: '▶', value: '>', title: 'triangle_right' }, 
+                { label: '┬', value: '1', title: 'tri_down' }, 
+                { label: '┵', value: '2', title: 'tri_up' }, 
+                { label: '┤', value: '3', title: 'tri_left' }, 
+                { label: '├', value: '4', title: 'tri_right' }, 
+                { label: 'octagon', value: '8', title: 'octagon' }, 
+                { label: 'square', value: 's', title: 'square' }, 
+                { label: 'pentagon', value: 'p', title: 'pentagon' }, 
+                { label: 'filled plus', value: 'P', title: 'plus (filled)' }, 
+                { label: 'star', value: '*', title: 'star' }, 
+                { label: 'hexagon1', value: 'h', title: 'hexagon1' }, 
+                { label: 'hexagon2', value: 'H', title: 'hexagon2' }, 
+                { label: 'plus', value: '+', title: 'plus' }, 
+                { label: 'x', value: 'x', title: 'x' }, 
+                { label: 'filled x', value: 'X', title: 'x (filled)' }, 
+                { label: 'diamond', value: 'D', title: 'diamond' }, 
+                { label: 'thin diamond', value: 'd', title: 'thin_diamond' }
+            ]
         }
 
         _bindEvent() {
-            super._bindEvent();
-
             let that = this;
 
+            super._bindEvent();
+
             // setting popup
             $(this.wrapSelector('#chartSetting')).on('click', function() {
                 // show popup box
@@ -88,30 +147,68 @@ define([
             // change tab
             $(this.wrapSelector('.vp-tab-item')).on('click', function() {
                 let level = $(this).parent().data('level');
-                let type = $(this).data('type'); // info / element / figure
+                let type = $(this).data('type'); // data / info / element / figure
 
                 $(that.wrapSelector(com_util.formatString('.vp-tab-bar.{0} .vp-tab-item', level))).removeClass('vp-focus');
                 $(this).addClass('vp-focus');
 
-                $(that.wrapSelector(com_util.formatString('.vp-tab-page-box.{0} .vp-tab-page', level))).hide();
+                $(that.wrapSelector(com_util.formatString('.vp-tab-page-box.{0} > .vp-tab-page', level))).hide();
                 $(that.wrapSelector(com_util.formatString('.vp-tab-page[data-type="{0}"]', type))).show();
             });
-
-            // bind column by dataframe
-            $(document).on('change', this.wrapSelector('#data'), function() {
-                com_generator.vp_bindColumnSource(that.wrapSelector(), this, ['x', 'y', 'hue'], 'select');
+            
+            // use data or not
+            $(this.wrapSelector('#setXY')).on('change', function() {
+                let setXY = $(this).prop('checked');
+                if (setXY == false) {
+                    // set Data
+                    $(that.wrapSelector('#data')).prop('disabled', false);
+
+                    $(that.wrapSelector('#x')).closest('.vp-vs-box').replaceWith('<select id="x"></select>');
+                    $(that.wrapSelector('#y')).closest('.vp-vs-box').replaceWith('<select id="y"></select>');
+                    $(that.wrapSelector('#hue')).closest('.vp-vs-box').replaceWith('<select id="hue"></select>');
+                } else {
+                    // set X Y indivisually
+                    // disable data selection
+                    $(that.wrapSelector('#data')).prop('disabled', true);
+                    $(that.wrapSelector('#data')).val('');
+                    that.state.data = '';
+                    that.state.x = '';
+                    that.state.y = '';
+                    that.state.hue = '';
+
+                    let varSelectorX = new VarSelector2(that.wrapSelector(), ['DataFrame', 'Series', 'list']);
+                    varSelectorX.setComponentID('x');
+                    varSelectorX.addClass('vp-state vp-input');
+                    varSelectorX.setValue(that.state.x);
+                    $(that.wrapSelector('#x')).replaceWith(varSelectorX.toTagString());
+
+                    let varSelectorY = new VarSelector2(that.wrapSelector(), ['DataFrame', 'Series', 'list']);
+                    varSelectorY.setComponentID('y');
+                    varSelectorY.addClass('vp-state vp-input');
+                    varSelectorY.setValue(that.state.y);
+                    $(that.wrapSelector('#y')).replaceWith(varSelectorY.toTagString());
+
+                    let varSelectorHue = new VarSelector2(that.wrapSelector(), ['DataFrame', 'Series', 'list']);
+                    varSelectorHue.setComponentID('hue');
+                    varSelectorHue.addClass('vp-state vp-input');
+                    varSelectorHue.setValue(that.state.hue);
+                    $(that.wrapSelector('#hue')).replaceWith(varSelectorHue.toTagString());
+                }
             });
 
             // preview refresh
             $(this.wrapSelector('#previewRefresh')).on('click', function() {
                 that.loadPreview();
             });
-            $(this.wrapSelector('.vp-state')).on('change', function() {
-                if (that.state.autoRefresh && that.state.data != '') {
+            // auto refresh
+            $(document).off('change', this.wrapSelector('.vp-state'));
+            $(document).on('change', this.wrapSelector('.vp-state'), function(evt) {
+                that._saveSingleState($(this)[0]);
+                if (that.state.autoRefresh) {
                     that.loadPreview();
                 }
+                evt.stopPropagation();
             });
-
         }
 
         templateForBody() {
@@ -138,12 +235,53 @@ define([
             $(page).find('#chartType').html(chartTypeTag.toString());
 
             // chart variable
-            let varSelector = new VarSelector2(this.wrapSelector(), ['DataFrame', 'Series', 'list']);
+            let varSelector = new VarSelector2(this.wrapSelector());
             varSelector.setComponentID('data');
             varSelector.addClass('vp-state vp-input');
-            varSelector.setValue(this.state.featureData);
+            varSelector.setValue(this.state.data);
+            varSelector.setSelectEvent(function (value, item) {
+                $(this.wrapSelector()).val(value);
+                that.state.dtype = item.dtype;
+
+                if (item.dtype == 'DataFrame') {
+                    $(that.wrapSelector('#x')).prop('disabled', false);
+                    $(that.wrapSelector('#y')).prop('disabled', false);
+                    $(that.wrapSelector('#hue')).prop('disabled', false);
+                    
+                    // bind column source using selected dataframe
+                    com_generator.vp_bindColumnSource(that.wrapSelector(), $(that.wrapSelector('#data')), ['x', 'y', 'hue'], 'select', true, true);
+                } else {
+                    $(that.wrapSelector('#x')).prop('disabled', true);
+                    $(that.wrapSelector('#y')).prop('disabled', true);
+                    $(that.wrapSelector('#hue')).prop('disabled', true);
+                }
+            });
             $(page).find('#data').replaceWith(varSelector.toTagString());
 
+            // legend position
+            let legendPosTag = new com_String();
+            this.legendPosList.forEach(pos => {
+                let selectedFlag = '';
+                if (pos.value == that.state.legendPos) {
+                    selectedFlag = 'selected';
+                }
+                legendPosTag.appendFormatLine('<option value="{0}" {1}>{2}{3}</option>',
+                    pos.value, selectedFlag, pos.label, pos.value == 'best'?' (default)':'');
+            });
+            $(page).find('#legendPos').html(legendPosTag.toString());
+
+            // marker style
+            let markerTag = new com_String();
+            this.markerList.forEach(marker => {
+                let selectedFlag = '';
+                if (marker.value == that.state.markerStyle) {
+                    selectedFlag = 'selected';
+                }
+                markerTag.appendFormatLine('<option value="{0}" title="{1}" {2}>{3}</option>',
+                    marker.value, marker.title, selectedFlag, marker.label);
+            });
+            $(page).find('#markerStyle').html(markerTag.toString());
+
             // preview sample count
             let sampleCountList = [30, 50, 100, 300, 500, 700, 1000];
             let sampleCountTag = new com_String();
@@ -157,23 +295,58 @@ define([
             });
             $(page).find('#sampleCount').html(sampleCountTag.toString());
 
+            //================================================================
+            // Load state
+            //================================================================
+            Object.keys(this.state).forEach(key => {
+                let tag = $(page).find('#' + key);
+                let tagName = $(tag).prop('tagName'); // returns with UpperCase
+                let value = that.state[key];
+                if (value == undefined) {
+                    return;
+                }
+                switch(tagName) {
+                    case 'INPUT':
+                        let inputType = $(tag).prop('type');
+                        if (inputType == 'checkbox') {
+                            $(tag).prop('checked', value);
+                        } else {
+                            // if (inputType == 'text' || inputType == 'number' || inputType == 'hidden') {
+                            $(tag).val(value);
+                        }
+                        break;
+                    case 'TEXTAREA':
+                    case 'SELECT':
+                    default:
+                        $(tag).val(value);
+                        break;
+                }
+            });
+
             return page;
         }
 
         templateForSettingBox() {
-            return `<div class="vp-grid-border-box vp-grid-col-95">
-                <label for="figureWidth" class="">Figure size</label>
-                <div>
-                    <input type="number" id="figureWidth" class="vp-input m" placeholder="width" value="12">
-                    <input type="number" id="figureHeight" class="vp-input m" placeholder="height" value="8">
+            return `<div class="vp-grid-border-box vp-grid-col-95 vp-chart-setting-body">
+                    <label for="figureWidth" class="">Figure size</label>
+                    <div>
+                        <input type="number" id="figureWidth" class="vp-input m" placeholder="width" value="12">
+                        <input type="number" id="figureHeight" class="vp-input m" placeholder="height" value="8">
+                    </div>
+                    <label for="styleSheet" class="">Style sheet</label>
+                    <input type="text" class="vp-input" id="styleSheet" placeholder="style name" value="">
+                    <label for="fontName" class="">System font</label>
+                    <input type="text" class="vp-input" id="fontName" placeholder="font name" value="">
+                    <label for="fontSize" class="">Font size</label>
+                    <input type="number" id="fontSize" class="vp-input" placeholder="size" value="10">
+                </div>
+                <div class="vp-chart-setting-footer">
+                    <label>
+                        <input type="checkbox" id="setDefault">
+                        <span title="Set chart setting to default.">Set Default</span>
+                    </label>
                 </div>
-                <label for="styleSheet" class="">Style sheet</label>
-                <input type="text" class="vp-input" id="styleSheet" placeholder="style name" value="">
-                <label for="fontName" class="">System font</label>
-                <input type="text" class="vp-input" id="fontName" placeholder="font name" value="">
-                <label for="fontSize" class="">Font size</label>
-                <input type="number" id="fontSize" class="vp-input" placeholder="size" value="10">
-            </div>`;
+            `;
         }
 
         render() {
@@ -191,10 +364,10 @@ define([
             // set size
             $(this.wrapSelector('.vp-inner-popup-box')).css({ width: 400, height: 260});
 
-            this.renderImportOptions();
+            this.bindSettingBox();
         }
 
-        renderImportOptions() {
+        bindSettingBox() {
             //====================================================================
             // Stylesheet suggestinput
             //====================================================================
@@ -213,6 +386,7 @@ define([
                 suggestInput.setComponentID('styleSheet');
                 suggestInput.setSuggestList(function() { return varList; });
                 suggestInput.setPlaceholder('style name');
+                suggestInput.setValue('seaborn-darkgrid'); // set default (seaborn-darkgrid)
                 // suggestInput.setNormalFilter(false);
                 $(stylesheetTag).replaceWith(function() {
                     return suggestInput.toTagString();
@@ -243,6 +417,20 @@ define([
                     return suggestInput.toTagString();
                 });
             });
+
+            let that = this;
+            // setting popup - set default
+            $(this.wrapSelector('#setDefault')).on('change', function() {
+                let checked = $(this).prop('checked');
+
+                if (checked) {
+                    // disable input
+                    $(that.wrapSelector('.vp-chart-setting-body input')).prop('disabled', true);
+                } else {
+                    // enable input
+                    $(that.wrapSelector('.vp-chart-setting-body input')).prop('disabled', false);
+                }
+            });
         }
 
         handleInnerOk() {
@@ -292,55 +480,141 @@ define([
             var code = new com_String();
     
             // get parameters
-            var figWidth = $(this.wrapSelector('#figureWidth')).val();
-            var figHeight = $(this.wrapSelector('#figureHeight')).val();
-            var styleName = $(this.wrapSelector('#styleSheet')).val();
-            var fontName = $(this.wrapSelector('#fontName')).val();
-            var fontSize = $(this.wrapSelector('#fontSize')).val();
-    
-            code.appendLine('import matplotlib.pyplot as plt');
-            code.appendFormatLine("plt.rc('figure', figsize=({0}, {1}))", figWidth, figHeight);
-            if (styleName && styleName.length > 0) {
-                code.appendFormatLine("plt.style.use('{0}')", styleName);
-            }
-            code.appendLine();
-    
-            code.appendLine('from matplotlib import rcParams');
-            if (fontName && fontName.length > 0) {
-                code.appendFormatLine("rcParams['font.family'] = '{0}'", fontName);
-            }
-            if (fontSize && fontSize.length > 0) {
-                code.appendFormatLine("rcParams['font.size'] = {0}", fontSize);
+            let setDefault = $(this.wrapSelector('#setDefault')).prop('checked');
+            if (setDefault == true) {
+                code.appendLine('from matplotlib import rcParams, rcParamsDefault');
+                code.append('rcParams.update(rcParamsDefault)');
+            } else {
+                var figWidth = $(this.wrapSelector('#figureWidth')).val();
+                var figHeight = $(this.wrapSelector('#figureHeight')).val();
+                var styleName = $(this.wrapSelector('#styleSheet')).val();
+                var fontName = $(this.wrapSelector('#fontName')).val();
+                var fontSize = $(this.wrapSelector('#fontSize')).val();
+        
+                code.appendLine('import matplotlib.pyplot as plt');
+                code.appendLine('import seaborn as sns');
+                code.appendFormatLine("plt.rc('figure', figsize=({0}, {1}))", figWidth, figHeight);
+                if (styleName && styleName.length > 0) {
+                    code.appendFormatLine("plt.style.use('{0}')", styleName);
+                }
+                code.appendLine();
+        
+                code.appendLine('from matplotlib import rcParams');
+                if (fontName && fontName.length > 0) {
+                    code.appendFormatLine("rcParams['font.family'] = '{0}'", fontName);
+                }
+                if (fontSize && fontSize.length > 0) {
+                    code.appendFormatLine("rcParams['font.size'] = {0}", fontSize);
+                }
+                code.append("rcParams['axes.unicode_minus'] = False");
             }
-            code.append("rcParams['axes.unicode_minus'] = False");
     
-            return code.toString();
+            return [code.toString()];
         }
 
         generateCode(preview=false) {
-            let { chartType, data, x, y, userOption='', allocateTo='', useSampling } = this.state;
+            let { 
+                chartType, data, userOption='',
+                title, x_label, y_label, legendPos,
+                color, useGrid, gridColor, markerStyle,
+                x_limit_from, x_limit_to, y_limit_from, y_limit_to,
+                useSampling, sampleCount 
+            } = this.state;
+
+            let indent = '';
             let code = new com_String();
             let config = this.chartConfig[chartType];
+            let state = JSON.parse(JSON.stringify(this.state));
+
+            let chartCode = new com_String();
+
+            let etcOptionCode = []
+            if (color != '') {
+                etcOptionCode.push(com_util.formatString("color='{0}'", color));
+            }
+            if (markerStyle != '') {
+                // TODO: marker to seaborn argument (ex. marker='+' / markers={'Lunch':'s', 'Dinner':'X'})
+                etcOptionCode.push(com_util.formatString("marker='{0}'", markerStyle));
+            }
+
+            // add user option
+            if (userOption != '') {
+                etcOptionCode.push(userOption);
+            }
 
-            let chartCode = com_generator.vp_codeGenerator(this, config, this.state, (userOption != ''? ', ' + userOption : ''));
+            if (etcOptionCode.length > 0) {
+                etcOptionCode = [
+                    '',
+                    ...etcOptionCode
+                ]
+            }
+
+            let generatedCode = com_generator.vp_codeGenerator(this, config, state, etcOptionCode.join(', '));
+
+            // Info
+            if (title && title != '') {
+                chartCode.appendFormatLine("plt.title('{0}')", title);
+            }
+            if (x_label && x_label != '') {
+                chartCode.appendFormatLine("plt.xlabel('{0}')", x_label);
+            }
+            if (y_label && y_label != '') {
+                chartCode.appendFormatLine("plt.ylabel('{0}')", y_label);
+            }
+            if (x_limit_from != '' && x_limit_to != '') {
+                chartCode.appendFormatLine("plt.xlim(({0}, {1}))", x_limit_from, x_limit_to);
+            }
+            if (y_limit_from != '' && y_limit_to != '') {
+                chartCode.appendFormatLine("plt.ylim(({0}, {1}))", y_limit_from, y_limit_to);
+            }
+            if (legendPos != '') {
+                chartCode.appendFormatLine("plt.legend(loc='{0}')", legendPos);
+            }
+            // Style - Grid
+            // plt.grid(True, axis='x', color='red', alpha=0.5, linestyle='--')
+            let gridCodeList = [];
+            if (useGrid != '') {
+                gridCodeList.push(useGrid);
+            }
+            if (gridColor != '') {
+                gridCodeList.push(com_util.formatString("color='{0}'", gridColor));
+            }
+            if (gridCodeList.length > 0) {
+                chartCode.appendFormatLine("plt.grid({0})", gridCodeList.join(', '));
+            }
+            chartCode.append('plt.show()');
 
             let convertedData = data;
             if (preview) {
+                // set indent
+                indent = ' '.repeat(4);
+
+                // Ignore warning
+                code.appendLine('import warnings');
+                code.appendLine('with warnings.catch_warnings():');
+                code.appendFormatLine("{0}warnings.simplefilter('ignore')", indent);
+
                 // set figure size for preview chart
-                code.appendLine('plt.figure(figsize=(6, 4))');
+                let defaultWidth = 8;
+                let defaultHeight = 6;
+                code.appendFormatLine('{0}plt.figure(figsize=({1}, {2}))', indent, defaultWidth, defaultHeight);
                 if (useSampling) {
                     // data sampling code for preview
-                    convertedData = data + '.sample(n=30, random_state=0)';
+                    convertedData = data + '.sample(n=' + sampleCount + ', random_state=0)';
+                    // replace pre-defined options
+                    generatedCode = generatedCode.replaceAll(data, convertedData);
                 }   
-            }
-
-            // replace pre-defined options
-            chartCode = chartCode.replace(data, convertedData);
 
-            code.appendLine(chartCode);
-            code.append('plt.show()');
+                code.appendFormatLine("{0}{1}", indent, generatedCode);
+                code.appendFormatLine("{0}{1}", indent, chartCode.toString().replaceAll('\n', '\n' + indent));
+                
+            } else {
+                code.appendLine(generatedCode);
+                code.appendLine(chartCode.toString());
+            }
 
-            return code.toString();
+            // remove last Enter(\n) from code and then run it
+            return code.toString().replace(/\n+$/, "");
         }
         
     }


Test patch:
diff --git a/data/libraries_new.json b/data/libraries_test.json
similarity index 99%
rename from data/libraries_new.json
rename to data/libraries_test.json
index 6fc6b0c5..99b476eb 100644
--- a/data/libraries_new.json
+++ b/data/libraries_test.json
@@ -2850,24 +2850,14 @@
                         "desc" : "Matplotlib Visualization",
                         "item" : [
                             {
-                                "id": "mp_importMatplotlib",
-                                "type": "function",
-                                "level": 2,
-                                "name": "import",
-                                "path": "visualpython - library - matplotlib - import matplotlib",
-                                "desc": "",
-                                "tag": "IMPORT MATPLOTLIB",
-                                "file": "m_matplotlib/import"
-                            },
-                            {
-                                "id": "mp_plot",
+                                "id": "mp_chart",
                                 "type": "function",
                                 "level": 2,
                                 "name": "Create chart",
                                 "path": "visualpython - library - matplotlib - plot",
                                 "desc": "",
                                 "tag": "MATPLOTLIB, PLOT, CHART",
-                                "file": "m_matplotlib/plot"
+                                "file": "m_visualize/Chart"
                             },
                             {
                                 "id": "mp_figure",
@@ -3074,6 +3064,20 @@
                             "color": 4,
                             "icon": "apps/apps_profiling.svg"
                         }
+                    },
+                    {
+                        "id"   : "apps_sample",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Sample",
+                        "tag"  : "SAMPLE,APPS",
+                        "path" : "visualpython - apps - sample",
+                        "desc" : "TODO: remove it (this is sample)",
+                        "file" : "m_apps/SampleApp",
+                        "apps" : {
+                            "color": 4,
+                            "icon": "apps/apps_white.svg"
+                        }
                     }
                 ]
             },
@@ -3097,38 +3101,10 @@
                         "desc" : "Chart style setting",
                         "file" : "m_visualize/ChartSetting",
                         "apps" : {
-                            "color": 1,
+                            "color": 5,
                             "icon": "apps/apps_style.svg"
                         }
                     },
-                    {
-                        "id"   : "pd_plot",
-                        "type" : "function",
-                        "level": 1,
-                        "name" : "Pandas Plot",
-                        "tag"  : "PANDAS PLOT,PANDAS",
-                        "path" : "visualpython - library - pandas - plot",
-                        "desc" : "Pandas plot creation",
-                        "file" : "m_library/m_pandas/plot",
-                        "apps" : {
-                            "color": 1,
-                            "icon": "apps/apps_chart.svg"
-                        }
-                    },
-                    {
-                        "id"   : "visualize_chart",
-                        "type" : "function",
-                        "level": 1,
-                        "name" : "Matplotlib",
-                        "tag"  : "MATPLOTLIB,CHART,VISUALIZATION,VISUALIZE",
-                        "path" : "visualpython - visualization - matplotlib",
-                        "desc" : "Matplotlib chart creation",
-                        "file" : "m_apps/Chart",
-                        "apps" : {
-                            "color": 1,
-                            "icon": "apps/apps_chart.svg"
-                        }
-                    },
                     {
                         "id"   : "visualize_seaborn",
                         "type" : "function",
@@ -3139,8 +3115,8 @@
                         "desc" : "Seaborn chart creation",
                         "file" : "m_visualize/Seaborn",
                         "apps" : {
-                            "color": 1,
-                            "icon": "apps/apps_chart.svg"
+                            "color": 5,
+                            "icon": "apps/apps_visualize.svg"
                         }
                     }
                 ]
@@ -3165,10 +3141,24 @@
                         "desc" : "Data sets for machine learning",
                         "file" : "m_ml/DataSets",
                         "apps" : {
-                            "color": 5,
+                            "color": 6,
                             "icon": "apps/apps_dataset.svg"
                         }
                     },
+                    {
+                        "id"   : "ml_dataSplit",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Data Split",
+                        "tag"  : "DATA SPLIT,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - data split",
+                        "desc" : "Data split for machine learning",
+                        "file" : "m_ml/dataSplit",
+                        "apps" : {
+                            "color": 6,
+                            "icon": "apps/apps_datasplit.svg"
+                        }
+                    },
                     {
                         "id"   : "ml_dataPrep",
                         "type" : "function",
@@ -3179,22 +3169,22 @@
                         "desc" : "Data preparation for machine learning",
                         "file" : "m_ml/DataPrep",
                         "apps" : {
-                            "color": 5,
+                            "color": 6,
                             "icon": "apps/apps_dataprep.svg"
                         }
                     },
                     {
-                        "id"   : "ml_dataSplit",
+                        "id"   : "ml_autoML",
                         "type" : "function",
                         "level": 1,
-                        "name" : "Data Split",
-                        "tag"  : "DATA SPLIT,MACHINE LEARNING,ML",
-                        "path" : "visualpython - machine_learning - data split",
-                        "desc" : "Data split for machine learning",
-                        "file" : "m_ml/dataSplit",
+                        "name" : "AutoML",
+                        "tag"  : "AUTO ML,MODEL,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - automl",
+                        "desc" : "AutoML model for machine learning",
+                        "file" : "m_ml/AutoML",
                         "apps" : {
-                            "color": 5,
-                            "icon": "apps/apps_datasplit.svg"
+                            "color": 6,
+                            "icon": "apps/apps_automl.svg"
                         }
                     },
                     {
@@ -3207,7 +3197,7 @@
                         "desc" : "Regression model for machine learning",
                         "file" : "m_ml/Regression",
                         "apps" : {
-                            "color": 5,
+                            "color": 7,
                             "icon": "apps/apps_regression.svg"
                         }
                     },
@@ -3221,7 +3211,7 @@
                         "desc" : "Classification model for machine learning",
                         "file" : "m_ml/Classification",
                         "apps" : {
-                            "color": 6,
+                            "color": 7,
                             "icon": "apps/apps_classification.svg"
                         }
                     },
@@ -3235,7 +3225,7 @@
                         "desc" : "Clustering model for machine learning",
                         "file" : "m_ml/Clustering",
                         "apps" : {
-                            "color": 6,
+                            "color": 7,
                             "icon": "apps/apps_clustering.svg"
                         }
                     },
@@ -3249,22 +3239,36 @@
                         "desc" : "Dimension reduction model for machine learning",
                         "file" : "m_ml/DimensionReduction",
                         "apps" : {
-                            "color": 6,
+                            "color": 7,
                             "icon": "apps/apps_dimension.svg"
                         }
                     },
                     {
-                        "id"   : "ml_autoML",
+                        "id"   : "ml_fitPredict",
                         "type" : "function",
                         "level": 1,
-                        "name" : "AutoML",
-                        "tag"  : "AUTO ML,MODEL,MACHINE LEARNING,ML",
-                        "path" : "visualpython - machine_learning - automl",
-                        "desc" : "AutoML model for machine learning",
-                        "file" : "m_ml/AutoML",
+                        "name" : "Fit/Predict",
+                        "tag"  : "FIT,PREDICT,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - fit_predict",
+                        "desc" : "Model fit/predict for machine learning",
+                        "file" : "m_ml/FitPredict",
                         "apps" : {
-                            "color": 6,
-                            "icon": "apps/apps_automl.svg"
+                            "color": 8,
+                            "icon": "apps/apps_fit.svg"
+                        }
+                    },
+                    {
+                        "id"   : "ml_modelInfo",
+                        "type" : "function",
+                        "level": 1,
+                        "name" : "Model Info",
+                        "tag"  : "MODEL INFO,INFORMATION,MACHINE LEARNING,ML",
+                        "path" : "visualpython - machine_learning - model_info",
+                        "desc" : "Model information for machine learning",
+                        "file" : "m_ml/ModelInfo",
+                        "apps" : {
+                            "color": 8,
+                            "icon": "apps/apps_predict.svg"
                         }
                     },
                     {
@@ -3277,7 +3281,7 @@
                         "desc" : "Performance evaluation for machine learning",
                         "file" : "m_ml/evaluation",
                         "apps" : {
-                            "color": 7,
+                            "color": 8,
                             "icon": "apps/apps_evaluate.svg"
                         }
                     }