<commit_before>new Ext.KeyMap(document, [{
  key: Ext.EventObject.F5,
  fn: function(k, e) {
    if (!e.ctrlKey) {
      if (Ext.isIE) {
        e.browserEvent.keyCode = 8;
      }
      e.stopEvent();
      document.location = document.location;
    }
    else {
      Ext.Msg.alert(_('ID_REFRESH_LABEL'), _('ID_REFRESH_MESSAGE'));
    }
  }
},
{
  key: Ext.EventObject.DELETE,
  fn: function(k, e) {
    iGrid = Ext.getCmp('infoGrid');
    rowSelected = iGrid.getSelectionModel().getSelected();
    if (rowSelected) {
      deleteDashletInstance();
    }
  }
},
{
  key: Ext.EventObject.F2,
  fn: function(k, e) {
    iGrid = Ext.getCmp('infoGrid');
    rowSelected = iGrid.getSelectionModel().getSelected();
    if (rowSelected){
      editDashletInstance();
    }
  }
}
]);

var store;
var cmodel;
var infoGrid;
var viewport;
var smodel;
var newButton;
var editButton;
var deleteButton;
var statusButton;
//var searchButton;
//var searchText;
//var clearTextButton;
var actionButtons;
var contextMenu;

Ext.onReady(function(){
  Ext.QuickTips.init();

  pageSize = 20; //parseInt(CONFIG.pageSize);

  newButton = new Ext.Action({
    text: _('ID_NEW'),
    iconCls: 'button_menu_ext ss_sprite ss_add',
    handler: newDashletInstance
  });

  editButton = new Ext.Action({
    text: _('ID_EDIT'),
    iconCls: 'button_menu_ext ss_sprite  ss_pencil',
    handler: editDashletInstance,
    disabled: true
  });

  deleteButton = new Ext.Action({
    text: _('ID_DELETE'),
    iconCls: 'button_menu_ext ss_sprite  ss_delete',
    handler: deleteDashletInstance,
    disabled: true
  });

  statusButton = new Ext.Action({
	text: _('ID_STATUS'),
	iconCls: 'silk-add',
	handler: statusDashletInstance,
	disabled: true
  });

  /*searchButton = new Ext.Action({
    text: _('ID_SEARCH'),
    handler: doSearch
  });

  searchText = new Ext.form.TextField ({
    id: 'searchText',
    ctCls:'pm_search_text_field',
    allowBlank: true,
    width: 150,
    emptyText: _('ID_ENTER_SEARCH_TERM'),
    listeners: {
      specialkey: function(f, e){
        if (e.getKey() == e.ENTER) {
          doSearch();
        }
      },
      focus: function(f, e) {
        var row = infoGrid.getSelectionModel().getSelected();
        infoGrid.getSelectionModel().deselectRow(infoGrid.getStore().indexOf(row));
      }
    }
  });

  clearTextButton = new Ext.Action({
    text: 'X',
    ctCls:'pm_search_x_button',
    handler: gridByDefault
  });*/

  contextMenu = new Ext.menu.Menu({
    items: [editButton, deleteButton, statusButton]
  });

  actionButtons = [newButton, '-', editButton, deleteButton, statusButton/*, {xtype: 'tbfill'}, searchText, clearTextButton, searchButton*/];

  smodel = new Ext.grid.RowSelectionModel({
    singleSelect: true,
    listeners:{
      rowselect: function(sm, index, record){
        editButton.enable();
        deleteButton.enable();
        statusButton.enable();
        if (typeof(_rowselect) !== 'undefined') {
          if (Ext.isArray(_rowselect)) {
            for (var i = 0; i < _rowselect.length; i++) {
              if (Ext.isFunction(_rowselect[i])) {
                _rowselect[i](sm, index, record);
              }
            }
          }
        }

        if( record.data.DAS_INS_STATUS_LABEL == 'Active' ){
        	statusButton.setIconClass('icon-activate');
        	statusButton.setText( _('ID_DEACTIVATE') );
        } else {
        	statusButton.setIconClass('icon-deactivate');
        	statusButton.setText( _('ID_ACTIVATE') );
        }

      },
      rowdeselect: function(sm, index, record){
        editButton.disable();
        deleteButton.disable();
        statusButton.disable();
        if (typeof(_rowdeselect) !== 'undefined') {
          if (Ext.isArray(_rowdeselect)) {
            for (var i = 0; i < _rowdeselect.length; i++) {
              if (Ext.isFunction(_rowdeselect[i])) {
                _rowdeselect[i](sm, index, record);
              }
            }
          }
        }
      }
    }
  });

  store = new Ext.data.GroupingStore( {
    proxy : new Ext.data.HttpProxy({
      url: 'getDashletsInstances'
    }),
    reader : new Ext.data.JsonReader( {
      root: 'dashletsInstances',
      totalProperty: 'totalDashletsInstances',
      fields : [
        {name : 'DAS_INS_UID'},
        {name : "DAS_INS_TITLE"},
        {name : 'DAS_TITLE'},
        {name : 'DAS_VERSION'},
        {name : 'DAS_INS_OWNER_TITLE'},
        {name : 'DAS_INS_UPDATE_DATE'},
        {name : 'DAS_INS_STATUS_LABEL'},
        {name : 'DAS_INS_STATUS'}
      ]
    }),
    sortInfo: {
        field: 'DAS_INS_TITLE',
        direction: 'ASC'
    }
  });

  cmodel = new Ext.grid.ColumnModel({
    defaults: {
      width: 50,
      sortable: true
    },
    columns: [
      {id:'DAS_INS_UID', dataIndex: 'DAS_INS_UID', hidden:true, hideable:false},
      {header: _("ID_TITLE"), dataIndex: "DAS_INS_TITLE", width: 150, hidden: false, align: "left"},
      {header: _("ID_DASHLET"), dataIndex: "DAS_TITLE", width: 200, hidden: false, align: "left"},
      {header: _('ID_VERSION'), dataIndex: 'DAS_VERSION', width: 60, hidden: false, align: 'center'},
      {header: _('ID_ASSIGNED_TO'), dataIndex: 'DAS_INS_OWNER_TITLE', width: 200, hidden: false, align: 'center'},
      {header: _('ID_UPDATE_DATE'), dataIndex: 'DAS_INS_UPDATE_DATE', width: 80, hidden: false, align: 'center'},
      {header: _('ID_STATUS'), dataIndex: 'DAS_INS_STATUS_LABEL', width: 60, hidden: false, align: 'center'}
    ]
  });

  storePageSize = new Ext.data.SimpleStore({
    fields: ['size'],
    data: [['20'],['30'],['40'],['50'],['100']],
    autoLoad: true
  });

  comboPageSize = new Ext.form.ComboBox({
    typeAhead     : false,
    mode          : 'local',
    triggerAction : 'all',
    store: storePageSize,
    valueField: 'size',
    displayField: 'size',
    width: 50,
    editable: false,
    listeners:{
      select: function(c,d,i){
        //UpdatePageConfig(d.data['size']);
        bbarpaging.pageSize = parseInt(d.data['size']);
        bbarpaging.moveFirst();
      }
    }
  });

  comboPageSize.setValue(pageSize);

  bbarpaging = new Ext.PagingToolbar({
    pageSize: pageSize,
    store: store,
    displayInfo: true,
    displayMsg: _('ID_GRID_PAGE_DISPLAYING_DASHLET_MESSAGE') + '    ',
    //displayMsg: 'Displaying dashlets instances {0} - {1} of {2}' + '    ',
    emptyMsg: _('ID_GRID_PAGE_NO_DASHLET_MESSAGE'),
    //emptyMsg: 'No dashlets instances to display',
    items: ['-',_('ID_PAGE_SIZE')+':',comboPageSize]
  });

  infoGrid = new Ext.grid.GridPanel({
    region: 'center',
    layout: 'fit',
    id: 'infoGrid',
    height:100,
    autoWidth : true,
    stateful : true,
    stateId : 'gridDashletList',
    enableColumnResize: true,
    enableHdMenu: true,
    frame:false,
    //iconCls:'icon-grid',
    columnLines: false,
    viewConfig: {
      forceFit:true
    },
    //title : _('ID_DASHLETS_INSTANCES'),
    title : _('ID_DASHLETS_INSTANCES'),
    store: store,
    cm: cmodel,
    sm: smodel,
    tbar: actionButtons,
    bbar: bbarpaging,
    listeners: {
      rowdblclick: editDashletInstance,
      render: function(){
        this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING_GRID')});
      }
    },
    view: new Ext.grid.GroupingView({
      forceFit:true,
      groupTextTpl: '{text}',
      cls:"x-grid-empty",
      emptyText: _('ID_NO_RECORDS_FOUND')
    })
  });

  infoGrid.on('rowcontextmenu',
      function (grid, rowIndex, evt) {
          var sm = grid.getSelectionModel();
          sm.selectRow(rowIndex, sm.isSelected(rowIndex));
      },
      this
  );

  infoGrid.on('contextmenu',
      function (evt) {
          evt.preventDefault();
      },
      this
  );

  infoGrid.addListener('rowcontextmenu',onMessageContextMenu,this);

  infoGrid.store.load();

  viewport = new Ext.Viewport({
    layout: 'fit',
    autoScroll: false,
    items: [
       infoGrid
    ]
  });

  if (typeof(__DASHBOARD_ERROR__) !== 'undefined') {
    PMExt.notify(_('ID_DASHBOARD'), __DASHBOARD_ERROR__);
  }
});

