1+ define ( [
2+ 'css!vp_base/css/component/instanceEditor.css' ,
3+ 'vp_base/js/com/com_String' ,
4+ 'vp_base/js/com/com_util' ,
5+ 'vp_base/js/com/com_generatorV2' ,
6+ 'vp_base/js/com/component/Component' ,
7+ 'vp_base/js/com/component/SuggestInput'
8+ ] , function ( insCss , com_String , com_util , com_generator , Component , SuggestInput ) {
9+
10+ // temporary const
11+ const VP_INS_BOX = 'vp-ins-box' ;
12+ const VP_INS_SELECT_CONTAINER = 'vp-ins-select-container' ;
13+ const VP_INS_SELECT_TITLE = 'vp-ins-select-title' ;
14+ const VP_INS_SEARCH = 'vp-ins-search' ;
15+ const VP_INS_TYPE = 'vp-ins-type' ;
16+ const VP_INS_SELECT_BOX = 'vp-ins-select-box' ;
17+ const VP_INS_SELECT_LIST = 'vp-ins-select-list' ;
18+ const VP_INS_SELECT_ITEM = 'vp-ins-select-item' ;
19+
20+ const VP_INS_PARAMETER_BOX = 'vp-ins-parameter-box' ;
21+ const VP_INS_PARAMETER = 'vp-ins-parameter' ;
22+
23+ const VP_CREATE_VAR_BOX = 'vp-create-var-box' ;
24+ const VP_CREATE_VAR = 'vp-create-var' ;
25+ const VP_CREATE_VAR_BTN = 'vp-create-var-btn' ;
26+
27+ class ModelEditor extends Component {
28+ constructor ( pageThis , targetId , containerId = 'vp_wrapper' ) {
29+ super ( null , { pageThis :pageThis , targetId :targetId , containerId :containerId } ) ;
30+ }
31+
32+ _init ( ) {
33+ super . _init ( ) ;
34+
35+ this . pageThis = this . state . pageThis ;
36+ this . targetId = this . state . targetId ;
37+ this . containerId = this . state . containerId ;
38+
39+ this . state = {
40+ action :{ } ,
41+ info :{ } ,
42+ config :{ } ,
43+ ...this . state
44+ }
45+ }
46+
47+ render ( ) {
48+ ;
49+ }
50+
51+ getModelCategory ( modelType ) {
52+ let mlDict = vpConfig . getMLDataDict ( ) ;
53+ let keys = Object . keys ( mlDict ) ;
54+ let modelCategory = '' ;
55+ for ( let i = 0 ; i < keys . length ; i ++ ) {
56+ let key = keys [ i ] ;
57+ if ( mlDict [ key ] . includes ( modelType ) ) {
58+ modelCategory = key ;
59+ break ;
60+ }
61+ }
62+ return modelCategory ;
63+ }
64+
65+ getAction ( modelType ) {
66+ let category = this . getModelCategory ( modelType ) ;
67+ let defaultActions = {
68+ 'fit' :{
69+ name :'fit' ,
70+ code :'${model}.fit(${featureData}, ${targetData})' ,
71+ options :[
72+ { name :'featureData' , component :[ 'var_select' ] , var_type :[ 'DataFrame' ] , default :'X_train' } ,
73+ { name :'targetData' , component :[ 'var_select' ] , var_type :[ 'DataFrame' ] , default :'y_train' }
74+ ]
75+ } ,
76+ 'predict' :{
77+ name :'predict' ,
78+ code :'${model}.predict(${featureData})' ,
79+ options :[
80+ { name :'featureData' , component :[ 'var_select' ] , var_type :[ 'DataFrame' ] , default :'X_train' }
81+ ]
82+ } ,
83+ 'predict_proba' :{
84+ name :'predict_proba' ,
85+ code :'${model}.predict_proba(${featureData})' ,
86+ options :[
87+ { name :'featureData' , component :[ 'var_select' ] , var_type :[ 'DataFrame' ] , default :'X_train' }
88+ ]
89+ } ,
90+ 'transform' :{
91+ name :'transform' ,
92+ code :'${model}.transform(${featureData})' ,
93+ options :[
94+ { name :'featureData' , component :[ 'var_select' ] , var_type :[ 'DataFrame' ] , default :'X_train' }
95+ ]
96+ }
97+ } ;
98+ let actions = { } ;
99+ switch ( category ) {
100+ case 'Regression' :
101+ actions = {
102+ 'fit' :defaultActions [ 'fit' ] ,
103+ 'predict' :defaultActions [ 'predict' ] ,
104+ }
105+ break ;
106+ case 'Classification' :
107+ actions = {
108+ 'fit' :defaultActions [ 'fit' ] ,
109+ 'predict' :defaultActions [ 'predict' ] ,
110+ 'predict_proba' :defaultActions [ 'predict_proba' ] ,
111+ }
112+ break ;
113+ case 'Auto ML' :
114+ actions = {
115+ 'fit' :defaultActions [ 'fit' ] ,
116+ 'predict' :defaultActions [ 'predict' ] ,
117+ }
118+ break ;
119+ case 'Clustering' :
120+ actions = {
121+ 'fit' :defaultActions [ 'fit' ] ,
122+ 'predict' :defaultActions [ 'predict' ] ,
123+ }
124+ break ;
125+ case 'Dimension Reduction' :
126+ actions = {
127+ 'fit' :defaultActions [ 'fit' ] ,
128+ 'transform' :defaultActions [ 'transform' ] ,
129+ }
130+ break ;
131+ }
132+ return actions ;
133+ }
134+
135+ getInfo ( modelType ) {
136+ let category = this . getModelCategory ( modelType ) ;
137+ let infos = { } ;
138+ let defaultInfos = {
139+ 'score' :{
140+ name :'score' ,
141+ code :'${model}.score()' ,
142+ options :[
143+
144+ ]
145+ }
146+ }
147+ switch ( category ) {
148+ case 'Regression' :
149+ infos = {
150+ 'score' :defaultInfos [ 'score' ]
151+ }
152+ break ;
153+ case 'Classification' :
154+ break ;
155+ case 'Auto ML' :
156+ break ;
157+ case 'Clustering' :
158+ break ;
159+ case 'Dimension Reduction' :
160+ break ;
161+ }
162+ return infos ;
163+ }
164+
165+ renderPage ( ) {
166+ var tag = new com_String ( ) ;
167+ tag . appendFormatLine ( '<div class="{0} {1}">' , VP_INS_BOX , this . uuid ) ; // vp-select-base
168+
169+ tag . appendFormatLine ( '<div class="{0} {1}">' , VP_INS_SELECT_CONTAINER , 'action' ) ;
170+ tag . appendFormatLine ( '<div class="vp-multilang {0}">Action</div>' , VP_INS_SELECT_TITLE ) ;
171+
172+ tag . appendFormatLine ( '<div style="{0}">' , 'position: relative;' ) ;
173+ tag . appendFormatLine ( '<input class="vp-input {0} {1}" type="text" placeholder="Search Action"/>' , VP_INS_SEARCH , 'attr' ) ;
174+ tag . appendFormatLine ( '<input class="{0} {1}" type="hidden"/>' , VP_INS_TYPE , 'action' ) ;
175+ tag . appendFormatLine ( '<i class="{0} {1}"></i>' , 'fa fa-search' , 'vp-ins-search-icon' ) ;
176+ tag . appendLine ( '</div>' ) ;
177+
178+ tag . appendFormatLine ( '<div class="{0} {1}">' , VP_INS_SELECT_BOX , 'action' ) ;
179+ tag . appendFormatLine ( '<ul class="{0} {1}" style="height:80px">' , VP_INS_SELECT_LIST , 'action' ) ;
180+ tag . appendLine ( '</ul>' ) ;
181+ tag . appendLine ( '</div>' ) ; // VP_INS_SELECT_BOX
182+ tag . appendLine ( '</div>' ) ; // VP_INS_SELECT_CONTAINER
183+
184+ tag . appendFormatLine ( '<div class="{0} {1}">' , VP_INS_SELECT_CONTAINER , 'info' ) ;
185+ tag . appendFormatLine ( '<div class="vp-multilang {0}">Info</div>' , VP_INS_SELECT_TITLE ) ;
186+
187+ tag . appendFormatLine ( '<div style="{0}">' , 'position: relative;' ) ;
188+ tag . appendFormatLine ( '<input class="vp-input {0} {1}" type="text" placeholder="Search Info"/>' , VP_INS_SEARCH , 'method' ) ;
189+ tag . appendFormatLine ( '<input class="{0} {1}" type="hidden"/>' , VP_INS_TYPE , 'info' ) ;
190+ tag . appendFormatLine ( '<i class="{0} {1}"></i>' , 'fa fa-search' , 'vp-ins-search-icon' ) ;
191+ tag . appendLine ( '</div>' ) ;
192+
193+ tag . appendFormatLine ( '<div class="{0} {1}">' , VP_INS_SELECT_BOX , 'info' ) ;
194+ tag . appendFormatLine ( '<ul class="{0} {1}" style="height:80px">' , VP_INS_SELECT_LIST , 'info' ) ;
195+ tag . appendLine ( '</ul>' ) ;
196+ tag . appendLine ( '</div>' ) ; // VP_INS_SELECT_BOX
197+ tag . appendLine ( '</div>' ) ; // VP_INS_SELECT_CONTAINER
198+
199+ tag . appendFormatLine ( '<div class="vp-multilang {0}">Options</div>' , VP_INS_SELECT_TITLE ) ;
200+ tag . appendFormatLine ( '<div class="{0} vp-grid-col-95">' , VP_INS_PARAMETER_BOX ) ;
201+ // TODO: option box
202+
203+ tag . appendLine ( '</div>' ) ; // VP_INS_PARAMETER
204+
205+ tag . appendLine ( '</div>' ) ; // VP_INS_BOX END
206+
207+ $ ( this . pageThis . wrapSelector ( '#' + this . containerId ) ) . html ( tag . toString ( ) ) ;
208+
209+ return tag . toString ( ) ;
210+ }
211+
212+ reload ( ) {
213+ this . renderPage ( ) ;
214+
215+ let targetTag = $ ( this . pageThis . wrapSelector ( '#' + this . targetId ) ) ;
216+ let model = $ ( targetTag ) . val ( ) ;
217+ let modelType = $ ( targetTag ) . find ( 'option:selected' ) . data ( 'type' ) ;
218+
219+ let actions = this . getAction ( modelType ) ;
220+ let infos = this . getInfo ( modelType ) ;
221+ this . state . action = { ...actions } ;
222+ this . state . info = { ...infos } ;
223+
224+ var actListTag = new com_String ( ) ;
225+ var infoListTag = new com_String ( ) ;
226+
227+ Object . keys ( actions ) . forEach ( actKey => {
228+ actListTag . appendFormatLine ( '<li class="{0}" data-var-name="{1}" data-var-type="{2}" title="{3}">{4}</li>' ,
229+ VP_INS_SELECT_ITEM , actKey , 'action' , actKey , actKey ) ;
230+ } ) ;
231+ Object . keys ( infos ) . forEach ( infoKey => {
232+ infoListTag . appendFormatLine ( '<li class="{0}" data-var-name="{1}" data-var-type="{2}" title="{3}">{4}</li>' ,
233+ VP_INS_SELECT_ITEM , infoKey , 'info' , infoKey , infoKey ) ;
234+ } ) ;
235+
236+ $ ( this . wrapSelector ( '.' + VP_INS_SELECT_LIST + '.action' ) ) . html ( actListTag . toString ( ) ) ;
237+ $ ( this . wrapSelector ( '.' + VP_INS_SELECT_LIST + '.info' ) ) . html ( infoListTag . toString ( ) ) ;
238+
239+ let that = this ;
240+ // action search suggest
241+ var suggestInput = new SuggestInput ( ) ;
242+ suggestInput . addClass ( 'vp-input action' ) ;
243+ suggestInput . addClass ( VP_INS_SEARCH ) ;
244+ suggestInput . setPlaceholder ( "Search Action" ) ;
245+ suggestInput . setSuggestList ( function ( ) { return Object . keys ( actions ) ; } ) ;
246+ suggestInput . setSelectEvent ( function ( value , item ) {
247+ $ ( this . wrapSelector ( ) ) . val ( value ) ;
248+ $ ( that . wrapSelector ( '.' + VP_INS_TYPE + '.action' ) ) . val ( item . type ) ;
249+
250+ $ ( that . pageThis . wrapSelector ( '#' + that . targetId ) ) . trigger ( {
251+ type :"model_editor_selected" ,
252+ varName :value ,
253+ varOptions :actions [ value ] ,
254+ isMethod :false
255+ } ) ;
256+ } ) ;
257+ $ ( that . wrapSelector ( '.' + VP_INS_SEARCH + '.action' ) ) . replaceWith ( function ( ) {
258+ return suggestInput . toTagString ( ) ;
259+ } ) ;
260+
261+ // info search suggest
262+ suggestInput = new SuggestInput ( ) ;
263+ suggestInput . addClass ( 'vp-input info' ) ;
264+ suggestInput . addClass ( VP_INS_SEARCH ) ;
265+ suggestInput . setPlaceholder ( "Search info" ) ;
266+ suggestInput . setSuggestList ( function ( ) { return Object . keys ( infos ) ; } ) ;
267+ suggestInput . setSelectEvent ( function ( value , item ) {
268+ $ ( this . wrapSelector ( ) ) . val ( value ) ;
269+ $ ( that . wrapSelector ( '.' + VP_INS_TYPE + '.info' ) ) . val ( item . type ) ;
270+
271+ $ ( that . pageThis . wrapSelector ( '#' + that . targetId ) ) . trigger ( {
272+ type :"model_editor_selected" ,
273+ varName :value ,
274+ varOptions :infos [ value ] ,
275+ isMethod :true
276+ } ) ;
277+ } ) ;
278+ $ ( that . wrapSelector ( '.' + VP_INS_SEARCH + '.info' ) ) . replaceWith ( function ( ) {
279+ return suggestInput . toTagString ( ) ;
280+ } ) ;
281+
282+ // bind event
283+ this . _bindEvent ( ) ;
284+ }
285+
286+ _bindEvent ( ) {
287+ super . _bindEvent ( ) ;
288+ let that = this ;
289+
290+ $ ( this . wrapSelector ( '.' + VP_INS_SELECT_ITEM ) ) . on ( 'click' , function ( ) {
291+ let name = $ ( this ) . data ( 'var-name' ) ;
292+ let type = $ ( this ) . data ( 'var-type' ) ;
293+ let config = that . state [ type ] [ name ] ;
294+ let optBox = new com_String ( ) ;
295+ // render tag
296+ config . options . forEach ( opt => {
297+ optBox . appendFormatLine ( '<label for="{0}" title="{1}">{2}</label>'
298+ , opt . name , opt . name , opt . name ) ;
299+ let content = com_generator . renderContent ( that , opt . component [ 0 ] , opt , that . pageThis . state ) ;
300+ optBox . appendLine ( content [ 0 ] . outerHTML ) ;
301+ } ) ;
302+ // replace option box
303+ $ ( that . wrapSelector ( '.' + VP_INS_PARAMETER_BOX ) ) . html ( optBox . toString ( ) ) ;
304+
305+ that . state . config = config ;
306+ } ) ;
307+ }
308+
309+ show ( ) {
310+ $ ( this . wrapSelector ( ) ) . show ( ) ;
311+ this . reload ( ) ;
312+ }
313+
314+ hide ( ) {
315+ $ ( this . wrapSelector ( ) ) . hide ( ) ;
316+ }
317+
318+ getCode ( ) {
319+ return com_generator . vp_codeGenerator ( this . pageThis , this . state . config , this . pageThis . state ) ;
320+ }
321+ }
322+
323+ return ModelEditor ;
324+ } ) ;