1 /**
  2  * @class Ozone.layout.CreateViewContainer
  3  * @extends Ext.form.Panel
  4  */
  5 Ext.define('Ozone.layout.CreateViewContainer', {
  6     extend: 'Ext.form.Panel',
  7     alias: [
  8         'widget.owfCreateDashboardsContainer',
  9         'widget.owfCreateViewsContainer',
 10         'widget.Ozone.layout.CreateViewContainer'
 11     ],
 12     requires: [
 13         'Ext.layout.container.Border'
 14     ],
 15     border: false,
 16     config: {},
 17     views: null,
 18     dashboardContainer: null,
 19     itemId: 'createNewDashboardPanel',
 20     cls: 'cvc-createNewDashboardContainer',
 21     afterRenderInitComplete: false,
 22     createViewContainer_FormValid: true,
 23     hideViewSelectRadio: false,
 24 
 25     initComponent: function() {
 26         this.config = this.dashboardContainer.activeDashboard.config;
 27         this.views = this.dashboardContainer.dashboards;
 28         
 29         this.addEvents('saved', 'failed');
 30         
 31         this.titleBox = {
 32             xtype: 'textfield',
 33             name: 'titleBox',
 34             cls: 'titleBox',
 35             itemId: 'titleBox', //OWF-2558
 36             fieldLabel: Ozone.util.createRequiredLabel(Ozone.ux.DashboardMgmtString.title),
 37             labelSeparator: '',
 38             labelWidth: undefined,
 39             allowBlank: false,
 40             maxLength: 200,
 41             value: '',
 42             enforceMaxLength: true,
 43             listeners: {
 44                 blur: function(field){
 45                     // Remove leading and tailing spaces
 46                     var val = field.getValue().replace(new RegExp(Ozone.lang.regexLeadingTailingSpaceChars), '');
 47                     field.setValue(val);
 48                 }
 49             }
 50         };
 51 
 52         this.description = {
 53             xtype: 'textareafield',
 54             name: 'description',
 55             cls: 'description',
 56             itemId: 'description',
 57             fieldLabel: Ozone.ux.DashboardMgmtString.description,
 58             labelSeparator: '',
 59             labelWidth: undefined,
 60             value: '',
 61             maxLength: 4000,
 62             enforceMaxLength: true
 63         };
 64 
 65         if (this.existingDashboardRecord != null) {
 66           this.titleBox.value = this.existingDashboardRecord.get('name');
 67           this.description.value = this.existingDashboardRecord.get('description');
 68         }
 69 
 70         this.existingViewRadio = { 
 71             boxLabel: Ozone.layout.CreateViewWindowString.createFromExisiting, 
 72             name: 'viewSelectRadio',
 73             inputValue: "copiedDashboard",
 74             cls:'existingViewRadio',
 75             //tabIndex: 2,
 76             listeners: {
 77                 'change': {
 78                     fn: function(radio, newValue, oldValue) {
 79                         if(newValue)
 80                         {
 81                             // var cmp = this.down('#viewCb');
 82                             // cmp.reset();
 83                             // cmp.disable();
 84 
 85                             var existViewCb = this.down('#existViewCb');
 86                             existViewCb.enable();
 87                             existViewCb.validate();
 88 
 89                             var importFileupload = this.down('#importFileupload');
 90                             importFileupload.reset();
 91                             importFileupload.disable();
 92                         }
 93                     },
 94                     scope: this
 95                 }
 96             },
 97             vtype: 'copiedDashboard',
 98             copiedDashboardField: 'existViewCb' // id of the field to validate
 99         };
100 		
101         this.importedViewRadio = { 
102             boxLabel: Ozone.layout.CreateViewWindowString.importView, 
103             name: 'viewSelectRadio',
104             inputValue: "importedDashboard",
105             cls:'importedViewRadio',
106             //tabIndex: 3,
107             listeners: {
108                 //this listener works for both since we can use the 'isSelected' param
109                 'change': {
110                     fn: function(radio, newValue, oldValue) {
111                         if(newValue) {
112                             var existViewCb = this.down('#existViewCb');
113                             existViewCb.reset();
114                             existViewCb.disable();
115 
116                             var importFileupload = this.down('#importFileupload');
117                             importFileupload.enable();
118                             importFileupload.validate();
119                         }
120                     },
121                     scope: this
122                 }
123             },
124             vtype: 'importedDashboard',
125             importedDashboardField: 'importFileupload' // id of the field to validate
126         };
127     	
128         // Set default layout for creating a new dashboard
129         //this.newView.value = this.config.layout;
130 		
131         this.existingView = {
132             xtype: 'combo',
133             //tabIndex: 2,
134             //id: 'existViewCb',
135             itemId: 'existViewCb',
136             store: this.dashboardContainer.dashboardStore,
137             valueField:'guid',
138             displayField:'name',
139             hideLabel: true,
140             typeAhead: true,
141             queryMode: 'local',
142             value: null,
143             triggerAction: 'all',
144             editable: true,
145             selectOnFocus:true,
146             allowBlank:true,
147             forceSelection: true,
148             disabled: true,
149             width: 400
150         };
151         this.existingView.value = this.views[0].guid;
152 
153         function handleInvalidFileUpload(current) {
154             dashboardJson = null;
155             Ozone.Msg.alert(Ozone.util.ErrorMessageString.dashboardConfig, "Invalid configuration file.", function () {
156                 current.focusTitleBox();
157             }, current, null, current.dashboardContainer.modalWindowManager);
158         }
159 
160         var container = this;
161         var dashboardJson = null;
162         var isSubmittingForm = false;
163         
164         this.importedView = {
165             xtype: 'filefield',
166             //tabIndex: 3,
167             //id: 'importFileupload',
168             itemId: 'importFileupload',
169             cls: 'importFileupload',
170             name: 'importFileupload',
171             hideLabel: true,
172             label: '',
173             width: 400,
174             emptyText: Ozone.ux.DashboardMgmtString.uploadConfig,
175             allowBlank: true,
176             disabled: true,
177             buttonText:Ozone.ux.DashboardMgmtString.browse,
178     //        buttonConfig: {
179     //            ui: 'button'
180     //        },
181             listeners: {
182                 afterrender: function (cmp) {
183                     cmp.setupFocus = function() {
184                         /*
185                          * We need to have the file input be focusable, but
186                          * have it appear that the button is what actually has focus
187                          */
188 
189                         var btnEl = this.button.getEl();
190                         var innerBtnEl = this.button.btnEl;
191                         var fileInputEl = this.fileInputEl;
192                         var allowFocus = true;
193 
194                         //set the <button> element and the text field to not be focusable
195                         innerBtnEl.dom.tabIndex = -1;
196                         cmp.inputEl.dom.tabIndex = -1;
197 
198                         fileInputEl.dom.tabIndex = 0;
199                         fileInputEl.dom.hideFocus = true;
200                         fileInputEl.dom.style.outlineStyle = 'none';
201 
202                         cmp.mon(fileInputEl, 'focus', function() {
203                             this.addCls('x-focus');
204                         }, btnEl);
205 
206                         cmp.mon(fileInputEl,'blur', function() {
207                             this.removeCls('x-focus');
208                         }, btnEl);
209 
210                         function enableBorder() {
211                             allowFocus = true;
212                         }
213 
214                         cmp.mon(fileInputEl, {
215                             mouseup: enableBorder,
216                             mouseout: enableBorder
217                         });
218                     };
219 
220                     cmp.setupFocus();
221 
222                     //override the reset function
223                     cmp._reset = cmp.reset;
224                     cmp.reset = function() {
225                         
226                         if (!isSubmittingForm) {
227                             this._reset.apply(this, arguments);
228                             dashboardJson = null;
229                         }
230                         // this small block does exactly what the extjs reset does, except
231                         // it does not clear out the inputEl value because we want to see
232                         // the file in the input text field after selecting it.  if the 
233                         // fileInputEl is not removed then created again, the browse button
234                         // will not work a second time.
235                         else {
236                             if (this.rendered) {
237                                 this.fileInputEl.remove();
238                                 this.createFileInput();
239                             }
240                             this.callParent();
241                         }
242                         
243                         this.setupFocus();
244                     }
245                 },
246                 change: function( cmp, value, eOpts ) {
247 
248                     isSubmittingForm = true;
249                     container.getForm().submit({
250                         clientValidation: false,
251                         reset: false,
252                         url: Ozone.util.contextPath() + '/servlet/FileServlet',
253                         waitMsg: 'Reading file...',
254                         success: function (fp, action) {
255 
256                             dashboardJson = Ozone.util.parseJson(action.response.responseText).value;
257                             
258                             if (!Ozone.util.validateDashboardJSON(dashboardJson)) {
259                                 handleInvalidFileUpload();
260                             }
261                             else {
262                                 
263                                 // if the description field is empty, fill it in with the imported description field, otherwise do nothing
264                                 if (container.getComponent('description').getValue() == null || container.getComponent('description').getValue() == "") {
265                                     container.getComponent('description').setValue(dashboardJson.description);
266                                 }   
267                             }
268                             isSubmittingForm = false;
269                         },
270                         failure: Ext.bind(function (form, action) {
271                             handleInvalidFileUpload(container);
272                             isSubmittingForm = false;
273                         }, container)
274                     });
275                 }
276             }
277         };
278 
279 
280         //RadioGroup and CheckboxGroup does not properly validate other form fields that are not radio/checkboxes
281         //when mixed with radio/checkbox fields because it assumes if any radio/checkbox is checked it can assume the
282         //entire group is valid
283         this.viewSelectRadio = {
284             layout: {
285                 type: 'hbox',
286                 align: 'stretchmax'
287             },
288             cls: 'createSelector',
289             region: 'center',
290             allowBlank: false,
291             hideLabel: true,
292             hidden: this.hideViewSelectRadio,
293             items: [
294                 [
295                     {
296                         xtype: 'radiogroup',
297                         flex: 1,
298                         cls: 'viewSelect',
299                         itemId: "viewSelect", //OWF-2558
300                         layout: {
301                             type: 'vbox',
302                             align: 'stretch'
303                         },
304                         defaults: {
305                             flex: 1
306                         },
307                         items: [
308                             this.existingViewRadio,
309                             this.importedViewRadio
310                         ]
311                     },
312                     {
313                         layout: {
314                             type: 'vbox',
315                             align: 'stretch'
316                         },
317                         cls: 'viewSelectBoxes',
318                         flex: 1,
319                         defaults: {
320                             flex: 1
321                         },
322                         items: [
323                             this.existingView,
324                             this.importedView
325                         ]
326                     }
327                 ]
328             ]
329         };
330 
331         this.layout = {
332             type: 'vbox',
333             align: 'stretch'
334         };
335         this.items = [
336             this.titleBox,
337             this.description,
338             this.viewSelectRadio
339         ];
340 
341         this.dockedItems = [{
342             xtype: 'toolbar',
343             dock: 'bottom',
344             defaults: {
345                 minWidth: this.minButtonWidth
346             },
347             items: [{
348                 xtype: 'tbfill'
349             },{
350                 xtype:'button',
351                 scale: 'small',
352                 text: Ozone.layout.DialogMessages.ok,
353                 itemId: 'saveButton',
354                 //iconCls: 'okSaveBtnIcon',
355                 //tabIndex: 4,
356                 handler: function (button, event) {
357                     if (this.getForm().isValid() && this.createViewContainer_FormValid) {
358                         Ozone.util.formField.removeLeadingTrailingSpaces(this.getComponent('titleBox'));
359                         //make sure name is unique
360                         Ext.getCmp('mainPanel').saveActiveDashboardToServer();
361 
362                         var title = this.getComponent('titleBox').getValue();
363                         var desc = this.getComponent('description').getValue();
364                         
365                         // add a space to the field if it is empty or null so that it will
366                         // store an empty string to the db instead of it thinking its a null value
367                         if (desc == null || desc == '')
368                             desc = ' ';
369 
370                         //edit an existing dashboard if a record was passed in
371                         if (this.existingDashboardRecord != null) {
372                             this.existingDashboardRecord.set('name',title);
373                             this.existingDashboardRecord.set('description',desc);
374                             this.dashboardContainer.editDashboard(this.existingDashboardRecord);
375                             this.close();
376                         }
377                         //else create a new one
378                         else {
379 
380                             var radioSelection = this.down('#viewSelect').getValue().viewSelectRadio;
381                             var isCreateFromExisting = (radioSelection == "copiedDashboard") ? true : false;
382                             var isImport = (radioSelection == "importedDashboard") ? true : false;
383 
384                             //create new from existing
385                             if (isCreateFromExisting) {
386                                 var existingViewSelected = this.down('#existViewCb').getValue();
387 
388                                 if (Ext.isEmpty(existingViewSelected)) {
389                                     this.down('#existViewCb').markInvalid("This field cannot be blank.");
390                                     Ozone.Msg.alert(Ozone.util.ErrorMessageString.invalidForm, Ozone.util.ErrorMessageString.invalidFormMsg, function () {
391                                             this.focusTitleBox();
392                                         }, this, null, this.dashboardContainer.modalWindowManager);
393                                     return;
394                                 }
395 
396                                 var existingViewToDuplicate = this.dashboardContainer.dashboardStore.getById(existingViewSelected).data;
397                                 existingViewToDuplicate = Ozone.util.cloneDashboard(existingViewToDuplicate, true);
398                                 
399                                 existingViewToDuplicate.name = title;
400                                 existingViewToDuplicate.description = desc;
401                                 existingViewToDuplicate.isdefault = false;
402 
403                                 Ext.getCmp('mainPanel').createDashboard(
404                                         Ext.create('Ozone.data.Dashboard', existingViewToDuplicate)
405                                 );
406 
407                                 this.close();
408                             }
409                             //create new from import
410                             else if (isImport) {
411                                 //check if the dashboardJson has been set from file upload
412                                 if (dashboardJson != null) {
413                                     
414                                     // Reset title
415                                     dashboardJson.name = title;
416                                     dashboardJson.description = desc;
417 
418                                     // make sure the right type of json is being imported
419                                     if (!Ozone.util.validateDashboardJSON(dashboardJson)) {
420                                         Ozone.Msg.alert(Ozone.util.ErrorMessageString.dashboardConfig, "Invalid " + dashboardJson.layout + " configuration file.", function () {
421                                             this.focusTitleBox();
422                                         }, this, null, this.dashboardContainer.modalWindowManager);
423                                     }
424                                     else {
425                                         delete dashboardJson.state;
426 
427                                         Ext.getCmp('mainPanel').createDashboard(
428                                             Ext.create('Ozone.data.Dashboard', Ozone.util.cloneDashboard(dashboardJson, true))
429                                             );
430                                         this.close();
431                                     }
432                                 }
433                                 else {
434                                     Ozone.Msg.alert(Ozone.util.ErrorMessageString.invalidForm, Ozone.util.ErrorMessageString.invalidFormMsg, function () {
435                                         this.focusTitleBox();
436                                     }, this, null, this.dashboardContainer.modalWindowManager);
437                                 }
438                             }
439                             //create new using name, and description
440                             else {
441                                 Ext.getCmp('mainPanel').createDashboard(
442                                         Ext.create('Ozone.data.Dashboard', {
443                                             "name": title,
444                                             "description": desc
445                                         })
446                                 );
447                                 this.close();
448                             }
449                         }
450                     }
451                     else {
452                         Ozone.Msg.alert(Ozone.util.ErrorMessageString.invalidForm, Ozone.util.ErrorMessageString.invalidFormMsg, function () {
453                             this.focusTitleBox();
454                         }, this, null, this.dashboardContainer.modalWindowManager);
455                     }
456                 },
457                 scope: this,
458                 listeners: {
459                     afterrender: function(button) {
460                         button.getEl().on('keydown', function(e) {
461                             e.stopPropagation(); //prevent keydown from bubbling up to the toolbar
462                         });
463                     }
464                 }
465             },{
466                 xtype:'button',
467                 scale: 'small',
468                 text: 'Cancel',
469                 itemId: 'cancelBtn',
470 //                iconCls: 'cancelBtnIcon',
471                 scope: this,
472                 handler: this.cancel
473             }]
474         }];
475 		
476         //Need this to get rid of destory errors with ExtJS
477         this.on('beforedestroy', function(cmp){
478             cmp.dockedItems = null;
479         });
480 
481         //        this.on("afterrender", function(cmp) {
482         //        	cmp.focusTitleBox();
483         //        });
484 
485         this.callParent();
486     },
487 
488     refreshData: function(){
489         this.config = this.dashboardContainer.activeDashboard.config;
490         this.views = this.dashboardContainer.dashboards;
491 
492         // Reset fields
493         var txtTitle = this.getComponent('titleBox');
494         if (txtTitle) {
495             txtTitle.setRawValue('');
496         }
497 
498         var txtDescription = this.getComponent('description');
499         if (txtDescription) {
500             txtDescription.setRawValue('');
501         }
502 
503         var txtImportFile = this.down('#importFileupload');
504         if (txtImportFile) {
505             txtImportFile.setRawValue('');
506         }
507 
508         var cboViewSelect = this.getComponent('viewSelect');
509         if (cboViewSelect) {
510             cboViewSelect.reset();
511         }
512 
513         var existingView = this.down('#existViewCb');
514         existingView.setValue(this.views[0].guid);
515     },
516 
517     focusTitleBox: function() {
518         /*
519          * Have to defer this so that it happens after a focus that Ext does 
520          * internally that is also deffered
521          */
522         Ext.defer(function() {
523             this.getComponent('titleBox').focus();
524         }, 500, this);
525     },
526 
527     cancel: function () {
528         this.close();
529     },
530 
531     close: function() {
532         Ext.getCmp(this.winId).close();
533     }
534 });