//Funtion Handles Context Menu Opening
onMessageContextMenu = function (grid, rowIndex, e) {
    e.stopEvent();
    var coords = e.getXY();
    contextMenu.showAt([coords[0], coords[1]]);
};

//Load Grid By Default
gridByDefault = function(){
  //searchText.reset();
  infoGrid.store.load();
};

//Do Search Function
/*doSearch = function(){
   infoGrid.store.load({params: {textFilter: searchText.getValue()}});
};*/

//Update Page Size Configuration
/*updatePageConfig = function(pageSize) {
  Ext.Ajax.request({
    url: 'updatePageConfig',
    params: {size: pageSize}
  });
};*/

//New Dashlet Instance Action
newDashletInstance = function() {
  location.href = 'dashletInstanceForm';
};

//Edit Dashlet Instance Action
editDashletInstance = function(){
  var rowSelected = infoGrid.getSelectionModel().getSelected();
  if (rowSelected){
    location.href = 'dashletInstanceForm?DAS_INS_UID=' + rowSelected.data.DAS_INS_UID;
  }
};

//Delete Dashlet Instance Action
deleteDashletInstance = function(){
  var rowSelected = infoGrid.getSelectionModel().getSelected();
  if (rowSelected){
    Ext.Msg.confirm(_('ID_CONFIRM'), _('ID_CONFIRM_DELETE_DASHLET_INSTANCE'),function(btn, text)
    //Ext.Msg.confirm(_('ID_CONFIRM'), 'Do you want to delete this Dashlet Instance?', function(btn, text)
    {
      if (btn == 'yes') {
        viewport.getEl().mask(_('ID_PROCESSING'));
        Ext.Ajax.request({
          url: 'deleteDashletInstance',
          params: {DAS_INS_UID: rowSelected.data.DAS_INS_UID},
          success: function(r, o){
            viewport.getEl().unmask();
            response = Ext.util.JSON.decode(r.responseText);
            if (response.status == 'OK') {
              PMExt.notify(_('ID_DASHLET_INSTANCE'),_('ID_DASHLET_SUCCESS_DELETE'));
              //PMExt.notify('Dashlet Instance', 'Dashlet instance deleted sucessfully.');
            }
            else {
              PMExt.error(_('ID_DASHLET_INSTANCE'), response.message);
              //PMExt.error('Dashlet Instance', response.message);
            }
            //doSearch();
            editButton.disable();
            deleteButton.disable();
            statusButton.disable();
            infoGrid.store.load();
          },
          failure: function(r, o){
            viewport.getEl().unmask();
          }
        });
      }
    });
  }
};

//Status Dashlet Instance Action
statusDashletInstance = function(){
	  var rows = infoGrid.getSelectionModel().getSelections();
	  if( rows.length > 0 ) {
	    for(i=0; i<rows.length; i++) {
	    	var status;
	    	if(rows[i].data.DAS_INS_STATUS == 1){
	    		status = 0;
	    	} else {
	    		status = 1;
	    	}

	    	var data = {
	    		DAS_INS_UID: rows[i].data.DAS_INS_UID,
	    		DAS_INS_TITLE: rows[i].data.DAS_INS_TITLE,
	    		DAS_UID: rows[i].data.DAS_INS_UID,
	    		DAS_INS_STATUS: status,
	    		DAS_STATUS: status
	    	};

	    	Ext.Ajax.request({
	             url:      'saveDashletInstance',
	             method:   'POST',
	             params:   data,
	             success:  function (result, request) {
	                         editButton.disable();
	                         deleteButton.disable();
	                         statusButton.disable();

	                         statusButton.setIconClass('silk-add');
	                     	 statusButton.setText( _('ID_STATUS') );
	                     	 infoGrid.store.load();
	                      },
	             failure: function (result, request) {
	                        Ext.MessageBox.alert( _('ID_ALERT'), _('ID_AJAX_COMMUNICATION_FAILED') );
	                      }
	        });
	    }
	  } else {
	     Ext.Msg.show({
	      title:'',
	      msg: _('ID_NO_SELECTION_WARNING'),
	      buttons: Ext.Msg.INFO,
	      fn: function(){},
	      animEl: 'elId',
	      icon: Ext.MessageBox.INFO,
	      buttons: Ext.MessageBox.OK
	    });
	  }
};
<commit_msg>BUG-14034 Status in Dashboards -NEW FEATURE In ADMIN > Settings > Dashboard now is available the button Status, this button let Activate or Deactivate the Dashlet, showing the changed status in the Status Field in the grid.<commit_after>new Ext.KeyMap(document, [{
  key: Ext.EventObject.F5,
  fn: function(k, e) {
    if (!e.ctrlKey) {
      if (Ext.isIE) {
        e.browserEvent.keyCode = 8;
      }
      e.stopEvent();
      document.location = document.location;
    }
    else {
      Ext.Msg.alert(_('ID_REFRESH_LABEL'), _('ID_REFRESH_MESSAGE'));
    }
  }
},
{
  key: Ext.EventObject.DELETE,
  fn: function(k, e) {
    iGrid = Ext.getCmp('infoGrid');
    rowSelected = iGrid.getSelectionModel().getSelected();
    if (rowSelected) {
      deleteDashletInstance();
    }
  }
},
{
  key: Ext.EventObject.F2,
  fn: function(k, e) {
    iGrid = Ext.getCmp('infoGrid');
    rowSelected = iGrid.getSelectionModel().getSelected();
    if (rowSelected){
      editDashletInstance();
    }
  }
}
]);

var store;
var cmodel;
var infoGrid;
var viewport;
var smodel;
var newButton;
var editButton;
var deleteButton;
var statusButton;
//var searchButton;
//var searchText;
//var clearTextButton;
var actionButtons;
var contextMenu;

