@@ -87,7 +87,8 @@ define([
87
87
{ id : 'add_row' , label : 'Add row' , selection : FRAME_SELECT_TYPE . NONE , menuType : FRAME_EDIT_TYPE . ADD_ROW } ,
88
88
{ id : 'delete' , label : 'Delete' , selection : FRAME_SELECT_TYPE . MULTI , menuType : FRAME_EDIT_TYPE . DROP } ,
89
89
{ id : 'rename' , label : 'Rename' , selection : FRAME_SELECT_TYPE . NONE , menuType : FRAME_EDIT_TYPE . RENAME } ,
90
- { id : 'asType' , label : 'As type' , selection : FRAME_SELECT_TYPE . NONE , axis : FRAME_AXIS . COLUMN , menuType : FRAME_EDIT_TYPE . AS_TYPE } ,
90
+ { id : 'as_type' , label : 'As type' , selection : FRAME_SELECT_TYPE . NONE , axis : FRAME_AXIS . COLUMN , menuType : FRAME_EDIT_TYPE . AS_TYPE } ,
91
+ { id : 'to_datetime' , label : 'To datetime' , selection : FRAME_SELECT_TYPE . SINGLE , axis : FRAME_AXIS . COLUMN , menuType : FRAME_EDIT_TYPE . TO_DATETIME } ,
91
92
{ id : 'replace' , label : 'Replace' , selection : FRAME_SELECT_TYPE . SINGLE , axis : FRAME_AXIS . COLUMN , menuType : FRAME_EDIT_TYPE . REPLACE } ,
92
93
{ id : 'discretize' , label : 'Discretize' , selection : FRAME_SELECT_TYPE . SINGLE , axis : FRAME_AXIS . COLUMN , numeric_only : true , menuType : FRAME_EDIT_TYPE . DISCRETIZE }
93
94
]
@@ -618,6 +619,7 @@ define([
618
619
case FRAME_EDIT_TYPE . RENAME :
619
620
case FRAME_EDIT_TYPE . REPLACE :
620
621
case FRAME_EDIT_TYPE . AS_TYPE :
622
+ case FRAME_EDIT_TYPE . TO_DATETIME :
621
623
case FRAME_EDIT_TYPE . DISCRETIZE :
622
624
case FRAME_EDIT_TYPE . DATA_SHIFT :
623
625
case FRAME_EDIT_TYPE . SORT_INDEX :
@@ -1106,6 +1108,73 @@ define([
1106
1108
$ ( that . wrapSelector ( '.vp-inner-popup-fill-row' ) ) . hide ( ) ;
1107
1109
}
1108
1110
} ) ;
1111
+ } else if ( menuType === FRAME_EDIT_TYPE . TO_DATETIME ) {
1112
+ // bind event for selecting format
1113
+ $ ( this . wrapSelector ( '.vp-inner-popup-todt-format' ) ) . on ( 'change' , function ( ) {
1114
+ let format = $ ( this ) . val ( ) ;
1115
+ if ( format === 'auto' ) {
1116
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-dayfirst' ) ) . prop ( 'disabled' , false ) ;
1117
+ } else {
1118
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-dayfirst' ) ) . prop ( 'disabled' , true ) ;
1119
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-dayfirst' ) ) . val ( '' ) ;
1120
+ }
1121
+
1122
+ if ( format === 'typing' ) {
1123
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-format-typing' ) ) . prop ( 'disabled' , false ) ;
1124
+ } else {
1125
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-format-typing' ) ) . prop ( 'disabled' , true ) ;
1126
+ }
1127
+ } ) ;
1128
+
1129
+ // bind event for checking add column
1130
+ $ ( this . wrapSelector ( '.vp-inner-popup-todt-use-addcol' ) ) . on ( 'change' , function ( ) {
1131
+ let checked = $ ( this ) . prop ( 'checked' ) ;
1132
+ if ( checked === true ) {
1133
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-addcol-box' ) ) . show ( ) ;
1134
+ } else {
1135
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-addcol-box' ) ) . hide ( ) ;
1136
+ }
1137
+ } ) ;
1138
+
1139
+ // Add column set event
1140
+ $ ( this . wrapSelector ( '.vp-inner-popup-todt-addcol' ) ) . on ( 'click' , function ( ) {
1141
+ let dateTypeList = [ // df[col].dt[{dateType}]
1142
+ { label : 'Year' , value : 'year' } ,
1143
+ { label : 'Month' , value : 'month' } ,
1144
+ { label : 'Day' , value : 'day' } ,
1145
+ { label : 'Date' , value : 'date' } ,
1146
+ { label : 'DayOfWeek' , value : 'dayofweek' } ,
1147
+ { label : 'DayOfYear' , value : 'dayofyear' } ,
1148
+ { label : 'DaysInMonth' , value : 'daysinmonth' } ,
1149
+ { label : 'Quarter' , value : 'quarter' } ,
1150
+ { label : 'Time' , value : 'time' } ,
1151
+ { label : 'Hour' , value : 'hour' } ,
1152
+ { label : 'Minute' , value : 'minute' } ,
1153
+ { label : 'Second' , value : 'second' } ,
1154
+ { label : 'Nanosecond' , value : 'nanosecond' } ,
1155
+ ] ;
1156
+ let dateTypeOptionTag = new com_String ( ) ;
1157
+ dateTypeList . forEach ( opt => {
1158
+ dateTypeOptionTag . appendFormat ( '<option value="{0}">{1}</option>' , opt . value , opt . label ) ;
1159
+ } ) ;
1160
+
1161
+ let addColItemTag = $ ( `<div class="vp-inner-popup-todt-addcol-item">
1162
+ <input type="text" class="vp-input vp-inner-popup-todt-addcol-colname" placeholder="Type column name" />
1163
+ <select class="vp-select vp-inner-popup-todt-addcol-type">
1164
+ ${ dateTypeOptionTag . toString ( ) }
1165
+ </select>
1166
+ <span class="vp-icon-close-small vp-inner-popup-todt-addcol-del mt5 vp-cursor"></span>
1167
+ </div>` ) ;
1168
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-addcol-content' ) ) . append ( addColItemTag ) ;
1169
+ $ ( addColItemTag ) [ 0 ] . scrollIntoView ( ) ;
1170
+
1171
+ // bind event for deleting
1172
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-addcol-del' ) ) . off ( 'click' ) ;
1173
+ $ ( that . wrapSelector ( '.vp-inner-popup-todt-addcol-del' ) ) . on ( 'click' , function ( ) {
1174
+ // delete item
1175
+ $ ( this ) . closest ( '.vp-inner-popup-todt-addcol-item' ) . remove ( ) ;
1176
+ } ) ;
1177
+ } ) ;
1109
1178
}
1110
1179
1111
1180
}
@@ -2113,6 +2182,75 @@ define([
2113
2182
return content . toString ( ) ;
2114
2183
}
2115
2184
2185
+ renderToDatetime ( ) {
2186
+ var content = new com_String ( ) ;
2187
+ let formatList = [
2188
+ { label : 'Auto' , value : 'auto' } ,
2189
+ { label : 'Year' , value : '%Y' } ,
2190
+ { label : 'Month' , value : '%m' } ,
2191
+ { label : 'Day' , value : '%d' } ,
2192
+ { label : 'Day Of Week' , value : '%w' } ,
2193
+ { label : '%Y/%m/%d' , value : '%Y/%m/%d' } ,
2194
+ { label : '%Y-%m-%d' , value : '%Y-%m-%d' } ,
2195
+ { label : '%d/%m/%Y' , value : '%d/%m/%Y' } ,
2196
+ { label : '%d-%m-%Y' , value : '%d-%m-%Y' } ,
2197
+ { label : 'Typing' , value : 'typing' } ,
2198
+ ] ;
2199
+ let formatOptionTag = new com_String ( ) ;
2200
+ formatList . forEach ( opt => {
2201
+ formatOptionTag . appendFormat ( '<option value="{0}">{1}</option>' , opt . value , opt . label ) ;
2202
+ } ) ;
2203
+
2204
+ content . appendFormat ( `<div class="vp-inner-popup-todt vp-grid-box">
2205
+ <div class="vp-grid-col-110">
2206
+ <label>Target column</label>
2207
+ <input type="text" class="vp-input" value="{0}" readonly />
2208
+ </div>
2209
+ <div class="vp-grid-col-110">
2210
+ <label>Format</label>
2211
+ <div>
2212
+ <select class="vp-inner-popup-todt-format">
2213
+ {1}
2214
+ </select>
2215
+ <input type="text" class="vp-input vp-inner-popup-todt-format-typing" value="" placeholder="Type format" disabled/>
2216
+ </div>
2217
+ </div>
2218
+ <div class="vp-grid-col-110">
2219
+ <label>Day first</label>
2220
+ <select class="vp-inner-popup-todt-dayfirst">
2221
+ <option value="">Select option...</option>
2222
+ <option value="True">True</option>
2223
+ <option value="False">False</option>
2224
+ </select>
2225
+ </div>
2226
+ <hr style="margin: 5px 0;"/>
2227
+ <div>
2228
+ <label>
2229
+ <input type="checkbox" class="vp-inner-popup-todt-use-addcol" />
2230
+ <span>
2231
+ Add column with date type
2232
+ </span>
2233
+ </label>
2234
+ </div>
2235
+ <div class="vp-inner-popup-todt-addcol-box vp-grid-border-box" style="display: none;">
2236
+ <div class="vp-inner-popup-todt-addcol-head">
2237
+ <label>New column name</label>
2238
+ <label>Date type</label>
2239
+ <label></label>
2240
+ </div>
2241
+ <div class="vp-inner-popup-todt-addcol-content vp-scrollbar">
2242
+
2243
+ </div>
2244
+ <button class="vp-button vp-inner-popup-todt-addcol">+ Add column</button>
2245
+ </div>
2246
+ </div>
2247
+ ` , this . state . selected [ 0 ] . label , formatOptionTag . toString ( ) , ) ;
2248
+
2249
+ // set content
2250
+ $ ( this . wrapSelector ( '.vp-inner-popup-body' ) ) . html ( content . toString ( ) ) ;
2251
+ return content . toString ( ) ;
2252
+ }
2253
+
2116
2254
renderFillNAPage ( ) {
2117
2255
var content = new com_String ( ) ;
2118
2256
content . appendFormatLine ( '<div class="{0}">' , 'vp-inner-popup-fillna-page' ) ;
@@ -2454,6 +2592,11 @@ define([
2454
2592
title = 'Convert type' ;
2455
2593
content = this . renderAsType ( ) ;
2456
2594
break ;
2595
+ case FRAME_EDIT_TYPE . TO_DATETIME :
2596
+ title = 'Convert to datetime' ;
2597
+ size = { width : 500 , height : 450 } ;
2598
+ content = this . renderToDatetime ( ) ;
2599
+ break ;
2457
2600
case FRAME_EDIT_TYPE . FILL_NA :
2458
2601
title = 'Fill NA' ;
2459
2602
content = this . renderFillNAPage ( ) ;
@@ -2823,6 +2966,22 @@ define([
2823
2966
}
2824
2967
} ) ;
2825
2968
break ;
2969
+ case FRAME_EDIT_TYPE . TO_DATETIME :
2970
+ content [ 'format' ] = $ ( this . wrapSelector ( '.vp-inner-popup-todt-format' ) ) . val ( ) ;
2971
+ content [ 'format_typing' ] = $ ( this . wrapSelector ( '.vp-inner-popup-todt-format-typing' ) ) . val ( ) ;
2972
+ content [ 'dayfirst' ] = $ ( this . wrapSelector ( '.vp-inner-popup-todt-dayfirst' ) ) . val ( ) ;
2973
+ content [ 'use_addcol' ] = $ ( this . wrapSelector ( '.vp-inner-popup-todt-use-addcol' ) ) . prop ( 'checked' ) ;
2974
+ var colList = [ ] ;
2975
+ var addcolItemTags = $ ( this . wrapSelector ( '.vp-inner-popup-todt-addcol-item' ) ) ;
2976
+ addcolItemTags && addcolItemTags . each ( ( idx , tag ) => {
2977
+ let colName = $ ( tag ) . find ( '.vp-inner-popup-todt-addcol-colname' ) . val ( ) ;
2978
+ let dateType = $ ( tag ) . find ( '.vp-inner-popup-todt-addcol-type' ) . val ( ) ;
2979
+ if ( colName !== '' && dateType !== '' ) {
2980
+ colList . push ( { colName : colName , dateType : dateType } ) ;
2981
+ }
2982
+ } ) ;
2983
+ content [ 'collist' ] = colList ;
2984
+ break ;
2826
2985
case FRAME_EDIT_TYPE . DISCRETIZE :
2827
2986
content [ 'input' ] = $ ( this . wrapSelector ( '.vp-inner-popup-input' ) ) . val ( ) ;
2828
2987
content [ 'inputastext' ] = $ ( this . wrapSelector ( '.vp-inner-popup-inputastext' ) ) . prop ( 'checked' ) ;
@@ -3343,6 +3502,31 @@ define([
3343
3502
} ) ;
3344
3503
code . appendFormat ( "{0} = {1}.astype({{2}})" , tempObj , tempObj , astypeStr . toString ( ) ) ;
3345
3504
break ;
3505
+ case FRAME_EDIT_TYPE . TO_DATETIME :
3506
+ code . appendFormat ( "{0}[{1}] = pd.to_datetime({2}[{3}]" , tempObj , selectedName , tempObj , selectedName ) ;
3507
+ let optionList = [ ] ;
3508
+ if ( content [ 'format' ] === 'auto' ) {
3509
+ if ( content [ 'dayfirst' ] !== '' ) {
3510
+ optionList . push ( `dayfirst=${ content [ 'dayfirst' ] } ` ) ;
3511
+ }
3512
+ } else if ( content [ 'format' ] === 'typing' ) {
3513
+ if ( content [ 'format_typing' ] !== '' ) {
3514
+ optionList . push ( `format='${ content [ 'format_typing' ] } '` ) ;
3515
+ }
3516
+ } else {
3517
+ optionList . push ( `format='${ content [ 'format' ] } '` ) ;
3518
+ }
3519
+ if ( optionList . length > 0 ) {
3520
+ code . appendFormat ( ', {0}' , optionList . join ( ', ' ) ) ;
3521
+ }
3522
+ code . append ( ')' ) ;
3523
+ if ( content [ 'use_addcol' ] === true && content [ 'collist' ] . length > 0 ) {
3524
+ content [ 'collist' ] . forEach ( obj => {
3525
+ code . appendLine ( ) ;
3526
+ code . appendFormat ( "{0}['{1}'] = {2}[{3}].dt.{4}" , tempObj , obj . colName , tempObj , selectedName , obj . dateType ) ;
3527
+ } ) ;
3528
+ }
3529
+ break ;
3346
3530
case FRAME_EDIT_TYPE . DISCRETIZE :
3347
3531
let newColumn = com_util . convertToStr ( content [ 'input' ] , content [ 'inputastext' ] ) ;
3348
3532
let method = content [ 'type' ] ;
@@ -3437,7 +3621,7 @@ define([
3437
3621
var indexList = data . index ;
3438
3622
var dataList = data . data ;
3439
3623
3440
- columnList = columnList . map ( col => { return { label : col . label , type : col . dtype , code : col . value } } ) ;
3624
+ columnList = columnList . map ( col => { return { label : col . label , type : col . dtype , code : col . value , isNumeric : col . is_numeric } } ) ;
3441
3625
indexList = indexList . map ( idx => { return { label : idx , code : idx } } ) ;
3442
3626
3443
3627
if ( ! more ) {
@@ -3453,6 +3637,12 @@ define([
3453
3637
while ( colIdx < columnList . length ) {
3454
3638
let col = columnList [ colIdx ] ;
3455
3639
let colCode = col . code . slice ( 0 , colLevIdx + 1 ) . join ( ',' ) ;
3640
+ var colIcon = '' ;
3641
+ if ( col . isNumeric === true ) {
3642
+ colIcon = '<span class="vp-fe-table-column-isnumeric vp-icon-numeric" title="Numeric column"></span>' ;
3643
+ } else {
3644
+ colIcon = '<span class="vp-fe-table-column-isnumeric vp-icon-non-numeric" title="Non-numeric column"></span>' ;
3645
+ }
3456
3646
let nextCol = columnList [ colIdx + 1 ] ;
3457
3647
if ( nextCol && nextCol . code . slice ( 0 , colLevIdx + 1 ) . join ( ',' ) === colCode ) {
3458
3648
colSpan ++ ;
@@ -3467,8 +3657,8 @@ define([
3467
3657
} else {
3468
3658
colClass = VP_FE_TABLE_COLUMN_GROUP ;
3469
3659
}
3470
- table . appendFormatLine ( '<th data-code="({0})" data-axis="{1}" data-type="{2}" data-parent="{3}" data-label="{4}" class="{5} {6}" colspan="{7}">{8}</th>'
3471
- , colCode , FRAME_AXIS . COLUMN , col . type , col . label [ colLevIdx - 1 ] , col . label [ colLevIdx ] , colClass , selected , colSpan , col . label [ colLevIdx ] ) ;
3660
+ table . appendFormatLine ( '<th data-code="({0})" data-axis="{1}" data-type="{2}" data-parent="{3}" data-label="{4}" class="{5} {6}" colspan="{7}">{8}{9} </th>'
3661
+ , colCode , FRAME_AXIS . COLUMN , col . type , col . label [ colLevIdx - 1 ] , col . label [ colLevIdx ] , colClass , selected , colSpan , colIcon , col . label [ colLevIdx ] ) ;
3472
3662
colSpan = 1 ;
3473
3663
}
3474
3664
colIdx ++ ;
@@ -3487,12 +3677,18 @@ define([
3487
3677
table . appendLine ( '<tr><th></th>' ) ;
3488
3678
columnList && columnList . forEach ( col => {
3489
3679
var colCode = col . code ;
3680
+ var colIcon = '' ;
3681
+ if ( col . isNumeric === true ) {
3682
+ colIcon = '<span class="vp-fe-table-column-isnumeric vp-icon-numeric" title="Numeric column"></span>' ;
3683
+ } else {
3684
+ colIcon = '<span class="vp-fe-table-column-isnumeric vp-icon-non-numeric" title="Non-numeric column"></span>' ;
3685
+ }
3490
3686
var colClass = '' ;
3491
3687
if ( that . state . axis == FRAME_AXIS . COLUMN && that . state . selected . map ( col => col . code ) . includes ( colCode ) ) {
3492
3688
colClass = 'selected' ;
3493
3689
}
3494
- table . appendFormatLine ( '<th data-code="{0}" data-axis="{1}" data-type="{2}" data-label="{3}" class="{4} {5}">{6}</th>'
3495
- , colCode , FRAME_AXIS . COLUMN , col . type , col . label , VP_FE_TABLE_COLUMN , colClass , col . label ) ;
3690
+ table . appendFormatLine ( '<th data-code="{0}" data-axis="{1}" data-type="{2}" data-label="{3}" class="{4} {5}">{6}{7} </th>'
3691
+ , colCode , FRAME_AXIS . COLUMN , col . type , col . label , VP_FE_TABLE_COLUMN , colClass , colIcon , col . label ) ;
3496
3692
} ) ;
3497
3693
// // add column
3498
3694
table . appendFormatLine ( '<th class="{0}"><div class="{1}"></div></th>' , VP_FE_ADD_COLUMN , 'vp-icon-plus' ) ;
@@ -3713,6 +3909,7 @@ define([
3713
3909
DROP : 3 ,
3714
3910
RENAME : 2 ,
3715
3911
AS_TYPE : 10 ,
3912
+ TO_DATETIME : 19 ,
3716
3913
REPLACE : 9 ,
3717
3914
DISCRETIZE : 15 ,
3718
3915
0 commit comments