      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 });