Ext.onReady(function(){
  Ext.QuickTips.init();

  pageSize = 20; //parseInt(CONFIG.pageSize);

  newButton = new Ext.Action({
    text: _('ID_NEW'),
    iconCls: 'button_menu_ext ss_sprite ss_add',
    handler: newDashletInstance
  });

  editButton = new Ext.Action({
    text: _('ID_EDIT'),
    iconCls: 'button_menu_ext ss_sprite  ss_pencil',
    handler: editDashletInstance,
    disabled: true
  });

  deleteButton = new Ext.Action({
    text: _('ID_DELETE'),
    iconCls: 'button_menu_ext ss_sprite  ss_delete',
    handler: deleteDashletInstance,
    disabled: true
  });

  statusButton = new Ext.Action({
	text: _('ID_STATUS'),
	iconCls: 'silk-add',
	handler: statusDashletInstance,
	disabled: true
  });

  /*searchButton = new Ext.Action({
    text: _('ID_SEARCH'),
    handler: doSearch
  });

  searchText = new Ext.form.TextField ({
    id: 'searchText',
    ctCls:'pm_search_text_field',
    allowBlank: true,
    width: 150,
    emptyText: _('ID_ENTER_SEARCH_TERM'),
    listeners: {
      specialkey: function(f, e){
        if (e.getKey() == e.ENTER) {
          doSearch();
        }
      },
      focus: function(f, e) {
        var row = infoGrid.getSelectionModel().getSelected();
        infoGrid.getSelectionModel().deselectRow(infoGrid.getStore().indexOf(row));
      }
    }
  });

  clearTextButton = new Ext.Action({
    text: 'X',
    ctCls:'pm_search_x_button',
    handler: gridByDefault
  });*/

  contextMenu = new Ext.menu.Menu({
    items: [editButton, deleteButton, statusButton]
  });

  actionButtons = [newButton, '-', editButton, deleteButton, statusButton/*, {xtype: 'tbfill'}, searchText, clearTextButton, searchButton*/];

  smodel = new Ext.grid.RowSelectionModel({
    singleSelect: true,
    listeners:{
      rowselect: function(sm, index, record){
        editButton.enable();
        deleteButton.enable();
        statusButton.enable();
        if (typeof(_rowselect) !== 'undefined') {
          if (Ext.isArray(_rowselect)) {
            for (var i = 0; i < _rowselect.length; i++) {
              if (Ext.isFunction(_rowselect[i])) {
                _rowselect[i](sm, index, record);
              }
            }
          }
        }

        if( record.data.DAS_INS_STATUS == 1 ){
        	statusButton.setIconClass('icon-activate');
        	statusButton.setText( _('ID_DEACTIVATE') );
        } else {
        	statusButton.setIconClass('icon-deactivate');
        	statusButton.setText( _('ID_ACTIVATE') );
        }

      },
      rowdeselect: function(sm, index, record){
        editButton.disable();
        deleteButton.disable();
        statusButton.disable();
        if (typeof(_rowdeselect) !== 'undefined') {
          if (Ext.isArray(_rowdeselect)) {
            for (var i = 0; i < _rowdeselect.length; i++) {
              if (Ext.isFunction(_rowdeselect[i])) {
                _rowdeselect[i](sm, index, record);
              }
            }
          }
        }
      }
    }
  });

  store = new Ext.data.GroupingStore( {
    proxy : new Ext.data.HttpProxy({
      url: 'getDashletsInstances'
    }),
    reader : new Ext.data.JsonReader( {
      root: 'dashletsInstances',
      totalProperty: 'totalDashletsInstances',
      fields : [
        {name : 'DAS_INS_UID'},
        {name : "DAS_INS_TITLE"},
        {name : 'DAS_TITLE'},
        {name : 'DAS_VERSION'},
        {name : 'DAS_INS_OWNER_TITLE'},
        {name : 'DAS_INS_UPDATE_DATE'},
        {name : 'DAS_INS_STATUS_LABEL'},
        {name : 'DAS_INS_STATUS'}
      ]
    }),
    sortInfo: {
        field: 'DAS_INS_TITLE',
        direction: 'ASC'
    }
  });

  cmodel = new Ext.grid.ColumnModel({
    defaults: {
      width: 50,
      sortable: true
    },
    columns: [
      {id:'DAS_INS_UID', dataIndex: 'DAS_INS_UID', hidden:true, hideable:false},
      {header: _("ID_TITLE"), dataIndex: "DAS_INS_TITLE", width: 150, hidden: false, align: "left"},
      {header: _("ID_DASHLET"), dataIndex: "DAS_TITLE", width: 200, hidden: false, align: "left"},
      {header: _('ID_VERSION'), dataIndex: 'DAS_VERSION', width: 60, hidden: false, align: 'center'},
      {header: _('ID_ASSIGNED_TO'), dataIndex: 'DAS_INS_OWNER_TITLE', width: 200, hidden: false, align: 'center'},
      {header: _('ID_UPDATE_DATE'), dataIndex: 'DAS_INS_UPDATE_DATE', width: 80, hidden: false, align: 'center'},
      {header: _('ID_STATUS'), dataIndex: 'DAS_INS_STATUS_LABEL', width: 60, hidden: false, align: 'center'}
    ]
  });

  storePageSize = new Ext.data.SimpleStore({
    fields: ['size'],
    data: [['20'],['30'],['40'],['50'],['100']],
    autoLoad: true
  });

  comboPageSize = new Ext.form.ComboBox({
    typeAhead     : false,
    mode          : 'local',
    triggerAction : 'all',
    store: storePageSize,
    valueField: 'size',
    displayField: 'size',
    width: 50,
    editable: false,
    listeners:{
      select: function(c,d,i){
        //UpdatePageConfig(d.data['size']);
        bbarpaging.pageSize = parseInt(d.data['size']);
        bbarpaging.moveFirst();
      }
    }
  });

  comboPageSize.setValue(pageSize);

  bbarpaging = new Ext.PagingToolbar({
    pageSize: pageSize,
    store: store,
    displayInfo: true,
    displayMsg: _('ID_GRID_PAGE_DISPLAYING_DASHLET_MESSAGE') + '    ',
    //displayMsg: 'Displaying dashlets instances {0} - {1} of {2}' + '    ',
    emptyMsg: _('ID_GRID_PAGE_NO_DASHLET_MESSAGE'),
    //emptyMsg: 'No dashlets instances to display',
    items: ['-',_('ID_PAGE_SIZE')+':',comboPageSize]
  });

  infoGrid = new Ext.grid.GridPanel({
    region: 'center',
    layout: 'fit',
    id: 'infoGrid',
    height:100,
    autoWidth : true,
    stateful : true,
    stateId : 'gridDashletList',
    enableColumnResize: true,
    enableHdMenu: true,
    frame:false,
    //iconCls:'icon-grid',
    columnLines: false,
    viewConfig: {
      forceFit:true
    },
    //title : _('ID_DASHLETS_INSTANCES'),
    title : _('ID_DASHLETS_INSTANCES'),
    store: store,
    cm: cmodel,
    sm: smodel,
    tbar: actionButtons,
    bbar: bbarpaging,
    listeners: {
      rowdblclick: editDashletInstance,
      render: function(){
        this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING_GRID')});
      }
    },
    view: new Ext.grid.GroupingView({
      forceFit:true,
      groupTextTpl: '{text}',
      cls:"x-grid-empty",
      emptyText: _('ID_NO_RECORDS_FOUND')
    })
  });

  infoGrid.on('rowcontextmenu',
      function (grid, rowIndex, evt) {
          var sm = grid.getSelectionModel();
          sm.selectRow(rowIndex, sm.isSelected(rowIndex));
      },
      this
  );

  infoGrid.on('contextmenu',
      function (evt) {
          evt.preventDefault();
      },
      this
  );

  infoGrid.addListener('rowcontextmenu',onMessageContextMenu,this);

  infoGrid.store.load();

  viewport = new Ext.Viewport({
    layout: 'fit',
    autoScroll: false,
    items: [
       infoGrid
    ]
  });

  if (typeof(__DASHBOARD_ERROR__) !== 'undefined') {
    PMExt.notify(_('ID_DASHBOARD'), __DASHBOARD_ERROR__);
  }
});

//Funtion Handles Context Menu Opening
onMessageContextMenu = function (grid, rowIndex, e) {
    e.stopEvent();
    var coords = e.getXY();
    contextMenu.showAt([coords[0], coords[1]]);
};

//Load Grid By Default
gridByDefault = function(){
  //searchText.reset();
  infoGrid.store.load();
};

//Do Search Function
/*doSearch = function(){
   infoGrid.store.load({params: {textFilter: searchText.getValue()}});
};*/

//Update Page Size Configuration
/*updatePageConfig = function(pageSize) {
  Ext.Ajax.request({
    url: 'updatePageConfig',
    params: {size: pageSize}
  });
};*/

//New Dashlet Instance Action
newDashletInstance = function() {
  location.href = 'dashletInstanceForm';
};

//Edit Dashlet Instance Action
editDashletInstance = function(){
  var rowSelected = infoGrid.getSelectionModel().getSelected();
  if (rowSelected){
    location.href = 'dashletInstanceForm?DAS_INS_UID=' + rowSelected.data.DAS_INS_UID;
  }
};

//Delete Dashlet Instance Action
deleteDashletInstance = function(){
  var rowSelected = infoGrid.getSelectionModel().getSelected();
  if (rowSelected){
    Ext.Msg.confirm(_('ID_CONFIRM'), _('ID_CONFIRM_DELETE_DASHLET_INSTANCE'),function(btn, text)
    //Ext.Msg.confirm(_('ID_CONFIRM'), 'Do you want to delete this Dashlet Instance?', function(btn, text)
    {
      if (btn == 'yes') {
        viewport.getEl().mask(_('ID_PROCESSING'));
        Ext.Ajax.request({
          url: 'deleteDashletInstance',
          params: {DAS_INS_UID: rowSelected.data.DAS_INS_UID},
          success: function(r, o){
            viewport.getEl().unmask();
            response = Ext.util.JSON.decode(r.responseText);
            if (response.status == 'OK') {
              PMExt.notify(_('ID_DASHLET_INSTANCE'),_('ID_DASHLET_SUCCESS_DELETE'));
              //PMExt.notify('Dashlet Instance', 'Dashlet instance deleted sucessfully.');
            }
            else {
              PMExt.error(_('ID_DASHLET_INSTANCE'), response.message);
              //PMExt.error('Dashlet Instance', response.message);
            }
            //doSearch();
            editButton.disable();
            deleteButton.disable();
            statusButton.disable();
            infoGrid.store.load();
          },
          failure: function(r, o){
            viewport.getEl().unmask();
          }
        });
      }
    });
  }
};

//Status Dashlet Instance Action
statusDashletInstance = function(){
	  var rows = infoGrid.getSelectionModel().getSelections();
	  if( rows.length > 0 ) {
	    for(i=0; i<rows.length; i++) {
	    	var status;
	    	if(rows[i].data.DAS_INS_STATUS == 1){
	    		status = 0;
	    	} else {
	    		status = 1;
	    	}

	    	var data = {
	    		DAS_INS_UID: rows[i].data.DAS_INS_UID,
	    		DAS_INS_TITLE: rows[i].data.DAS_INS_TITLE,
	    		DAS_UID: rows[i].data.DAS_INS_UID,
	    		DAS_INS_STATUS: status,
	    		DAS_STATUS: status
	    	};

	    	Ext.Ajax.request({
	             url:      'saveDashletInstance',
	             method:   'POST',
	             params:   data,
	             success:  function (result, request) {
	                         editButton.disable();
	                         deleteButton.disable();
	                         statusButton.disable();

	                         statusButton.setIconClass('silk-add');
	                     	 statusButton.setText( _('ID_STATUS') );
	                     	 infoGrid.store.load();
	                      },
	             failure: function (result, request) {
	                        Ext.MessageBox.alert( _('ID_ALERT'), _('ID_AJAX_COMMUNICATION_FAILED') );
	                      }
	        });
	    }
	  } else {
	     Ext.Msg.show({
	      title:'',
	      msg: _('ID_NO_SELECTION_WARNING'),
	      buttons: Ext.Msg.INFO,
	      fn: function(){},
	      animEl: 'elId',
	      icon: Ext.MessageBox.INFO,
	      buttons: Ext.MessageBox.OK
	    });
	  }
};
<|endoftext|>


<commit_before>/*
Copyright 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import React from 'react';
import request from 'browser-request';
import { _t } from 'matrix-react-sdk/lib/languageHandler';
import sanitizeHtml from 'sanitize-html';

module.exports = React.createClass({
    displayName: 'HomePage',

    propTypes: {
        // URL base of the team server. Optional.
        teamServerUrl: React.PropTypes.string,
        // Team token. Optional. If set, used to get the static homepage of the team
        //      associated. If unset, homePageUrl will be used.
        teamToken: React.PropTypes.string,
        // URL to use as the iFrame src. Defaults to /home.html.
        homePageUrl: React.PropTypes.string,
    },

    getInitialState: function() {
        return {
            iframeSrc: '',
            page: '',
        };
    },

    translate: function(s) {
        s = sanitizeHtml(_t(s));
        // ugly fix for https://github.com/vector-im/riot-web/issues/4243
        s = s.replace(/Riot\.im/, 'Riot.im');
        s = s.replace(/\[matrix\]/, '');
        return s;
    },

    componentWillMount: function() {
        this._unmounted = false;

        if (this.props.teamToken && this.props.teamServerUrl) {
            this.setState({
                iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
            });
        }
        else {
            // we use request() to inline the homepage into the react component
            // so that it can inherit CSS and theming easily rather than mess around
            // with iframes and trying to synchronise document.stylesheets.

            let src = this.props.homePageUrl || 'home.html';

            request(
                { method: "GET", url: src },
                (err, response, body) => {
                    if (this._unmounted) {
                        return;
                    }

                    if (err || response.status < 200 || response.status >= 300) {
                        console.warn(`Error loading home page: ${err}`);
                        this.setState({ page: _t("Couldn't load home page") });
                        return;
                    }

                    body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
                    this.setState({ page: body });
                }
            );
        }
    },

    componentWillUnmount: function() {
        this._unmounted = true;
    },

    render: function() {
        if (this.state.iframeSrc) {
            return (

            );
        }
        else {
            const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
            return (
                <GeminiScrollbarWrapper autoshow={true} className="mx_HomePage">

                </GeminiScrollbarWrapper>
            );
        }
    }
});
<commit_msg>Fix missing import<commit_after>/*
Copyright 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import React from 'react';
import request from 'browser-request';
import { _t } from 'matrix-react-sdk/lib/languageHandler';
import sanitizeHtml from 'sanitize-html';
import sdk from 'matrix-react-sdk/lib';

module.exports = React.createClass({
    displayName: 'HomePage',

    propTypes: {
        // URL base of the team server. Optional.
        teamServerUrl: React.PropTypes.string,
        // Team token. Optional. If set, used to get the static homepage of the team
        //      associated. If unset, homePageUrl will be used.
        teamToken: React.PropTypes.string,
        // URL to use as the iFrame src. Defaults to /home.html.
        homePageUrl: React.PropTypes.string,
    },

    getInitialState: function() {
        return {
            iframeSrc: '',
            page: '',
        };
    },

    translate: function(s) {
        s = sanitizeHtml(_t(s));
        // ugly fix for https://github.com/vector-im/riot-web/issues/4243
        s = s.replace(/Riot\.im/, 'Riot.im');
        s = s.replace(/\[matrix\]/, '');
        return s;
    },

    componentWillMount: function() {
        this._unmounted = false;

        if (this.props.teamToken && this.props.teamServerUrl) {
            this.setState({
                iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
            });
        }
        else {
            // we use request() to inline the homepage into the react component
            // so that it can inherit CSS and theming easily rather than mess around
            // with iframes and trying to synchronise document.stylesheets.

            let src = this.props.homePageUrl || 'home.html';

            request(
                { method: "GET", url: src },
                (err, response, body) => {
                    if (this._unmounted) {
                        return;
                    }

                    if (err || response.status < 200 || response.status >= 300) {
                        console.warn(`Error loading home page: ${err}`);
                        this.setState({ page: _t("Couldn't load home page") });
                        return;
                    }

                    body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
                    this.setState({ page: body });
                }
            );
        }
    },

    componentWillUnmount: function() {
        this._unmounted = true;
    },

    render: function() {
        if (this.state.iframeSrc) {
            return (

            );
        }
        else {
            const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
            return (
                <GeminiScrollbarWrapper autoshow={true} className="mx_HomePage">

                </GeminiScrollbarWrapper>
            );
        }
    }
});
<|endoftext|>


<commit_before>// newick tree
// console.log(JSON.stringify(tnt.tree.parse_newick(newick)))
var newick = "";
var tree = tnt.tree();
var treeCreated = false;
var numOpenPar = 0;
var numClosedPar = 0;
var numCommas = 0;

tree.on("click", function (node)
{
  var root = tree.root();
  //node.sort(function (node, node.parent()) {return 1});
  var tempTree = root.subtree(node.get_all_leaves());
  var nodeParent = node.parent();
  tree.data(tempTree.data());
    tree.update();
});

function makeTree(newick) {
    document.getElementById("treemaker").innerHTML=""

    /*errorcheck begins here*/
  for (var x=0; x<newick.length; x++)
    {
      if (newick.charAt(x)==='(')
        {
        numOpenPar++;
        }
      if (newick.charAt(x)===')')
        {
        numClosedPar++;
        }
      if (newick.charAt(x)==',')
        {
          numCommas++;
        }
    }
  if (numOpenPar!==numClosedPar || newick.charAt(0)!=='(' || newick.charAt(newick.length-1)!==')')
    {  document.getElementById("errorspot").style.color="Red"
    /*errorcheck ends here*/
      document.getElementById("errorspot").innerHTML = "ERROR: INVALID INPUT";
      resetPar();
  }
  else
    {
      resetPar();
        tree
        .data(tnt.tree.parse_newick(newick))
        .node_display(tree.node_display()
            .size(1)
            .fill("black")
            )
        .label (tnt.tree.label.text()
        .fontsize(12)
        .height(window.innerHeight*0.7/(numCommas+1))
            )
        .layout(tnt.tree.layout.vertical()
        .width(window.innerWidth*0.58)
        .scale(false)
            );
    tree(document.getElementById("treemaker"));
    }
}

function submitNewick ()
{
  document.getElementById("errorspot").innerHTML = "";
  var newick=document.getElementById("userInput").value;
  makeTree(newick);
}

function resetPar() {
  numOpenPar=0;
  numClosedPar=0;
}

function submitFile() {
    document.getElementById("errorspot").innerHTML = "";
    var fileInput = document.getElementById("fileInput")
    console.log(fileInput.files[0])
    var newick = ''

    var file = fileInput.files[0]
    var reader = new FileReader()

    reader.onload = function(e) {
        newick = reader.result
    }
    reader.readAsText(file);
    makeTree(newick);
}

function updateVertical()
{
            tree.layout(tnt.tree.layout.vertical().width(window.innerWidth*0.58).scale(false));
            tree.update();
}

function updateRadial()
{
  {
            tree.layout(tnt.tree.layout.radial().width(window.innerWidth*0.58).scale(false));
            tree.update();
        }
}

$(window).resize(function() {
  var newick=document.getElementById("userInput").value;
  makeTree(newick);
});

<commit_msg>comments<commit_after>// newick tree
// console.log(JSON.stringify(tnt.tree.parse_newick(newick)))
var newick = "";
var tree = tnt.tree();
var treeCreated = false;
var numOpenPar = 0;
var numClosedPar = 0;
var numCommas = 0;

function makeTree(newick) {
    document.getElementById("treemaker").innerHTML=""

    /*errorcheck begins here*/
  for (var x=0; x<newick.length; x++)
    {
      if (newick.charAt(x)==='(')
        {
        numOpenPar++;
        }
      if (newick.charAt(x)===')')
        {
        numClosedPar++;
        }
      if (newick.charAt(x)==',')
        {
          numCommas=0;
          numCommas++;
        }
    }
  if (numOpenPar!==numClosedPar || newick.charAt(0)!=='(' || newick.charAt(newick.length-1)!==')')
    {  document.getElementById("errorspot").style.color="Red"
    /*errorcheck ends here*/
      document.getElementById("errorspot").innerHTML = "ERROR: INVALID INPUT";
      resetPar();
  }
  else
    {
      resetPar();
        tree
        .data(tnt.tree.parse_newick(newick))
        .node_display(tree.node_display()
            .size(1)
            .fill("black")
            )
        .label (tnt.tree.label.text()
        .fontsize(12)
        .height(window.innerHeight*0.7/(numCommas+1))
            )
        .layout(tnt.tree.layout.vertical()
        .width(window.innerWidth*0.58)
        .scale(false)
            );
    tree(document.getElementById("treemaker"));
    }
}

function submitNewick ()
{
  document.getElementById("errorspot").innerHTML = "";
  var newick=document.getElementById("userInput").value;
  makeTree(newick);
}

function resetPar() {
  numOpenPar=0;
  numClosedPar=0;
}

function submitFile() {
    document.getElementById("errorspot").innerHTML = "";
    var fileInput = document.getElementById("fileInput")
    console.log(fileInput.files[0])
    var newick = ''

    var file = fileInput.files[0]
    var reader = new FileReader()

    reader.onload = function(e) {
        newick = reader.result
    }
    reader.readAsText(file);
    makeTree(newick);
}

function updateVertical()
{
            tree.layout(tnt.tree.layout.vertical().width(window.innerWidth*0.58).scale(false));
            tree.update();
}

function updateRadial()
{
  {
            tree.layout(tnt.tree.layout.radial().width(window.innerWidth*0.58).scale(false));
            tree.update();
        }
}

/*dynamic resizing*/
$(window).resize(function() {
  var newick=document.getElementById("userInput").value;
  makeTree(newick);
});

/*click node=view subtree*/
tree.on("click", function (node)
{
  var root = tree.root();
  //node.sort(function (node, node.parent()) {return 1});
  var tempTree = root.subtree(node.get_all_leaves());
  var nodeParent = node.parent();
  tree.data(tempTree.data());
    tree.update();
});

<|endoftext|>


<commit_before>import UtilsNew from "../../core/utilsNew.js";
import Renderer from "./renderer.js";
import {SVG} from "../../core/svg.js";

/**
  @param  args example:
        {
            height: number, <- height of div
            histogramColor: String
            histogramHeight: number <- height of histogram
            histogramMaxFreqValue: number
            ...
        }
 */
export default class HistogramRenderer extends Renderer {

    constructor(args) {
        super(args);
        //Extend and add Backbone Events
        Object.assign(this, Backbone.Events);

        //set default args
        this.histogramHeight = 75;
        this.histogramColor = "#428bca";

        this.maxValue = 10;
        this.updateScale(args);
        //set instantiation args
        Object.assign(this, args);

    }

    _checkFeatureValue(feature) {
        if (feature.features_count === null) {
            if (feature.absolute !== 0 && feature.absolute > 0) {
                // take care of feature.absolute==1 counts and set scaled value to 0.2 as log(2) ~= 0.3
                feature.features_count = Math.max(0.2, Math.log(feature.absolute));
            } else {
                feature.features_count = 0;
            }
        }
    }

    /**
     * updates "this.multiplier" using "histogramMaxFreqValue" and "height"
     * @param args
     */
    updateScale(args) {
        if (args !== null) {
            if (UtilsNew.isNotUndefinedOrNull(args.height)) {
                this.histogramHeight = args.height * 0.95;
            }
            if (UtilsNew.isNotUndefinedOrNull(args.histogramMaxFreqValue)) {
                this.maxValue = args.histogramMaxFreqValue;
            }
        }
        this.multiplier = this.histogramHeight / this.maxValue;
    }
    /**
    @param features  Array containing chunks example
            [   {chunkKey:"13:3298_histogram_10000"
                 region: Region{chromosome: "13", start:329800000, end:32980016}
                 value:{_id: 1940000, chromosome:"13", start: 32980000, end: 32980016, features_count:0},
                 ...
                 }
            ]
     @param args example
                {pixelPosition: number,
                position: number,
                svgCanvasFeatures
                }

     */
    render(features, args) {
        features.sort(function (a, b) {
            return a.value.start - b.value.start;
        });

        let middle = args.width / 2;
        //console.log(middle);
        let points = "";

        this.updateScale(args);

        if (features.length > 0) {
            let firstFeature = features[0].value;
            let width = (firstFeature.end - firstFeature.start + 1) * args.pixelBase;
            let x = args.pixelPosition + middle - ((args.position - parseInt(firstFeature.start)) * args.pixelBase);

            this._checkFeatureValue(firstFeature);
            let height = firstFeature.features_count * this.multiplier;

            points = (x - (width / 2)).toFixed(1) + "," + this.histogramHeight.toFixed(1) + " ";
            points += (x - (width / 2)).toFixed(1) + "," + (this.histogramHeight - height).toFixed(1) + " ";
        }
        for (let i = 0, len = features.length; i < len; i++) {
            let feature = features[i].value;
            feature.start = parseInt(feature.start);
            feature.end = parseInt(feature.end);
            let width = (feature.end - feature.start + 1) * args.pixelBase;
            let x = args.pixelPosition + middle - ((args.position - feature.start) * args.pixelBase);

            this._checkFeatureValue(feature);
            let height = feature.features_count * this.multiplier;

            points += (x + (width / 2)).toFixed(1) + "," + (this.histogramHeight - height).toFixed(1) + " ";
        }
        if (features.length > 0) {
            let lastFeature = features[features.length - 1].value;
            let width = (lastFeature.end - lastFeature.start + 1) * args.pixelBase;
            let x = args.pixelPosition + middle - ((args.position - parseInt(lastFeature.start)) * args.pixelBase);

            this._checkFeatureValue(lastFeature);
            let height = lastFeature.features_count * this.multiplier;

            points += (x + (width)).toFixed(1) + "," + (this.histogramHeight - height).toFixed(1) + " ";
            points += (x + (width)).toFixed(1) + "," + this.histogramHeight.toFixed(1) + " ";
        }

        if (points !== "") {
            SVG.addChild(args.svgCanvasFeatures, "polyline", {
                "points": points,
                "fill": this.histogramColor,
                "cursor": "pointer"
            });

        }
    }
}
<commit_msg>gb: refactor histogram renderer (#337)<commit_after>import Renderer from "./renderer.js";
import {SVG} from "../../core/svg.js";

export default class HistogramRenderer extends Renderer {

    #getFeatureValue(feature) {
        return feature.absolute > 0 ? Math.max(0.2, Math.log(feature.absolute)) : 0;
    }

    render(features, options) {
        // Sort features by start position
        features.sort((a, b) => a.value.start - b.value.start);

        const middle = options.width / 2;

        // Update the scale values
        const histogramHeight = options.height ? options.height * 0.95 : this.config.histogramHeight;
        const maxValue = options.histogramMaxFreqValue || this.config.maxValue;
        const multiplier = histogramHeight / maxValue;

        const points = [];

        // Draw starting point
        if (features.length > 0) {
            const firstFeature = features[0].value;
            const width = (firstFeature.end - firstFeature.start + 1) * options.pixelBase;
            const x = options.pixelPosition + middle - ((options.position - parseInt(firstFeature.start)) * options.pixelBase);
            const height = this.#getFeatureValue(firstFeature) * multiplier;

            points.push(`${(x - (width / 2)).toFixed(1)},${histogramHeight.toFixed(1)}`);
            points.push(`${(x - (width / 2)).toFixed(1)},${(histogramHeight - height).toFixed(1)}`);
        }

        features.forEach(feature => {
            const width = (feature.end - feature.start + 1) * options.pixelBase;
            const x = options.pixelPosition + middle - ((options.position - feature.start) * options.pixelBase);
            const height = this.#getFeatureValue(feature) * multiplier;

            points.push(`${(x + (width / 2)).toFixed(1)},${(histogramHeight - height).toFixed(1)}`);
        });

        // Draw ending point of histogram
        if (features.length > 0) {
            const lastFeature = features[features.length - 1].value;
            const width = (lastFeature.end - lastFeature.start + 1) * options.pixelBase;
            const x = options.pixelPosition + middle - ((options.position - parseInt(lastFeature.start)) * options.pixelBase);
            const height = this.#getFeatureValue(lastFeature) * multiplier;

            points.push(`${(x + width).toFixed(1)},${(histogramHeight - height).toFixed(1)}`);
            points.push(`${(x + width).toFixed(1)},${histogramHeight.toFixed(1)}`);
        }

        // Draw histogram points
        if (points.length > 0) {
            SVG.addChild(options.svgCanvasFeatures, "polyline", {
                points: points.join(" "),
                fill: this.config.histogramColor,
                cursor: "pointer",
            });
        }
    }

    // Get histogram default config
    getDefaultConfig() {
        return {
            maxValue: 10,
            histogramHeight: 75,
            histogramColor: "#428bca",
        };
    }

}
<|endoftext|>


<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2012-2013 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

YUI.add('search-results', function(Y) {

  juju.components.SearchResults = React.createClass({
    searchXhr: null,
    template: Handlebars.templates['search-results-tmpl.hbs'],

     /**
      If it's the same charm but for different series, collapse into one
      entity. We do this by converting the list to an OrderedDict, keyed on
      the match criteria (name, owner, type). When there is a key collision,
      add the series to the exist entity. Using an OrderedDict (versus a
      normal dict) is important to preserve sorting.

      @method collapseSeries
      @param {Array} entities The entities in their uncollapsed state.
     */
    collapseSeries: function(entities) {

      function seriesKey(series) {
        // XXX kadams54, 2015-05-21: This series mapping needs to be updated
        // with each release, at least until we can figure out a better way.
        // XXX urosj, 2015-11-04: We need to support all series, not just
        // Ubuntu ones.
        return {
          precise: 12.04,
          trusty:  14.04,
          utopic:  14.10,
          vivid:   15.04,
          wily:    15.10
        }[series.name];
      }

      function entityKey(entity) {
        return [entity.name, entity.owner, entity.type, entity.promulgated];
      }

      var collapsedEntities = {},
          orderedKeys = [];
      for (var i = 0, l = entities.length; i < l; i++) {
        var entity = entities[i],
            key = entityKey(entity),
            series = entity.series,
            url = entity.url || '',
            value = {name: series, url: url};
        // If the key already exists, append the series to the existing list.
        if (collapsedEntities[key]) {
          var collapsed = collapsedEntities[key];
          // Aggregate downloads across different series.
          collapsed.downloads += entity.downloads || 0;
          // Add series to the list.
          collapsed.series.push(value);
          // Ensure that the most recent series is first.
          collapsed.series.sort(function(a, b) {
            var k1 = seriesKey(a),
                k2 = seriesKey(b);
            // We want a reverse sort, so...
            return k2 - k1;
          });
          // De-dupe the series array.
          collapsed.series = collapsed.series.filter(function(s, pos, arry) {
            return !pos || s.name != arry[pos - 1].name;
          });
          // And that its URL is used for the entity.
          collapsed.url = collapsed.series[0].url;
        } else {
          // Convert all series attributes in the entities to lists.
          if (series) {
            entity.series = [value];
          } else {
            entity.series = [];
          }
          // Ensure downloads and URL are present.
          entity.downloads = entity.downloads || 0;
          entity.url = entity.url || '';
          entity.id = entity.series.length > 0 ?
              entity.series[0].name + '/' + entity.name : entity.name;
          collapsedEntities[key] = entity;
          // Save the key so we can preserve sort order.
          orderedKeys.push(key);
        }
      }
      // Now convert that object back to an ordered list and return it.
      var returnedEntities = [];
      for (var i = 0, l = orderedKeys.length; i < l; i++) {
        var k = orderedKeys[i];
        returnedEntities.push(collapsedEntities[k]);
      }
      return returnedEntities;
    },

    /**
      Handle successful searches by updating internal state with the results.

      @method searchSuccess
      @param {Array} rawResults The entity models returned by the search.
    */
    searchSuccess: function(rawResults) {
      // Parse the raw results.
      var results = rawResults.map(function(model) {
        return model.toEntity();
      }, this);
      results = this.collapseSeries(results);
      // Split the results into promulgated and normal.
      var promulgatedResults = [],
          normalResults = [];
      results.forEach(function(obj) {
        // Pass in a full id including the owner to allow looking up the entity.
        obj.storeId = '~' + obj.owner + '/' + obj.id;
        if (obj.promulgated) {
          promulgatedResults.push(obj);
        } else {
          normalResults.push(obj);
        }
      });
      var data = {
        standalone: false,
        text: this.props.query,
        hasResults: results.length > 0,
        solutionsCount: results.length,
        normalResultsCount: normalResults.length,
        normalResults: normalResults,
        promulgatedResultsCount: promulgatedResults.length,
        promulgatedResults: promulgatedResults
      };
      // These need to be set separately, seemingly due to a React quirk.
      this.setState({waitingForSearch: false});
      this.setState({data: data});
      this._changeActiveComponent('search-results');
    },

    /**
      Handle failed searches by displaying appropriate error notification.

      @method searchFailure
      @param {Object} response The failure response.
    */
    searchFailure: function(response) {
      // XXX: Implement error handling.
      console.error('Search request failed.');
    },

    /**
      Search the charmstore with the given filters.

      @method searchRequest
      @param {String} query The text to search for.
      @param {String} tags The tags to limit the search by.
    */
    searchRequest: function(query, tags) {
      this._changeActiveComponent('loading');
      this.setState({ waitingForSearch: true });
      this.searchXhr = this.props.charmstoreSearch(
        {text: query, tags: tags},
        this.searchSuccess,
        this.searchFailure,
        150
      );
    },

    /**
      Determines whether an API search request is actually needed. We only need
      to make a new search request if the query has changed since the last one.

      @method shouldSearch
      @param {Object} nextProps The next set of properties.
    */
    shouldSearch: function(nextProps) {
      if (!this.state.data || !this.state.data.text) {
        return true;
      }
      var nextQuery = JSON.stringify(nextProps.query),
          currentQuery = JSON.stringify(this.state.data.text);
      return nextQuery !== currentQuery;
    },

    getInitialState: function() {
      var state = this.generateState(this.props);
      state.waitingForSearch = false;
      return state;
    },

    componentDidMount: function() {
      this.searchRequest(this.props.query, this.props.tags);
    },

    componentWillUnmount: function() {
      this.searchXhr.abort();
    },

    componentWillReceiveProps: function(nextProps) {
      if (this.shouldSearch(nextProps)) {
        this.searchRequest(nextProps.query, this.props.tags);
      }
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      return this.state.activeComponent !== 'loading' ||
          this.shouldSearch(nextProps) && !this.state.waitingForSearch;
    },

    /**
      Generates the state for the search results.

      @method generateState
      @param {Object} nextProps The props which were sent to the component.
      @return {Object} A generated state object which can be passed to setState.
    */
    generateState: function(nextProps) {
      var state = {
        activeComponent: nextProps.activeComponent || 'loading'
      };
      switch (state.activeComponent) {
        case 'loading':
          var generateChangeDescription = nextProps.generateChangeDescription ||
              this.props.generateChangeDescription;
          state.activeChild = {
            component:

              <juju.components.Spinner />

          };
        break;
        case 'search-results':
          var html = this.template(this.state.data);
          state.activeChild = {
            component:

          };
        break;
      }
      return state;
    },

    /**
      Change the state to reflect the chosen component.

      @method _changeActiveComponent
      @param {String} newComponent The component to switch to.
    */
    _changeActiveComponent: function(newComponent) {
      var nextProps = this.state;
      nextProps.activeComponent = newComponent;
      this.setState(this.generateState(nextProps));
    },

    /**
      Handle any clicks inside the template and route them to the correct
      handler.

      @method _handleTemplateClicks
      @param {Object} e The click event
    */
    _handleTemplateClicks: function(e) {
      e.preventDefault();
      var target = e.target;
      var className = target.className;
      if (className.indexOf('list-block__entity-link') > -1) {
        this._handleEntityClick(target);
      }
    },

    /**
      Show the entity details when clicked.

      @method _handleEntityClick
      @param {Object} target The element that was clicked
    */
    _handleEntityClick: function(target) {
      this.props.changeState({
        sectionC: {
          component: 'charmbrowser',
          metadata: {
            activeComponent: 'entity-details',
            id: target.getAttribute('data-id')
          }
        }
      });
    },

    /**
      Generate the base classes from on the props.

      @method _generateClasses
      @returns {String} The collection of class names.
    */
    _generateClasses: function() {
      return classNames(
        'search-results',
        this.props.inline ? '' : 'search-results--floating'
      );
    },

    render: function() {
      return (

          {this.state.activeChild.component}

      );
    }
  });

}, '0.1.0', {requires: [
  'loading-spinner'
]});
<commit_msg>Fixed lint.<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2012-2013 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

YUI.add('search-results', function(Y) {

  juju.components.SearchResults = React.createClass({
    searchXhr: null,
    template: Handlebars.templates['search-results-tmpl.hbs'],

     /**
      If it's the same charm but for different series, collapse into one
      entity. We do this by converting the list to an OrderedDict, keyed on
      the match criteria (name, owner, type). When there is a key collision,
      add the series to the exist entity. Using an OrderedDict (versus a
      normal dict) is important to preserve sorting.

      @method collapseSeries
      @param {Array} entities The entities in their uncollapsed state.
     */
    collapseSeries: function(entities) {

      function seriesKey(series) {
        // XXX kadams54, 2015-05-21: This series mapping needs to be updated
        // with each release, at least until we can figure out a better way.
        // XXX urosj, 2015-11-04: We need to support all series, not just
        // Ubuntu ones.
        return {
          precise: 12.04,
          trusty:  14.04,
          utopic:  14.10,
          vivid:   15.04,
          wily:    15.10
        }[series.name];
      }

      function entityKey(entity) {
        return [entity.name, entity.owner, entity.type, entity.promulgated];
      }

      var collapsedEntities = {},
          orderedKeys = [];
      for (var i = 0, l = entities.length; i < l; i++) {
        var entity = entities[i],
            key = entityKey(entity),
            series = entity.series,
            url = entity.url || '',
            value = {name: series, url: url};
        // If the key already exists, append the series to the existing list.
        if (collapsedEntities[key]) {
          var collapsed = collapsedEntities[key];
          // Aggregate downloads across different series.
          collapsed.downloads += entity.downloads || 0;
          // Add series to the list.
          collapsed.series.push(value);
          // Ensure that the most recent series is first.
          collapsed.series.sort(function(a, b) {
            var k1 = seriesKey(a),
                k2 = seriesKey(b);
            // We want a reverse sort, so...
            return k2 - k1;
          });
          // De-dupe the series array.
          collapsed.series = collapsed.series.filter(function(s, pos, arry) {
            return !pos || s.name != arry[pos - 1].name;
          });
          // And that its URL is used for the entity.
          collapsed.url = collapsed.series[0].url;
        } else {
          // Convert all series attributes in the entities to lists.
          if (series) {
            entity.series = [value];
          } else {
            entity.series = [];
          }
          // Ensure downloads and URL are present.
          entity.downloads = entity.downloads || 0;
          entity.url = entity.url || '';
          entity.id = entity.series.length > 0 ?
              entity.series[0].name + '/' + entity.name : entity.name;
          collapsedEntities[key] = entity;
          // Save the key so we can preserve sort order.
          orderedKeys.push(key);
        }
      }
      // Now convert that object back to an ordered list and return it.
      var returnedEntities = [];
      for (var i = 0, l = orderedKeys.length; i < l; i++) {
        var k = orderedKeys[i];
        returnedEntities.push(collapsedEntities[k]);
      }
      return returnedEntities;
    },

    /**
      Handle successful searches by updating internal state with the results.

      @method searchSuccess
      @param {Array} rawResults The entity models returned by the search.
    */
    searchSuccess: function(rawResults) {
      // Parse the raw results.
      var results = rawResults.map(function(model) {
        return model.toEntity();
      }, this);
      results = this.collapseSeries(results);
      // Split the results into promulgated and normal.
      var promulgatedResults = [],
          normalResults = [];
      results.forEach(function(obj) {
        // Pass in a full id including the owner to allow looking up the entity.
        obj.storeId = '~' + obj.owner + '/' + obj.id;
        if (obj.promulgated) {
          promulgatedResults.push(obj);
        } else {
          normalResults.push(obj);
        }
      });
      var data = {
        standalone: false,
        text: this.props.query,
        hasResults: results.length > 0,
        solutionsCount: results.length,
        normalResultsCount: normalResults.length,
        normalResults: normalResults,
        promulgatedResultsCount: promulgatedResults.length,
        promulgatedResults: promulgatedResults
      };
      // These need to be set separately, seemingly due to a React quirk.
      this.setState({waitingForSearch: false});
      this.setState({data: data});
      this._changeActiveComponent('search-results');
    },

    /**
      Handle failed searches by displaying appropriate error notification.

      @method searchFailure
      @param {Object} response The failure response.
    */
    searchFailure: function(response) {
      // XXX: Implement error handling.
      console.error('Search request failed.');
    },

    /**
      Search the charmstore with the given filters.

      @method searchRequest
      @param {String} query The text to search for.
      @param {String} tags The tags to limit the search by.
    */
    searchRequest: function(query, tags) {
      this._changeActiveComponent('loading');
      this.setState({ waitingForSearch: true });
      this.searchXhr = this.props.charmstoreSearch(
        {text: query, tags: tags},
        this.searchSuccess,
        this.searchFailure,
        150
      );
    },

    /**
      Determines whether an API search request is actually needed. We only need
      to make a new search request if the query has changed since the last one.

      @method shouldSearch
      @param {Object} nextProps The next set of properties.
    */
    shouldSearch: function(nextProps) {
      if (!this.state.data || !this.state.data.text) {
        return true;
      }
      var nextQuery = JSON.stringify(nextProps.query),
          currentQuery = JSON.stringify(this.state.data.text);
      return nextQuery !== currentQuery;
    },

    getInitialState: function() {
      var state = this.generateState(this.props);
      state.waitingForSearch = false;
      return state;
    },

    componentDidMount: function() {
      this.searchRequest(this.props.query, this.props.tags);
    },

    componentWillUnmount: function() {
      this.searchXhr.abort();
    },

    componentWillReceiveProps: function(nextProps) {
      if (this.shouldSearch(nextProps)) {
        this.searchRequest(nextProps.query, this.props.tags);
      }
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      return this.state.activeComponent !== 'loading' ||
          this.shouldSearch(nextProps) && !this.state.waitingForSearch;
    },

    /**
      Generates the state for the search results.

      @method generateState
      @param {Object} nextProps The props which were sent to the component.
      @return {Object} A generated state object which can be passed to setState.
    */
    generateState: function(nextProps) {
      var state = {
        activeComponent: nextProps.activeComponent || 'loading'
      };
      switch (state.activeComponent) {
        case 'loading':
          var generateChangeDescription = nextProps.generateChangeDescription ||
              this.props.generateChangeDescription;
          state.activeChild = {
            component:

                <juju.components.Spinner />

          };
        break;
        case 'search-results':
          var html = this.template(this.state.data);
          state.activeChild = {
            component:

          };
        break;
      }
      return state;
    },

    /**
      Change the state to reflect the chosen component.

      @method _changeActiveComponent
      @param {String} newComponent The component to switch to.
    */
    _changeActiveComponent: function(newComponent) {
      var nextProps = this.state;
      nextProps.activeComponent = newComponent;
      this.setState(this.generateState(nextProps));
    },

    /**
      Handle any clicks inside the template and route them to the correct
      handler.

      @method _handleTemplateClicks
      @param {Object} e The click event
    */
    _handleTemplateClicks: function(e) {
      e.preventDefault();
      var target = e.target;
      var className = target.className;
      if (className.indexOf('list-block__entity-link') > -1) {
        this._handleEntityClick(target);
      }
    },

    /**
      Show the entity details when clicked.

      @method _handleEntityClick
      @param {Object} target The element that was clicked
    */
    _handleEntityClick: function(target) {
      this.props.changeState({
        sectionC: {
          component: 'charmbrowser',
          metadata: {
            activeComponent: 'entity-details',
            id: target.getAttribute('data-id')
          }
        }
      });
    },

    /**
      Generate the base classes from on the props.

      @method _generateClasses
      @returns {String} The collection of class names.
    */
    _generateClasses: function() {
      return classNames(
        'search-results',
        this.props.inline ? '' : 'search-results--floating'
      );
    },

    render: function() {
      return (

          {this.state.activeChild.component}

      );
    }
  });

}, '0.1.0', {requires: [
  'loading-spinner'
]});
<|endoftext|>


<commit_before>import Log from '../utils/logger.js';
import {BaseLoader, LoaderStatus, LoaderError} from './loader.js';

class FetchStreamLoader extends BaseLoader {

    static isSupported() {
        try {
            return (self.fetch && self.ReadableByteStream);
        } catch (e) {
            return false;
        }
    }

    constructor() {
        super('fetch-stream');
        this.TAG = this.constructor.name;
        this._requestAbort = false;
        this._contentLength = null;
        this._receivedLength = 0;
    }

    destroy() {
        if (this.isWorking()) {
            this.abort();
        }
        super.destroy();
    }

    open(url, range) {
        this._url = url;
        this._range = range;

        let headers = new self.Headers();

        if (range.from !== 0 || range.to !== -1) {
            let param;
            if (range.to !== -1) {
                param = 'bytes=' + range.from.toString() + '-' + range.to.toString();
            } else {
                param = 'bytes=' + range.from.toString() + '-';
            }
            headers.append('Range', param);
        }

        let params = {
            method: 'GET',
            headers: headers,
            mode: 'cors',
            cache: 'default'
        };

        this._status = LoaderStatus.kConnecting;
        self.fetch(this._url, params).then((res) => {
            if (this._requestAbort) {
                this._requestAbort = false;
                this._status = LoaderStatus.kIdle;
                return;
            }
            if (res.ok && (res.status >= 200 && res.status <= 299)) {
                let lengthHeader = res.headers.get('Content-Length');
                if (lengthHeader != null) {
                    this._contentLength = parseInt(lengthHeader);
                    if (this._contentLength !== 0) {
                        if (this._onContentLengthKnown) {
                            this._onContentLengthKnown(this._contentLength);
                        }
                    }
                }
                return this._pump.call(this, res.body.getReader());
            } else {
                this._status = LoaderStatus.kError;
                if (this._onError) {
                    this._onError(LoaderError.kHttpStatusCodeInvalid, {code: res.status, msg: res.statusText});
                } else {
                    throw 'FetchStreamLoader: Http code invalid, ' + res.status + ' ' + res.statusText;
                }
            }
        }).catch((e) => {
            this._status = LoaderStatus.kError;
            if (this._onError) {
                this._onError(LoaderError.kException, {code: -1, msg: e.message});
            } else {
                throw e;
            }
        });
    }

    abort() {
        this._requestAbort = true;
    }

    _pump(reader) {  // ReadableStreamReader
        return reader.read().then((result) => {
            if (result.done) {
                this._status = LoaderStatus.kComplete;
                if (this._onComplete) {
                    this._onComplete(this._range.from, this._range.from + this._receivedLength - 1);
                }
            } else {
                if (this._requestAbort === true) {
                    this._requestAbort = false;
                    this._status = LoaderStatus.kComplete;
                    return reader.cancel();
                }

                this._status = LoaderStatus.kBuffering;

                let chunk = result.value;
                let byteStart = this._range.from + this._receivedLength;
                this._receivedLength += chunk.byteLength;
                Log.v(this.TAG, 'Received chunk, size = ' + chunk.byteLength + ', total_received = ' + this._receivedLength);

                if (this._onDataArrival) {
                    this._onDataArrival(chunk, byteStart, this._receivedLength);
                }

                return this._pump(reader);
            }
        }).catch((e) => {
            this._status = LoaderStatus.kError;
            let type = 0;
            let info = null;

            if (this._contentLength === null ||
                (this._contentLength !== null && this._receivedLength < this._contentLength)) {
                type = LoaderError.kEarlyEof;
                info = {code: e.code, msg: 'Fetch stream meet Early-EOF'};
            } else {
                type = LoaderError.kException;
                info = {code: e.code, msg: e.message};
            }

            if (this._onError) {
                this._onError(type, info);
            } else {
                throw info.msg;
            }
        });
    }

}

export default FetchStreamLoader;<commit_msg>FetchStreamLoader: Report EarlyEof error only if e.code === 19 (NETWORK_ERR)<commit_after>import Log from '../utils/logger.js';
import {BaseLoader, LoaderStatus, LoaderError} from './loader.js';

class FetchStreamLoader extends BaseLoader {

    static isSupported() {
        try {
            return (self.fetch && self.ReadableByteStream);
        } catch (e) {
            return false;
        }
    }

    constructor() {
        super('fetch-stream');
        this.TAG = this.constructor.name;
        this._requestAbort = false;
        this._contentLength = null;
        this._receivedLength = 0;
    }

    destroy() {
        if (this.isWorking()) {
            this.abort();
        }
        super.destroy();
    }

    open(url, range) {
        this._url = url;
        this._range = range;

        let headers = new self.Headers();

        if (range.from !== 0 || range.to !== -1) {
            let param;
            if (range.to !== -1) {
                param = 'bytes=' + range.from.toString() + '-' + range.to.toString();
            } else {
                param = 'bytes=' + range.from.toString() + '-';
            }
            headers.append('Range', param);
        }

        let params = {
            method: 'GET',
            headers: headers,
            mode: 'cors',
            cache: 'default'
        };

        this._status = LoaderStatus.kConnecting;
        self.fetch(this._url, params).then((res) => {
            if (this._requestAbort) {
                this._requestAbort = false;
                this._status = LoaderStatus.kIdle;
                return;
            }
            if (res.ok && (res.status >= 200 && res.status <= 299)) {
                let lengthHeader = res.headers.get('Content-Length');
                if (lengthHeader != null) {
                    this._contentLength = parseInt(lengthHeader);
                    if (this._contentLength !== 0) {
                        if (this._onContentLengthKnown) {
                            this._onContentLengthKnown(this._contentLength);
                        }
                    }
                }
                return this._pump.call(this, res.body.getReader());
            } else {
                this._status = LoaderStatus.kError;
                if (this._onError) {
                    this._onError(LoaderError.kHttpStatusCodeInvalid, {code: res.status, msg: res.statusText});
                } else {
                    throw 'FetchStreamLoader: Http code invalid, ' + res.status + ' ' + res.statusText;
                }
            }
        }).catch((e) => {
            this._status = LoaderStatus.kError;
            if (this._onError) {
                this._onError(LoaderError.kException, {code: -1, msg: e.message});
            } else {
                throw e;
            }
        });
    }

    abort() {
        this._requestAbort = true;
    }

    _pump(reader) {  // ReadableStreamReader
        return reader.read().then((result) => {
            if (result.done) {
                this._status = LoaderStatus.kComplete;
                if (this._onComplete) {
                    this._onComplete(this._range.from, this._range.from + this._receivedLength - 1);
                }
            } else {
                if (this._requestAbort === true) {
                    this._requestAbort = false;
                    this._status = LoaderStatus.kComplete;
                    return reader.cancel();
                }

                this._status = LoaderStatus.kBuffering;

                let chunk = result.value;
                let byteStart = this._range.from + this._receivedLength;
                this._receivedLength += chunk.byteLength;

                if (this._onDataArrival) {
                    this._onDataArrival(chunk, byteStart, this._receivedLength);
                }

                return this._pump(reader);
            }
        }).catch((e) => {
            this._status = LoaderStatus.kError;
            let type = 0;
            let info = null;

            if (e.code === 19 && // NETWORK_ERR
                (this._contentLength === null ||
                (this._contentLength !== null && this._receivedLength < this._contentLength))) {
                type = LoaderError.kEarlyEof;
                info = {code: e.code, msg: 'Fetch stream meet Early-EOF'};
            } else {
                type = LoaderError.kException;
                info = {code: e.code, msg: e.message};
            }

            if (this._onError) {
                this._onError(type, info);
            } else {
                throw info.msg;
            }
        });
    }

}

export default FetchStreamLoader;<|endoftext|>


<commit_before>const library = (lib) => {
    const store = lib.store;
    const dispatch = store.dispatch;
    const { config, network } = store.getState();

    const saveBounds = () => {
        const now = window.performance.now();

        if (now - self.lastFilterSearch < 250) {
            clearTimeout(self.filterSearchTimeOut);
        }

        self.lastFilterSearch = now;

        self.filterSearchTimeOut = setTimeout(() => {
            dispatch(lib.actions.config.set('bounds', lib.app.browserWindows.main.getBounds()));
        }, 250);
    };

    // Prevent some events
    window.addEventListener('dragover', (e) => e.preventDefault(), false);
    window.addEventListener('drop', (e) => e.preventDefault(), false);

    // Remember dimensions and positionning
    const currentWindow = lib.app.browserWindows.main;
    currentWindow.on('resize', saveBounds);
    currentWindow.on('move', saveBounds);

    // load data and apply app settings
    dispatch(lib.actions.tracks.find());
    dispatch(lib.actions.playlists.refresh());
    dispatch(lib.actions.settings.check());

    console.log(dispatch(lib.actions.player.shuffle(true)));
}

export default library;
<commit_msg>change init<commit_after>const library = (lib) => {
    const store = lib.store;
    const dispatch = store.dispatch;
    const { config, network } = store.getState();

    const saveBounds = () => {
        const now = window.performance.now();

        if (now - self.lastFilterSearch < 250) {
            clearTimeout(self.filterSearchTimeOut);
        }

        self.lastFilterSearch = now;

        self.filterSearchTimeOut = setTimeout(() => {
            dispatch(lib.actions.config.set('bounds', lib.app.browserWindows.main.getBounds()));
        }, 250);
    };

    // Prevent some events
    window.addEventListener('dragover', (e) => e.preventDefault(), false);
    window.addEventListener('drop', (e) => e.preventDefault(), false);

    // Remember dimensions and positionning
    const currentWindow = lib.app.browserWindows.main;
    currentWindow.on('resize', saveBounds);
    currentWindow.on('move', saveBounds);

    // load data and apply app settings
    dispatch(lib.actions.tracks.find());
    dispatch(lib.actions.playlists.refresh());
    dispatch(lib.actions.settings.check());

    dispatch(lib.actions.player.shuffle(true)).then(console.log)
}

export default library;
<|endoftext|>