<commit_before>$(function () {
    /*var date = new Date();
    var d = date.getDate();
    var m = date.getMonth();
    var y = date.getFullYear();*/

    $('#calendar-holder').fullCalendar({
        defaultView: 'month',
        selectable: true,
        lazyFetching: true,
        header: {
            left: 'prev, next',
            center: 'title',
            right: 'month,basicWeek,basicDay,'
        },
        select: function(startDate, endDate, allDay) {
            $( "#dialog-create-events" ).dialog({
                buttons: {
                    Ajouter: function() {
                        startDate = startDate.getUTCFullYear() + "-" + (1 + startDate.getUTCMonth()) + "-" +  (1 + startDate.getUTCDate()) + " " + $("#start_time").val();
                        endDate = endDate.getUTCFullYear() + "-" + (1 + endDate.getUTCMonth()) + "-" +  (1 + endDate.getUTCDate()) + " " + $("#end_time").val();
                        var json = { name: $("#lesson_name").val(), startDate: startDate, endDate: endDate};
                        $.ajax({
                            url     : Routing.generate('agenda_add_lesson', { data: JSON.stringify(json) } ),
                            type    : 'POST',
                            success : function(response){
                                if(response === true) {
                                    window.location.reload();
                                }
                            }
                         });
                    },
                    Annuler: function() {
                        $( this ).dialog( "close" );
                    }
                }
            });
            return;
        },
        eventClick: function(calEvent, jsEvent, view) {
            var json = { name:calEvent.title, startDate:calEvent.start, endDate:calEvent.end };
            $("
Voulez-vous vraiment supprimer cette entrée ?
").dialog({
                buttons: {
                  Delete: function() {
                    $.ajax({
                          url     : Routing.generate('agenda_delete_lesson', { id:calEvent.id } ),
                          type    : 'POST',
                          success : function(response){
                              if(response === true) {
                                  window.location.reload();
                              }
                          }
                      });
                    },
                  Cancel: function() {
                    $( this ).dialog( "close" );
                  }
                }
            });

        },
        timeFormat: {
            // for agendaWeek and agendaDay
            agenda: 'h:mmt', // 5:00 - 6:30
            // for all other views
            '': 'H:mm{ - H:mm}'  // 7p
        },
        eventSources: [
            {
                url: Routing.generate('fullcalendar_loader'),
                type: 'POST',
                // A way to add custom filters to your event listeners
                data: {
                },
                error: function() {
                   alert('There was an error while fetching Google Calendar!');
                }
            }
        ]
    });
});
<commit_msg>Calendar display customize (eg.)<commit_after>$(function () {
    /*var date = new Date();
    var d = date.getDate();
    var m = date.getMonth();
    var y = date.getFullYear();*/

    $('#calendar-holder').fullCalendar({
        /** You can change value here (as event color, calendar column...) **/
        defaultView: 'month',
        selectable: true,
        lazyFetching: true,
        eventColor: '#3d4c67',
        eventTextColor: '#FFFFFF',
        weekends: true,
        /** You can change value here (as event color, calendar column...) **/
        header: {
            left: 'prev, next',
            center: 'title',
            right: 'month,basicWeek,basicDay,'
        },
        select: function(startDate, endDate, allDay) {
            $( "#dialog-create-events" ).dialog({
                buttons: {
                    Ajouter: function() {
                        startDate = startDate.getUTCFullYear() + "-" + (1 + startDate.getUTCMonth()) + "-" +  (1 + startDate.getUTCDate()) + " " + $("#start_time").val();
                        endDate = endDate.getUTCFullYear() + "-" + (1 + endDate.getUTCMonth()) + "-" +  (1 + endDate.getUTCDate()) + " " + $("#end_time").val();
                        var json = { name: $("#lesson_name").val(), startDate: startDate, endDate: endDate};
                        $.ajax({
                            url     : Routing.generate('agenda_add_lesson', { data: JSON.stringify(json) } ),
                            type    : 'POST',
                            success : function(response){
                                if(response === true) {
                                    window.location.reload();
                                }
                            }
                         });
                    },
                    Annuler: function() {
                        $( this ).dialog( "close" );
                    }
                }
            });
            return;
        },
        eventClick: function(calEvent, jsEvent, view) {
            var json = { name:calEvent.title, startDate:calEvent.start, endDate:calEvent.end };
            $("
Voulez-vous vraiment supprimer cette entrée ?
").dialog({
                buttons: {
                  Delete: function() {
                    $.ajax({
                          url     : Routing.generate('agenda_delete_lesson', { id:calEvent.id } ),
                          type    : 'POST',
                          success : function(response){
                              if(response === true) {
                                  window.location.reload();
                              }
                          }
                      });
                    },
                  Cancel: function() {
                    $( this ).dialog( "close" );
                  }
                }
            });

        },
        timeFormat: {
            // for agendaWeek and agendaDay
            agenda: 'h:mmt', // 5:00 - 6:30
            // for all other views
            '': 'H:mm{ - H:mm}'  // 7p
        },
        eventSources: [
            {
                url: Routing.generate('fullcalendar_loader'),
                type: 'POST',
                // A way to add custom filters to your event listeners
                data: {
                },
                error: function() {
                   alert('There was an error while fetching Google Calendar!');
                }
            }
        ]
    });
});
<|endoftext|>


<commit_before>
var wfStore = Ext.create('Ext.data.ArrayStore', {
    fields: [
       {name: 'name'},
       {name: 'desc'},
       {name: 'status'},
       {name: 'date', type: 'date', dateFormat: 'Y-m-d'},
       {name: 'date2'},
       {name: 'workflowId'}
    ],
    sortOnLoad: true,
    sorters: { property: 'date2', direction : 'DESC' },
    proxy: {
	         type: 'ajax',
	          url: getWorkflowListURL,
	          reader: {
		             root: 'list'
		          }
	},
	autoLoad: true
});

wfStore.load(function() {
		console.log(arguments);
});

Ext.define('CF.view.WfGrid', {
	extend: 'Ext.grid.Panel',
	initComponent: function() {
	    Ext.apply(this, {
	        store: wfStore,
	        id: 'wfGrid',
	        columns: [
	            {
	                text     : 'Name',
	                flex     : 1,
	                sortable : true,
	                dataIndex: 'name'
	            },
	            {
	                text     : 'Desc',
	                flex     : 1,
	                sortable : true,
	                dataIndex: 'desc',
	                renderer: function(value, metaData, record, row, col, store, gridView) {
	                	if (value == null || value === '' || value === 'null') {
	                		return '-';
	                	}

	                	return value;
	                }
	            },
	            {
	                text     : 'Status',
	                width    : 75,
	                sortable : true,
	                renderer : statusRenderer,
	                dataIndex: 'status'
	            },
	            {
	                text     : 'Date',
	                width    : 90,
	                sortable : true,
	                renderer : Ext.util.Format.dateRenderer('d - m - Y'),
	                dataIndex: 'date'
	            },
	            {
	                xtype: 'actioncolumn',
	                width: 55,
	                items: [
		            {
		                icon   : localResourcesPath+'/img/Farm-Fresh_page_white_text.png',
		                tooltip: 'Download logfiles',
		                handler: function(grid, rowIndex, colIndex) {
		                    var rec = wfStore.getAt(rowIndex);

		                    window.open(downloadWorkflowOutputURL + '&workflowId=' + rec.get('workflowId'), '_self');
		                }
		            },
		            {
		                icon   : localResourcesPath+'/img/Farm-Fresh_arrow_rotate_clockwise.png',
		                tooltip: 'Reuse',
		                handler: function(grid, rowIndex, colIndex) {
		                    var rec = wfStore.getAt(rowIndex);

		                    Ext.Ajax.request({
		                    	url: "/j2ep-1.0/prov/workflow/"+encodeURIComponent(rec.get('name')),
      	      	    			params: {
      	      	    			},
      	      	    			method: 'GET',
      	      	    			success: function(response){
      	      	    				var object = JSON.parse(response.responseText);

      	      	    				var input = {};
      	      	    				object.input.forEach(function(item) {
      	      	    					input[item.name] = item;
      	      	    				});

				                    Ext.Ajax.request({
				                    	url: input.solverconf.url,
		      	      	    			success: function(response){
		      	      	    				var object = JSON.parse(response.responseText);

		      	      	    				// reuse solver
		      	      	    				var solverType = Ext.getCmp('solvertype');
		      	      	    				var solver = solverType.store.findRecord('name', object.solver);
		      	      	    				solverType.clearValue();
		      	      	    				solverType.setValue(solver.get('abbr'));

		      	      	    				// reuse velocity when store is loaded
											var velocityCombo = Ext.getCmp('velocity');
		      	      	    				velocityCombo.store.addListener('add', function() {
			  	      	    					velocityCombo.setValue(object.velocity_model);

			      	      	    				solverConfStore.loadData(object.fields);

			      	      	    				// TODO fix selecting events and stations
			      	      	    				// var eventGrid = Ext.getCmp('gridEvents');
			      	      	    				// Ext.util.Observable.capture(ctrl, function(evname) {console.log("ctrl: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(ctrl.eventstore, function(evname) {console.log("store: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(eventGrid, function(evname) {console.log("grid: ", evname, arguments);});
			      	      	    				// eventGrid.on('add', function() {
			      	      	    				// 	console.log('add', arguments);
			      	      	    				// }, this);
			      	      	    				// Ext.util.Observable.capture(eventGrid.getSelectionModel(), function(evname) {console.log("grid: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(ctrl.mapPanel, function(evname) {console.log("mapPanel: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(ctrl.mapPanel.map.events, function(evname) {console.log("map: ", evname, arguments);});

			      	      	    				// ctrl.eventstore.addListener('refresh', function() {
				      	      	    			// 	object.events.forEach(function(eventId) {
				      	      	    			// 		var record = eventGrid.store.findRecord('eventId', eventId);
				      	      	    			// 		eventGrid.getSelectionModel().select(record);
				      	      	    			// 	});
				      	      	    			// }, this, { single: true });

												// reuse events
			      	      	    				getEvents(ctrl, input.quakeml.url);

			      	      	    				// reuse stations
			      	      	    				getStations(ctrl, input.stations.url, input.stations['mime-type'] === 'application/xml' ? STXML_TYPE : STPOINTS_TYPE);
		      	      	    					var selectedStations = Ext.getCmp('gridStations').getSelectionModel().selected;
		      	      	    				}, this, { single: true });

		      	      	    				// reuse mesh and trigger velocity store reload
		      	      	    				Ext.getCmp('meshes').setValue(object.mesh);
		      	      	    			},
		      	      	    			failure: function(response) {
		      	      	    				Ext.Msg.alert("Error", "Failed to get workflow settings!");
		      	      	                }
				                    })
      	      	    			},
      	      	    			failure: function(response) {
      	      	    				Ext.Msg.alert("Error", "Failed to get workflow from provenance api!");
      	      	                }
		                    })
		                }
		            },
	                {
	                    icon   : localResourcesPath+'/img/delete-icon.png',
	                    tooltip: 'Delete instance',
	                    handler: function(grid, rowIndex, colIndex) {
	                        var rec = wfStore.getAt(rowIndex);
	                        Ext.Msg.confirm('Warning', 'Are you sure that you want to delete '+rec.get('name')+"?",
	          	                  function(btn) {
	          	                  	if(btn === 'yes')
	          	                  	{
	    	      	                  	Ext.Ajax.request({
	    	      	      	    			url: deleteWorkflowURL,
	    	      	      	    			params: {
	    	      	      	    				"workflowId": rec.get('workflowId')
	    	      	      	    			},
	    	      	      	    			success: function(response){
	    	      	      	    				wfStore.load();
	    	      	      	    			},
	    	      	      	    			failure: function(response) {
	    	      	      	    				Ext.Msg.alert("Error", "Delete failed!");
	    	      	      	                }
	    	      	                    });
	          	                  	}
	          	            });
	                    }
	                }
	                ]
	            }
	        ],
	        flex: 1
	    });
	    this.callParent(arguments);
	}
});

var refreshMenuControl = [
	{
       html: 'Submited workflows'
	},
	"->",
	{
		tooltip: 'Refresh list',
		handler: function() {
			  wfStore.load();
		},
		style: {
		    background:'none',
		    backgroundImage: 'url('+localResourcesPath+'/img/refresh-icon.png)',
		    backgroundSize: '90% 85%',
		    backgroundRepeat: 'no-repeat',
			height: 32,
			width: 45,
			margin: 1,
			marginRight: '10px'
		},
		height: 35,
		width: 35
	},
	{
		tooltip: 'Go to Document Library
(open in a new win)',
		height: 32,
		width: 32,
		handler: function() {
		    openInNewTab('file-manager');
		},
		style: {
		    background:'none',
		    backgroundImage: 'url('+localResourcesPath+'/img/folder-icon.png)',
		    backgroundSize: '90% 90%',
		    backgroundRepeat: 'no-repeat',
			height: 32,
			width: 32,
			top: 0,
			margin: 1,
			marginRight: '10px'
		},
		height: 32,
		width: 32
	}
	];

Ext.define('CF.view.Control', {
	  extend:'Ext.form.Panel',
		layout: 'fit',
		  viewConfig      : {
		    style           : { overflow: 'scroll', overflowX: 'hidden' }
		  },
	  dockedItems:
		  [{
		    xtype: 'toolbar',
		    dock: 'top',
			height: 35,
		    items: refreshMenuControl
		}],
	  items: [Ext.create('CF.view.WfGrid')]
	});

function statusRenderer(val) {
    if (val === 'INIT' || val === 'RUNNING') {
        return '' + val + '';
    }
    else if (val === 'ERROR') {
        return '' + val + '';
    }
    return val;
}

function openInNewTab(url)
{
  var win=window.open(url, '_blank');
  win.focus();
}

<commit_msg>Error message<commit_after>
var wfStore = Ext.create('Ext.data.ArrayStore', {
    fields: [
       {name: 'name'},
       {name: 'desc'},
       {name: 'status'},
       {name: 'date', type: 'date', dateFormat: 'Y-m-d'},
       {name: 'date2'},
       {name: 'workflowId'}
    ],
    sortOnLoad: true,
    sorters: { property: 'date2', direction : 'DESC' },
    proxy: {
	         type: 'ajax',
	          url: getWorkflowListURL,
	          reader: {
		             root: 'list'
		          }
	},
	autoLoad: true
});

wfStore.load(function() {
		console.log(arguments);
});

Ext.define('CF.view.WfGrid', {
	extend: 'Ext.grid.Panel',
	initComponent: function() {
	    Ext.apply(this, {
	        store: wfStore,
	        id: 'wfGrid',
	        columns: [
	            {
	                text     : 'Name',
	                flex     : 1,
	                sortable : true,
	                dataIndex: 'name'
	            },
	            {
	                text     : 'Desc',
	                flex     : 1,
	                sortable : true,
	                dataIndex: 'desc',
	                renderer: function(value, metaData, record, row, col, store, gridView) {
	                	if (value == null || value === '' || value === 'null') {
	                		return '-';
	                	}

	                	return value;
	                }
	            },
	            {
	                text     : 'Status',
	                width    : 75,
	                sortable : true,
	                renderer : statusRenderer,
	                dataIndex: 'status'
	            },
	            {
	                text     : 'Date',
	                width    : 90,
	                sortable : true,
	                renderer : Ext.util.Format.dateRenderer('d - m - Y'),
	                dataIndex: 'date'
	            },
	            {
	                xtype: 'actioncolumn',
	                width: 55,
	                items: [
		            {
		                icon   : localResourcesPath+'/img/Farm-Fresh_page_white_text.png',
		                tooltip: 'Download logfiles',
		                handler: function(grid, rowIndex, colIndex) {
		                    var rec = wfStore.getAt(rowIndex);

		                    window.open(downloadWorkflowOutputURL + '&workflowId=' + rec.get('workflowId'), '_self');
		                }
		            },
		            {
		                icon   : localResourcesPath+'/img/Farm-Fresh_arrow_rotate_clockwise.png',
		                tooltip: 'Reuse',
		                handler: function(grid, rowIndex, colIndex) {
		                    var rec = wfStore.getAt(rowIndex);

		                    Ext.Ajax.request({
		                    	url: "/j2ep-1.0/prov/workflow/"+encodeURIComponent(rec.get('name')),
      	      	    			params: {
      	      	    			},
      	      	    			method: 'GET',
      	      	    			success: function(response){
      	      	    				var object = JSON.parse(response.responseText);

      	      	    				var input = {};
      	      	    				object.input.forEach(function(item) {
      	      	    					input[item.name] = item;
      	      	    				});

				                    Ext.Ajax.request({
				                    	url: input.solverconf.url,
		      	      	    			success: function(response){
		      	      	    				var object = JSON.parse(response.responseText);
		      	      	    				if (object === null) {
		      	      	    					Ext.Msg.alert("Failed to get workflow settings");
		      	      	    					return;
		      	      	    				}

		      	      	    				// reuse solver
		      	      	    				var solverType = Ext.getCmp('solvertype');
		      	      	    				var solver = solverType.store.findRecord('name', object.solver);
		      	      	    				solverType.clearValue();
		      	      	    				solverType.setValue(solver.get('abbr'));

		      	      	    				// reuse velocity when store is loaded
											var velocityCombo = Ext.getCmp('velocity');
		      	      	    				velocityCombo.store.addListener('add', function() {
			  	      	    					velocityCombo.setValue(object.velocity_model);

			      	      	    				solverConfStore.loadData(object.fields);

			      	      	    				// TODO fix selecting events and stations
			      	      	    				// var eventGrid = Ext.getCmp('gridEvents');
			      	      	    				// Ext.util.Observable.capture(ctrl, function(evname) {console.log("ctrl: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(ctrl.eventstore, function(evname) {console.log("store: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(eventGrid, function(evname) {console.log("grid: ", evname, arguments);});
			      	      	    				// eventGrid.on('add', function() {
			      	      	    				// 	console.log('add', arguments);
			      	      	    				// }, this);
			      	      	    				// Ext.util.Observable.capture(eventGrid.getSelectionModel(), function(evname) {console.log("grid: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(ctrl.mapPanel, function(evname) {console.log("mapPanel: ", evname, arguments);});
			      	      	    				// Ext.util.Observable.capture(ctrl.mapPanel.map.events, function(evname) {console.log("map: ", evname, arguments);});

			      	      	    				// ctrl.eventstore.addListener('refresh', function() {
				      	      	    			// 	object.events.forEach(function(eventId) {
				      	      	    			// 		var record = eventGrid.store.findRecord('eventId', eventId);
				      	      	    			// 		eventGrid.getSelectionModel().select(record);
				      	      	    			// 	});
				      	      	    			// }, this, { single: true });

												// reuse events
			      	      	    				getEvents(ctrl, input.quakeml.url);

			      	      	    				// reuse stations
			      	      	    				getStations(ctrl, input.stations.url, input.stations['mime-type'] === 'application/xml' ? STXML_TYPE : STPOINTS_TYPE);
		      	      	    					var selectedStations = Ext.getCmp('gridStations').getSelectionModel().selected;
		      	      	    				}, this, { single: true });

		      	      	    				// reuse mesh and trigger velocity store reload
		      	      	    				Ext.getCmp('meshes').setValue(object.mesh);
		      	      	    			},
		      	      	    			failure: function(response) {
		      	      	    				Ext.Msg.alert("Error", "Failed to get workflow settings!");
		      	      	                }
				                    })
      	      	    			},
      	      	    			failure: function(response) {
      	      	    				Ext.Msg.alert("Error", "Failed to get workflow from provenance api!");
      	      	                }
		                    })
		                }
		            },
	                {
	                    icon   : localResourcesPath+'/img/delete-icon.png',
	                    tooltip: 'Delete instance',
	                    handler: function(grid, rowIndex, colIndex) {
	                        var rec = wfStore.getAt(rowIndex);
	                        Ext.Msg.confirm('Warning', 'Are you sure that you want to delete '+rec.get('name')+"?",
	          	                  function(btn) {
	          	                  	if(btn === 'yes')
	          	                  	{
	    	      	                  	Ext.Ajax.request({
	    	      	      	    			url: deleteWorkflowURL,
	    	      	      	    			params: {
	    	      	      	    				"workflowId": rec.get('workflowId')
	    	      	      	    			},
	    	      	      	    			success: function(response){
	    	      	      	    				wfStore.load();
	    	      	      	    			},
	    	      	      	    			failure: function(response) {
	    	      	      	    				Ext.Msg.alert("Error", "Delete failed!");
	    	      	      	                }
	    	      	                    });
	          	                  	}
	          	            });
	                    }
	                }
	                ]
	            }
	        ],
	        flex: 1
	    });
	    this.callParent(arguments);
	}
});

var refreshMenuControl = [
	{
       html: 'Submited workflows'
	},
	"->",
	{
		tooltip: 'Refresh list',
		handler: function() {
			  wfStore.load();
		},
		style: {
		    background:'none',
		    backgroundImage: 'url('+localResourcesPath+'/img/refresh-icon.png)',
		    backgroundSize: '90% 85%',
		    backgroundRepeat: 'no-repeat',
			height: 32,
			width: 45,
			margin: 1,
			marginRight: '10px'
		},
		height: 35,
		width: 35
	},
	{
		tooltip: 'Go to Document Library
(open in a new win)',
		height: 32,
		width: 32,
		handler: function() {
		    openInNewTab('file-manager');
		},
		style: {
		    background:'none',
		    backgroundImage: 'url('+localResourcesPath+'/img/folder-icon.png)',
		    backgroundSize: '90% 90%',
		    backgroundRepeat: 'no-repeat',
			height: 32,
			width: 32,
			top: 0,
			margin: 1,
			marginRight: '10px'
		},
		height: 32,
		width: 32
	}
	];

Ext.define('CF.view.Control', {
	  extend:'Ext.form.Panel',
		layout: 'fit',
		  viewConfig      : {
		    style           : { overflow: 'scroll', overflowX: 'hidden' }
		  },
	  dockedItems:
		  [{
		    xtype: 'toolbar',
		    dock: 'top',
			height: 35,
		    items: refreshMenuControl
		}],
	  items: [Ext.create('CF.view.WfGrid')]
	});

function statusRenderer(val) {
    if (val === 'INIT' || val === 'RUNNING') {
        return '' + val + '';
    }
    else if (val === 'ERROR') {
        return '' + val + '';
    }
    return val;
}

function openInNewTab(url)
{
  var win=window.open(url, '_blank');
  win.focus();
}

<|endoftext|>


<commit_before>/*
 * Provides methods for input validation.
 */
var InputValidator =
{
    EMPTY: " is null or empty.",
    NULL: " is null.",
    UNDEFINED: " is undefined.",

    isArray: function(object)
    {
        return Array.isArray(object);
    },

    isNumber: function(n)
    {
        return !isNaN(parseFloat(n)) && isFinite(n);
    },

    validateInRange: function(objectName, object, low, high)
    {
        this.validateIsNumber(objectName, object);

        if (object < low || high < object)
        {
            LOGGER.error(new Error().stack);
            throw objectName + " is out of range [" + low + ", " + high + "]: "
                    + object;
        }
    },

    validateIsNumber: function(objectName, object)
    {
        if (typeof object !== "number")
        {
            LOGGER.error(new Error().stack);
            throw objectName + " is not a number: " + object;
        }
    },

    validateNotEmpty: function(objectName, object)
    {
        if (InputValidator.isArray(object))
        {
            if (object.length == 0)
            {
                // Empty array.
                LOGGER.error(new Error().stack);
                throw objectName + InputValidator.EMPTY;
            }
        }
        else if (InputValidator.isNumber(object))
        {
            // Valid.
        }
        else if (object === true || object === false)
        {
            // Valid.
        }
        else
        {
            if (!object)
            {
                LOGGER.error(new Error().stack);
                throw objectName + InputValidator.EMPTY;
            }
        }
    },

    validateNotNull: function(objectName, object)
    {
        if (object === undefined)
        {
            LOGGER.error(new Error().stack);
            throw objectName + InputValidator.UNDEFINED;
        }

        if (object === null)
        {
            LOGGER.error(new Error().stack);
            throw objectName + InputValidator.NULL;
        }
    }
}
<commit_msg>Added a validateBoolean() method.<commit_after>/*
 * Provides methods for input validation.
 */
var InputValidator =
{
    EMPTY: " is null or empty.",
    NULL: " is null.",
    UNDEFINED: " is undefined.",

    isArray: function(object)
    {
        return Array.isArray(object);
    },

    isNumber: function(n)
    {
        return !isNaN(parseFloat(n)) && isFinite(n);
    },

    validateBoolean: function(objectName,object)
    {
        if (object !== true && object !== false)
        {
            LOGGER.error(new Error().stack);
            throw objectName + " is not a boolean: " + object;
        }
    },

    validateInRange: function(objectName, object, low, high)
    {
        this.validateIsNumber(objectName, object);

        if (object < low || high < object)
        {
            LOGGER.error(new Error().stack);
            throw objectName + " is out of range [" + low + ", " + high + "]: "
                    + object;
        }
    },

    validateIsNumber: function(objectName, object)
    {
        if (typeof object !== "number")
        {
            LOGGER.error(new Error().stack);
            throw objectName + " is not a number: " + object;
        }
    },

    validateNotEmpty: function(objectName, object)
    {
        if (InputValidator.isArray(object))
        {
            if (object.length == 0)
            {
                // Empty array.
                LOGGER.error(new Error().stack);
                throw objectName + InputValidator.EMPTY;
            }
        }
        else if (InputValidator.isNumber(object))
        {
            // Valid.
        }
        else if (object === true || object === false)
        {
            // Valid.
        }
        else
        {
            if (!object)
            {
                LOGGER.error(new Error().stack);
                throw objectName + InputValidator.EMPTY;
            }
        }
    },

    validateNotNull: function(objectName, object)
    {
        if (object === undefined)
        {
            LOGGER.error(new Error().stack);
            throw objectName + InputValidator.UNDEFINED;
        }

        if (object === null)
        {
            LOGGER.error(new Error().stack);
            throw objectName + InputValidator.NULL;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2011 Joyent, Inc.  All rights reserved.

var assert = require('assert');
var crypto = require('crypto');

var ldap = require('ldapjs');
var restify = require('restify');
var sprintf = require('sprintf').sprintf;
var uuid = require('node-uuid');

///--- Globals

var hidden = new ldap.Control({
  type: '1.3.6.1.4.1.38678.1',
  criticality: true
});
var log = restify.log;

var AES_KEY = uuid().replace('-').substring(0, 16);

///--- Helpers

function _randomId(min, max) {
  if (!min) min = 0;
  if (!max) max = Math.pow(2, 32) - 1;

  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function _merge(obj1, obj2) {
  Object.keys(obj2).forEach(function(k) {
    if (!obj1.hasOwnProperty(k))
      obj1[k] = obj2[k];
  });

  return obj1;
}

//
// http://www.youtube.com/watch?v=J7RsYvRSyXs
//
// In the ghetto
// On a cold and gray Chicago mornin'
// Another little baby child is born
// In the ghetto
// (In the ghetto)
// And his mama cries
// because if there's one thing that she don't need
// it's another little hungry mouth to feed
// In the ghetto
//
// Basically, this lets a password token last up to a day, statelessly, since
// the client doesn't call capi back for a token.  Asking for a token at 23:59?
// fuck off.
//
function _forgotPasswordCode(customerId) {
  var cipher = crypto.createCipher('aes-128-cbc', AES_KEY);
  var now = new Date();
  cipher.update('' + (now.getUTCDay() + 1));
  cipher.update('' + now.getUTCDate());
  cipher.update('' + (now.getUTCMonth() + 1));
  cipher.update('' + now.getUTCFullYear());
  cipher.update(customerId.replace('-', ''), 'utf8', 'hex');
  return cipher.final('hex');
}

function _translate(entry) {
  assert.ok(entry);

  var customer = {
    id: _randomId(),
    uuid: entry.uuid,
    customer_id: entry.uuid,
    customer_uuid: entry.uuid,
    login: entry.login,
    email_address: entry.email,
    first_name: entry.cn,
    last_name: entry.sn,
    company_name: entry.company || null
  };

  if (entry.address && entry.address.length) {
    if (!Array.isArray(entry.address))
      entry.address = [entry.address];
    for (var i = 0; i < entry.address.length; i++)
      customer['street_' + (i + 1)] = entry.address[i];
  }

  if (!customer.street_1)
    customer.street_1 = null;

  if (!customer.street_2)
    customer.street_2 = null;

  var dn = ldap.parseDN(entry.dn);
  if (dn.childOf('ou=operators, o=smartdc')) {
    customer.role_type = 2;
    customer.role = 2;
  }

  return _merge(customer, {
    city: entry.city || null,
    state: entry.state || null,
    postal_code: entry.postalcode || null,
    country: entry.country || null,
    phone_number: entry.phone || null,
    role_type: 1,
    role: 1,
    asset_id: null,
    legacy_id: null,
    deleted_at: null,
    alternate_email_address: null,
    forgot_password_code: _forgotPasswordCode(entry.uuid),
    activation_code: null,
    activated_at: entry._ctime,
    created_at: entry._ctime,
    updated_at: entry._mtime
  });
}

///--- Exports

module.exports = {

  loadCustomers: function loadCustomers(ldap, filter, translate, callback,
                                        base) {
    assert.ok(ldap);
    assert.ok(filter);
    assert.ok(translate !== undefined);

    if (typeof(translate) === 'function') {
      base = callback;
      callback = translate;
      translate = true;
    }

    if (!base)
      base = 'o=smartdc';

    var opts = {
      scope: 'sub',
      filter: filter
    };
    return ldap.search(base, opts, hidden, function(err, result) {
      if (err)
        return callback(new restify.InternalError(500, err.message));

      var entries = [];
      result.on('searchEntry', function(entry) {
        entries.push((translate ? _translate(entry.object) : entry.object));
      });
      result.on('end', function() {
        return callback(null, entries);
      });
    });
  },

  loadCustomer: function(req, res, next) {
    if (!req.uriParams.uuid)
      return next();

    log.debug('LoadCustomer(%s) entered', req.uriParams.uuid);

    var opts = {
      scope: 'sub',
      filter: '(uuid=' + req.uriParams.uuid + ')'
    };
    return req.ldap.search('o=smartdc', opts, hidden, function(err, result) {
      if (err)
        return next(new restify.InternalError(err.message));

      result.on('searchEntry', function(entry) {
        req.customer = entry;
      });
      result.on('end', function() {
        log.debug('LoadCustomer(%s) -> %o', req.uriParams.uuid, req.customer);
        return next();
      });
    });
  },

  translateCustomer: _translate,

  forgotPasswordCode: _forgotPasswordCode

};
<commit_msg>CAPI-71 Update customer not accounting for 404s<commit_after>// Copyright 2011 Joyent, Inc.  All rights reserved.

var assert = require('assert');
var crypto = require('crypto');

var ldap = require('ldapjs');
var restify = require('restify');
var sprintf = require('sprintf').sprintf;
var uuid = require('node-uuid');

///--- Globals

var hidden = new ldap.Control({
  type: '1.3.6.1.4.1.38678.1',
  criticality: true
});
var log = restify.log;

var AES_KEY = uuid().replace('-').substring(0, 16);

///--- Helpers

function _randomId(min, max) {
  if (!min) min = 0;
  if (!max) max = Math.pow(2, 32) - 1;

  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function _merge(obj1, obj2) {
  Object.keys(obj2).forEach(function(k) {
    if (!obj1.hasOwnProperty(k))
      obj1[k] = obj2[k];
  });

  return obj1;
}

//
// http://www.youtube.com/watch?v=J7RsYvRSyXs
//
// In the ghetto
// On a cold and gray Chicago mornin'
// Another little baby child is born
// In the ghetto
// (In the ghetto)
// And his mama cries
// because if there's one thing that she don't need
// it's another little hungry mouth to feed
// In the ghetto
//
// Basically, this lets a password token last up to a day, statelessly, since
// the client doesn't call capi back for a token.  Asking for a token at 23:59?
// fuck off.
//
function _forgotPasswordCode(customerId) {
  var cipher = crypto.createCipher('aes-128-cbc', AES_KEY);
  var now = new Date();
  cipher.update('' + (now.getUTCDay() + 1));
  cipher.update('' + now.getUTCDate());
  cipher.update('' + (now.getUTCMonth() + 1));
  cipher.update('' + now.getUTCFullYear());
  cipher.update(customerId.replace('-', ''), 'utf8', 'hex');
  return cipher.final('hex');
}

function _translate(entry) {
  assert.ok(entry);

  var customer = {
    id: _randomId(),
    uuid: entry.uuid,
    customer_id: entry.uuid,
    customer_uuid: entry.uuid,
    login: entry.login,
    email_address: entry.email,
    first_name: entry.cn,
    last_name: entry.sn,
    company_name: entry.company || null
  };

  if (entry.address && entry.address.length) {
    if (!Array.isArray(entry.address))
      entry.address = [entry.address];
    for (var i = 0; i < entry.address.length; i++)
      customer['street_' + (i + 1)] = entry.address[i];
  }

  if (!customer.street_1)
    customer.street_1 = null;

  if (!customer.street_2)
    customer.street_2 = null;

  var dn = ldap.parseDN(entry.dn);
  if (dn.childOf('ou=operators, o=smartdc')) {
    customer.role_type = 2;
    customer.role = 2;
  }

  return _merge(customer, {
    city: entry.city || null,
    state: entry.state || null,
    postal_code: entry.postalcode || null,
    country: entry.country || null,
    phone_number: entry.phone || null,
    role_type: 1,
    role: 1,
    asset_id: null,
    legacy_id: null,
    deleted_at: null,
    alternate_email_address: null,
    forgot_password_code: _forgotPasswordCode(entry.uuid),
    activation_code: null,
    activated_at: entry._ctime,
    created_at: entry._ctime,
    updated_at: entry._mtime
  });
}

///--- Exports

module.exports = {

  loadCustomers: function loadCustomers(ldap, filter, translate, callback,
                                        base) {
    assert.ok(ldap);
    assert.ok(filter);
    assert.ok(translate !== undefined);

    if (typeof(translate) === 'function') {
      base = callback;
      callback = translate;
      translate = true;
    }

    if (!base)
      base = 'o=smartdc';

    var opts = {
      scope: 'sub',
      filter: filter
    };
    return ldap.search(base, opts, hidden, function(err, result) {
      if (err)
        return callback(new restify.InternalError(500, err.message));

      var entries = [];
      result.on('searchEntry', function(entry) {
        entries.push((translate ? _translate(entry.object) : entry.object));
      });
      result.on('end', function() {
        return callback(null, entries);
      });
    });
  },

  loadCustomer: function(req, res, next) {
    if (!req.uriParams.uuid)
      return next();

    log.debug('LoadCustomer(%s) entered', req.uriParams.uuid);
    var sent = false;
    function returnError(err) {
      if (!sent) {
        sent = true;
        return next(new restify.InternalError(err.message));
      }
    }
    var opts = {
      scope: 'sub',
      filter: '(uuid=' + req.uriParams.uuid + ')'
    };
    return req.ldap.search('o=smartdc', opts, hidden, function(err, result) {
      if (err)
        return returnError(err);

      result.on('searchEntry', function(entry) {
        req.customer = entry;
      });
      result.on('error', function(err) {
        return returnError(err);
      })
      result.on('end', function() {
        log.debug('LoadCustomer(%s) -> %o', req.uriParams.uuid, req.customer);
        if (!sent) {
          sent = true;
          if (!req.customer) {
            return next(new restify.ResourceNotFoundError(req.uriParams.uuid));
          }
          return next();
        }
      });
    });
  },

  translateCustomer: _translate,

  forgotPasswordCode: _forgotPasswordCode

};
<|endoftext|>


<commit_before>import React from "react";
import CX from "classnames";
import PropTypes from "prop-types";
import { map, sortBy } from "lodash-es";
import { Badge, ListGroup } from "react-bootstrap";
import { connect } from "react-redux";

import { byteSize } from "../../utils";
import { hideUploadOverlay } from "../actions";
import { Flex, FlexItem, ListGroupItem, ProgressBar } from "../../base";

const UploadItem = ({ localId, name, progress, size}) => (
    <ListGroupItem key={localId} disabled={progress === 0}>
        <ProgressBar bsStyle={progress === 100 ? "primary" : "success"} now={progress} affixed />
        <Flex>
            <FlexItem grow={1}>
                {name}
            </FlexItem>
            <FlexItem shrink={0} grow={0} pad={15}>
                {byteSize(size)}
            </FlexItem>
        </Flex>
    </ListGroupItem>
);

class UploadOverlay extends React.Component {

    componentWillReceiveProps(nextProps) {
        this.props.uploadsComplete
            ?   window.removeEventListener("beforeunload", this.handlePageLeave)
            :   window.addEventListener("beforeunload", this.handlePageLeave);
    }

    handlePageLeave (e) {
        const message = "Upload(s) still in progress";
        e.returnValue = message;
        return message;
    }

    render () {

        console.log(this.props.uploadsComplete);

        const classNames = CX("upload-overlay", {hidden: !this.props.showUploadOverlay});

        const uploadComponents = map(sortBy(this.props.uploads, "progress").reverse(), upload =>
            upload.progress === 100 ?
 : <UploadItem key={upload.localId} {...upload} />
        );

        let content = this.props.uploadsComplete
            ?   null
            :   (

                                    Uploads <Badge>{uploadComponents.length}</Badge>

                                <button type="button" className="close pullRight" onClick={this.props.onClose}>
                                    ×
                                </button>

                            <ListGroup style={{height: "auto", maxHeight: "175px", overflowX: "hidden"}}>
                                {uploadComponents}
                            </ListGroup>

                );

        return (

                {content}

        );
    }
}

UploadOverlay.propTypes = {
    uploads: PropTypes.arrayOf(PropTypes.object),
    showUploadOverlay: PropTypes.bool,
    uploadsComplete: PropTypes.bool,
    onClose: PropTypes.func
};

const mapStateToProps = (state) => ({...state.files});

const mapDispatchToProps = (dispatch) => ({

    onClose: () => {
        dispatch(hideUploadOverlay());
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(UploadOverlay);

export default Container;
<commit_msg>Remove console log<commit_after>import React from "react";
import CX from "classnames";
import PropTypes from "prop-types";
import { map, sortBy } from "lodash-es";
import { Badge, ListGroup } from "react-bootstrap";
import { connect } from "react-redux";

import { byteSize } from "../../utils";
import { hideUploadOverlay } from "../actions";
import { Flex, FlexItem, ListGroupItem, ProgressBar } from "../../base";

const UploadItem = ({ localId, name, progress, size}) => (
    <ListGroupItem key={localId} disabled={progress === 0}>
        <ProgressBar bsStyle={progress === 100 ? "primary" : "success"} now={progress} affixed />
        <Flex>
            <FlexItem grow={1}>
                {name}
            </FlexItem>
            <FlexItem shrink={0} grow={0} pad={15}>
                {byteSize(size)}
            </FlexItem>
        </Flex>
    </ListGroupItem>
);

class UploadOverlay extends React.Component {

    componentWillReceiveProps(nextProps) {
        this.props.uploadsComplete
            ?   window.removeEventListener("beforeunload", this.handlePageLeave)
            :   window.addEventListener("beforeunload", this.handlePageLeave);
    }

    handlePageLeave (e) {
        const message = "Upload(s) still in progress";
        e.returnValue = message;
        return message;
    }

    render () {

        const classNames = CX("upload-overlay", {hidden: !this.props.showUploadOverlay});

        const uploadComponents = map(sortBy(this.props.uploads, "progress").reverse(), upload =>
            upload.progress === 100 ?
 : <UploadItem key={upload.localId} {...upload} />
        );

        let content = this.props.uploadsComplete
            ?   null
            :   (

                                    Uploads <Badge>{uploadComponents.length}</Badge>

                                <button type="button" className="close pullRight" onClick={this.props.onClose}>
                                    ×
                                </button>

                            <ListGroup style={{height: "auto", maxHeight: "175px", overflowX: "hidden"}}>
                                {uploadComponents}
                            </ListGroup>

                );

        return (

                {content}

        );
    }
}

UploadOverlay.propTypes = {
    uploads: PropTypes.arrayOf(PropTypes.object),
    showUploadOverlay: PropTypes.bool,
    uploadsComplete: PropTypes.bool,
    onClose: PropTypes.func
};

const mapStateToProps = (state) => ({...state.files});

const mapDispatchToProps = (dispatch) => ({

    onClose: () => {
        dispatch(hideUploadOverlay());
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(UploadOverlay);

export default Container;
<|endoftext|>


<commit_before>/*
 AngularJS v1.2.16
 (c) 2010-2014 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(n,e,A){'use strict';function x(s,g,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,w){function y(){p&&(p.remove(),p=null);h&&(h.$destroy(),h=null);l&&(k.leave(l,function(){p=null}),p=l,l=null)}function v(){var b=s.current&&s.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),d=s.current;l=w(b,function(d){k.enter(d,null,l||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||g()});y()});h=d.scope=b;h.$emit("$viewContentLoaded");h.$eval(u)}else y()}
var h,l,p,t=b.autoscroll,u=b.onload||"";a.$on("$routeChangeSuccess",v);v()}}}function z(e,g,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var w=e(c.contents());b.controller&&(f.$scope=a,f=g(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));w(a)}}}n=e.module("ngRoute",["ng"]).provider("$route",function(){function s(a,c){return e.extend(new (e.extend(function(){},
{prototype:a})),c)}function g(a,e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},k=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;k.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&g(a,c));if(a){var b=
"/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";k[b]=e.extend({redirectTo:a},g(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,g,n,v,h){function l(){var d=p(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!u)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)u=!1,a.$broadcast("$routeChangeStart",
d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(t(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?g.get(d):g.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=h.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=
b,c=n.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function p(){var a,b;e.forEach(k,function(f,k){var q;if(q=!b){var g=c.path();q=f.keys;var l={};if(f.regexp)if(g=f.regexp.exec(g)){for(var h=1,p=g.length;h<p;++h){var n=q[h-1],r="string"==typeof g[h]?decodeURIComponent(g[h]):
g[h];n&&r&&(l[n.name]=r)}q=l}else q=null;else q=null;q=a=q}q&&(b=s(f,{params:e.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||k[null]&&s(k[null],{params:{},pathParams:{}})}function t(a,c){var b=[];e.forEach((a||"").split(":"),function(a,d){if(0===d)b.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];b.push(c[f]);b.push(e[2]||"");delete c[f]}});return b.join("")}var u=!1,r={routes:k,reload:function(){u=!0;a.$evalAsync(l)}};a.$on("$locationChangeSuccess",l);return r}]});n.provider("$routeParams",
function(){this.$get=function(){return{}}});n.directive("ngView",x);n.directive("ngView",z);x.$inject=["$route","$anchorScroll","$animate"];z.$inject=["$compile","$controller","$route"]})(window,window.angular);
//# sourceMappingURL=angular-route.min.js.map
<commit_msg>del min version<commit_after><|endoftext|>


<commit_before>var async  = require('async'),
    phantom = require('node-phantom');

module.exports = function(url, username, password, callback) {
  var ph, page;
  async.waterfall([
    function(cb) {
      phantom.create(cb);
    },
    function(_ph, cb) {
      ph = _ph;
      ph.createPage(cb);
    },
    function(_page, cb) {
      page = _page;
      page.open(url, cb);
    },
    function(status, cb) {
      setTimeout(function() {
        page.evaluate(function(username, password) {
          document.querySelector('#username').value = username;
          document.querySelector('#password').value = password;
          var e = document.createEvent('MouseEvents');
          e.initEvent("click", false, true);
          document.querySelector('button[name=Login]').dispatchEvent(e);
          return true;
        }, cb, username, password);
      }, 4000);
    },
    function(status, cb) {
      setTimeout(function() {
        page.evaluate(function() {
          if (location.href.indexOf("RemoteAccessAuthorizationPage.apexp") > 0) {
            var e = document.createEvent('MouseEvents');
            e.initEvent("click", false, true);
            document.querySelector('#oaapprove').dispatchEvent(e);
            return false;
          }
          return true;
        }, cb);
      }, 4000);
    },
    function(loaded, cb) {
      setTimeout(function() {
        page.evaluate(function() {
          var params = {};
          var m = document.querySelector('head script').innerText.match(/\/callback\?([^'"]+)/);
          if (m) {
            var qparams = m[1].split('&');
            for (var i=0; i<qparams.length; i++) {
              var qparam = qparams[i];
              var pair = qparam.split('=');
              params[pair[0]] = decodeURIComponent(pair[1]);
            }
          }
          return params;
        }, cb);
      }, loaded ? 0 : 4000);
    }
  ], function(err, params) {
    ph.exit();
    callback(err, params);
  });
};
<commit_msg>add wait for node-phantom ph initialization<commit_after>var async  = require('async'),
    phantom = require('node-phantom');

module.exports = function(url, username, password, callback) {
  var ph, page;
  async.waterfall([
    function(cb) {
      phantom.create(cb);
    },
    function(_ph, cb) {
      ph = _ph;
      setTimeout(function() {
        ph.createPage(cb);
      }, 100);
    },
    function(_page, cb) {
      page = _page;
      page.open(url, cb);
    },
    function(status, cb) {
      setTimeout(function() {
        page.evaluate(function(username, password) {
          document.querySelector('#username').value = username;
          document.querySelector('#password').value = password;
          var e = document.createEvent('MouseEvents');
          e.initEvent("click", false, true);
          document.querySelector('button[name=Login]').dispatchEvent(e);
          return true;
        }, cb, username, password);
      }, 4000);
    },
    function(status, cb) {
      setTimeout(function() {
        page.evaluate(function() {
          if (location.href.indexOf("RemoteAccessAuthorizationPage.apexp") > 0) {
            var e = document.createEvent('MouseEvents');
            e.initEvent("click", false, true);
            document.querySelector('#oaapprove').dispatchEvent(e);
            return false;
          }
          return true;
        }, cb);
      }, 4000);
    },
    function(loaded, cb) {
      setTimeout(function() {
        page.evaluate(function() {
          var params = {};
          var m = document.querySelector('head script').innerText.match(/\/callback\?([^'"]+)/);
          if (m) {
            var qparams = m[1].split('&');
            for (var i=0; i<qparams.length; i++) {
              var qparam = qparams[i];
              var pair = qparam.split('=');
              params[pair[0]] = decodeURIComponent(pair[1]);
            }
          }
          return params;
        }, cb);
      }, loaded ? 0 : 4000);
    }
  ], function(err, params) {
    ph.exit();
    callback(err, params);
  });
};
<|endoftext|>


<commit_before>/**
 * Joint abstract class.
 * A Joint represents a node in the hierarchy.
 */
define([
    'dejavu/AbstractClass',
    'events-emitter/EventsEmitter',
    'services/broadcaster',
    'mout/array/insert',
    'mout/array/remove',
    'has'
], function (AbstractClass, EventsEmitter, broadcaster, insert, remove, has) {

    'use strict';

    return AbstractClass.declare({
        $name: 'Joint',

        _uplinks: [],
        _downlinks: [],
        _emitter: null,
        _destroyed: false,

        /**
         * Constructor.
         */
        initialize: function () {
            this._emitter = new EventsEmitter();
        },

        /**
         * Adds a listener for an upcast or broadcast event.
         * Duplicate listeners for the same event will be discarded.
         *
         * @param {String}   event      The event name
         * @param {Function} fn         The handler
         * @param {Object}   [$context] The context to be used to call the handler, defaults to the conector instance
         *
         * @return {Object} The instance itself to allow chaining
         */
        on: function (event, fn, $context) {
            var context = $context || this;

            this._emitter.on(event, fn, context);
            this.$static._broadcaster.on(event, fn, context);

            return this;
        },

        /**
         * Removes a previously added listener.
         *
         * @param {String}   event      The event name
         * @param {Function} fn         The handler
         * @param {Object}   [$context] The context passed to the on() function
         *
         * @return {Object} The instance itself to allow chaining
         */
        off: function (event, fn, $context) {
            var context = $context || this;

            this._emitter.off(event, fn, context);
            this.$static._broadcaster.off(event, fn, context);

            return this;
        },

        /**
         * Destroys the instance, releasing all of its resources.
         * Note that all links to this joint will also be destroyed if no remaining links are found.
         */
        destroy: function () {
            if (!this._destroyed) {
                this._onDestroy();
                this._destroyed = true;
            }
        },

        ////////////////////////////////////////////////////////////

        /**
         * Creates a link between this joint and another one.
         *
         * @param {Joint} joint Another joint to link to this one
         *
         * @return {Joint} The joint passed in as the argument
         */
        _link: function (joint) {
            insert(joint._uplinks, this);
            insert(this._downlinks, joint);

            return joint;
        },

        /**
         * Removes a previously created link between a joint and another one.
         *
         * @param {Joint} joint Another joint to link to this one
         *
         * @return {Object} The instance itself to allow chaining
         */
        _unlink: function (joint) {
            remove(joint._uplinks, this);
            remove(this._downlinks, joint);

            return this;
        },

        /**
         * Fires an event upwards the chain.
         *
         * @param {String}   event   The event name
         * @param {...mixed} [$args] The arguments to pass along with the event
         *
         * @return {Object} The instance itself to allow chaining
         */
        _upcast: function (event, $args) {
            var x,
                length,
                curr;

            // Check if the event will be handled locally
            // Otherwise we will keep upcasting upwards the chain
            if (this._emitter.has(event)) {
                this._emitter.emit.apply(this._emitter, arguments);
            } else {
                length = this._uplinks.length;

                // If we got no uplinks, then warn that this event was unhandled
                if (length) {
                    for (x = 0; x < length; x += 1) {
                        curr = this._uplinks[x];

                        // If this uplink explicit listens for this event, fire the callbacks and stop the propagation
                        if (curr._emitter.has(event)) {
                            curr._emitter.emit.apply(curr._emitter, arguments);
                        // Otherwise keep upcasting
                        } else {
                            curr._upcast.apply(curr, arguments);
                        }
                    }
                } else if (has('debug')) {
                    console.warn('Unhandled upcast event "' + event + '".');
                }
            }

            return this;
        },

        /**
         * Fires an event to all the joints.
         *
         * @param {String}   event   The event name
         * @param {...mixed} [$args] The arguments to pass along with the event
         *
         * @return {Object} The instance itself to allow chaining
         */
        _broadcast: function (event, $args) {
            var broadcaster = this.$static._broadcaster;

            broadcaster.broadcast.apply(broadcaster, arguments);

            return this;
        },

        /**
         * Function called after calling destroy().
         * This function is ensured to only be called once.
         * Subclasses should override this method to release their resources.
         */
        _onDestroy: function () {
            var broadcaster = this.$static._broadcaster,
                x,
                curr;

            // Remove the listeners from the broadcaster
            this._emitter.forEach(broadcaster.off, broadcaster);

            // Clear the listeners
            this._emitter.off();

            // Foreach uplink, automatically unlink this instance
            for (x = this._uplinks.length - 1; x >= 0; x -= 1) {
                this._uplinks[x]._unlink(this);
            }

            // Foreach downlink, automatically unlink it and destroy it if no more references exist to it
            for (x = this._downlinks.length - 1; x >= 0; x -= 1) {
                curr = this._downlinks[x];
                this._unlink(curr);
                if (!curr._uplinks.length) {
                    curr.destroy();
                }
            }

            // Null references
            this._uplinks = this._downlinks = this._emitter = null;
        },

        ////////////////////////////////////////////////////////////

        $statics: {
            _broadcaster: broadcaster
        }
    });
});
<commit_msg>Emit event when joint is linked/unlinked.<commit_after>/**
 * Joint abstract class.
 * A Joint represents a node in the hierarchy.
 */
define([
    'dejavu/AbstractClass',
    'events-emitter/EventsEmitter',
    'services/broadcaster',
    'mout/array/insert',
    'mout/array/remove',
    'has'
], function (AbstractClass, EventsEmitter, broadcaster, insert, remove, has) {

    'use strict';

    return AbstractClass.declare({
        $name: 'Joint',

        _uplinks: [],
        _downlinks: [],
        _emitter: null,
        _destroyed: false,

        /**
         * Constructor.
         */
        initialize: function () {
            this._emitter = new EventsEmitter();
        },

        /**
         * Adds a listener for an upcast or broadcast event.
         * Duplicate listeners for the same event will be discarded.
         *
         * @param {String}   event      The event name
         * @param {Function} fn         The handler
         * @param {Object}   [$context] The context to be used to call the handler, defaults to the conector instance
         *
         * @return {Object} The instance itself to allow chaining
         */
        on: function (event, fn, $context) {
            var context = $context || this;

            this._emitter.on(event, fn, context);
            this.$static._broadcaster.on(event, fn, context);

            return this;
        },

        /**
         * Removes a previously added listener.
         *
         * @param {String}   event      The event name
         * @param {Function} fn         The handler
         * @param {Object}   [$context] The context passed to the on() function
         *
         * @return {Object} The instance itself to allow chaining
         */
        off: function (event, fn, $context) {
            var context = $context || this;

            this._emitter.off(event, fn, context);
            this.$static._broadcaster.off(event, fn, context);

            return this;
        },

        /**
         * Destroys the instance, releasing all of its resources.
         * Note that all links to this joint will also be destroyed if no remaining links are found.
         */
        destroy: function () {
            if (!this._destroyed) {
                this._onDestroy();
                this._destroyed = true;
            }
        },

        ////////////////////////////////////////////////////////////

        /**
         * Creates a link between this joint and another one.
         *
         * @param {Joint} joint Another joint to link to this one
         *
         * @return {Joint} The joint passed in as the argument
         */
        _link: function (joint) {
            insert(joint._uplinks, this);
            insert(this._downlinks, joint);
            joint._emitter.emit('link', this);

            return joint;
        },

        /**
         * Removes a previously created link between a joint and another one.
         *
         * @param {Joint} joint Another joint to link to this one
         *
         * @return {Object} The instance itself to allow chaining
         */
        _unlink: function (joint) {
            remove(joint._uplinks, this);
            remove(this._downlinks, joint);
            joint._emitter.emit('unlink', this);

            return this;
        },

        /**
         * Fires an event upwards the chain.
         *
         * @param {String}   event   The event name
         * @param {...mixed} [$args] The arguments to pass along with the event
         *
         * @return {Object} The instance itself to allow chaining
         */
        _upcast: function (event, $args) {
            var x,
                length,
                curr;

            // Check if the event will be handled locally
            // Otherwise we will keep upcasting upwards the chain
            if (this._emitter.has(event)) {
                this._emitter.emit.apply(this._emitter, arguments);
            } else {
                length = this._uplinks.length;

                // If we got no uplinks, then warn that this event was unhandled
                if (length) {
                    for (x = 0; x < length; x += 1) {
                        curr = this._uplinks[x];

                        // If this uplink explicit listens for this event, fire the callbacks and stop the propagation
                        if (curr._emitter.has(event)) {
                            curr._emitter.emit.apply(curr._emitter, arguments);
                        // Otherwise keep upcasting
                        } else {
                            curr._upcast.apply(curr, arguments);
                        }
                    }
                } else if (has('debug')) {
                    console.warn('Unhandled upcast event "' + event + '".');
                }
            }

            return this;
        },

        /**
         * Fires an event to all the joints.
         *
         * @param {String}   event   The event name
         * @param {...mixed} [$args] The arguments to pass along with the event
         *
         * @return {Object} The instance itself to allow chaining
         */
        _broadcast: function (event, $args) {
            var broadcaster = this.$static._broadcaster;

            broadcaster.broadcast.apply(broadcaster, arguments);

            return this;
        },

        /**
         * Function called after calling destroy().
         * This function is ensured to only be called once.
         * Subclasses should override this method to release their resources.
         */
        _onDestroy: function () {
            var broadcaster = this.$static._broadcaster,
                x,
                curr;

            // Remove the listeners from the broadcaster
            this._emitter.forEach(broadcaster.off, broadcaster);

            // Clear the listeners
            this._emitter.off();

            // Foreach uplink, automatically unlink this instance
            for (x = this._uplinks.length - 1; x >= 0; x -= 1) {
                this._uplinks[x]._unlink(this);
            }

            // Foreach downlink, automatically unlink it and destroy it if no more references exist to it
            for (x = this._downlinks.length - 1; x >= 0; x -= 1) {
                curr = this._downlinks[x];
                this._unlink(curr);
                if (!curr._uplinks.length) {
                    curr.destroy();
                }
            }

            // Null references
            this._uplinks = this._downlinks = this._emitter = null;
        },

        ////////////////////////////////////////////////////////////

        $statics: {
            _broadcaster: broadcaster
        }
    });
});
<|endoftext|>


<commit_before>/*
> electangular.js
> AngularJS Module for Atom Electron
> (c)2016 develephant @develephant
> license MIT
> version 0.0.1
*/
'use strict';

angular.module('electangular', [])

.run(['$rootScope', 'electron', function($rootScope, ele) {
  ele.ipcRenderer.on('electron-msg', (event, arg) => {
    $rootScope.$emit('electron-msg', arg);
  });
}])

.value("electron_core", require('electron'))

.service("ipc", ['electron_core', function(ele) {
  var ipcRenderer = ele.ipcRenderer;
  return {
    send: function(msg) {
      ipcRenderer.send('electron-msg', msg);
    },
    sendToHost: function(msg) {
      ipcRenderer.sendToHost('electron-msg', msg);
    }
  }
}])

.service("electron", ['$q', 'electron_core', function($q, core) {
  var remote = core.remote;
  return {
    Accelerator: remote.Accelerator,
    app: remote.app,
    autoUpdater: remote.autoUpdater,
    BrowserWindow: remote.BrowserWindow,
    contentTracing: remote.contentTracing, //TODO Promise
    dialog: {
      showErrorBox: remote.dialog.showErrorBox,
      showOpenDialog: function(bw, options) {
        if (!options) {
          options = bw;
          bw = remote.BrowserWindow.getFocusedWindow();
        }
        var deferred = $q.defer();
        remote.dialog.showOpenDialog(bw, options, (result) => {
          if (!result) {
            deferred.reject();
          } else {
            deferred.resolve(result);
          }
        })
        return deferred.promise;
      },
      showSaveDialog: function(bw, options) {
        if (!options) {
          options = bw;
          bw = remote.BrowserWindow.getFocusedWindow();
        }
        var deferred = $q.defer();
        remote.dialog.showSaveDialog(bw, options, (result) => {
          if (!result) {
            deferred.reject();
          } else {
            deferred.resolve(result);
          }
        });
        return deferred.promise;
      },
      showMessageBox: function(bw, options) {
        if (!options) {
          options = bw
          bw = remote.BrowserWindow.getFocusedWindow();
        }
        var deferred = $q.defer();
        remote.dialog.showMessageBox(bw, options, (result) => {
          if (!result) {
            deferred.reject();
          } else {
            deferred.resolve(result);
          }
        });
        return deferred.promise;
      }
    },
    globalShortcut: remote.globalShortcut,
    Menu: remote.Menu,
    MenuItem: remote.MenuItem,
    powerMonitor: remote.powerMonitor,
    powerSaveBlocker: remote.powerSaveBlocker,
    protocol: remote.protocol,
    session: remote.session,
    systemPreferences: remote.systemPreferences,
    Tray: remote.Tray,
    desktopCapturer: core.desktopCapturer,
    webFrame: core.webFrame,
    clipboard: core.clipboard,
    crashReporter: core.crashReporter,
    nativeImage: core.nativeImage,
    process: core.process,
    screen: core.screen,
    shell: core.shell
  }
}]);
<commit_msg>0.0.9<commit_after>/*
> electangular.js
> AngularJS Module for Atom Electron
> (c)2016 develephant @develephant
> license MIT
> version 0.0.2
*/
'use strict';

angular.module('electangular', [])

.run(['$rootScope', 'electron', function($rootScope, ele) {
  ele.ipcRenderer.on('electron-msg', (event, arg) => {
    $rootScope.$emit('electron-msg', arg);
  });
}])

.value("electron_core", require('electron'))

.service("ipc", ['electron_core', function(ele) {
  var ipcRenderer = ele.ipcRenderer;
  return {
    send: function(msg) {
      ipcRenderer.send('electron-msg', msg);
    },
    sendToHost: function(msg) {
      ipcRenderer.sendToHost('electron-msg', msg);
    }
  }
}])

.service("electron", ['$q', 'electron_core', function($q, core) {
  var remote = core.remote;
  return {
    Accelerator: remote.Accelerator,
    app: remote.app,
    autoUpdater: remote.autoUpdater,
    BrowserWindow: remote.BrowserWindow,
    contentTracing: remote.contentTracing, //TODO Promise
    dialog: {
      showErrorBox: remote.dialog.showErrorBox,
      showOpenDialog: function(bw, options) {
        if (!options) {
          options = bw;
          bw = remote.BrowserWindow.getFocusedWindow();
        }
        var deferred = $q.defer();
        remote.dialog.showOpenDialog(bw, options, (result) => {
          if (!result) {
            deferred.reject();
          } else {
            deferred.resolve(result);
          }
        })
        return deferred.promise;
      },
      showSaveDialog: function(bw, options) {
        if (!options) {
          options = bw;
          bw = remote.BrowserWindow.getFocusedWindow();
        }
        var deferred = $q.defer();
        remote.dialog.showSaveDialog(bw, options, (result) => {
          if (!result) {
            deferred.reject();
          } else {
            deferred.resolve(result);
          }
        });
        return deferred.promise;
      },
      showMessageBox: function(bw, options) {
        if (!options) {
          options = bw
          bw = remote.BrowserWindow.getFocusedWindow();
        }
        var deferred = $q.defer();
        remote.dialog.showMessageBox(bw, options, (result) => {
          if (!result) {
            deferred.reject();
          } else {
            deferred.resolve(result);
          }
        });
        return deferred.promise;
      }
    },
    globalShortcut: remote.globalShortcut,
    Menu: remote.Menu,
    MenuItem: remote.MenuItem,
    powerMonitor: remote.powerMonitor,
    powerSaveBlocker: remote.powerSaveBlocker,
    protocol: remote.protocol,
    session: remote.session,
    systemPreferences: remote.systemPreferences,
    Tray: remote.Tray,
    desktopCapturer: core.desktopCapturer,
    webFrame: core.webFrame,
    clipboard: core.clipboard,
    crashReporter: core.crashReporter,
    nativeImage: core.nativeImage,
    process: core.process,
    screen: core.screen,
    shell: core.shell,
    ipcRenderer: core.ipcRenderer
  }
}]);
<|endoftext|>


<commit_before>/**
 * Created by ken on 2017/5/15.
 */
import React from 'react'
import {inject, observer} from 'store/index'
import {Modal, Row, Col, Form, Button, Input, InputNumber, Radio} from 'antd'
const {create, Item} = Form
const formItemLayout = {
  labelCol: {span: 4},
  wrapperCol: {span: 18},
}

@create()
@observer
export default class extends React.Component {

  handleCancel() {
    this.props.store.changeState({modal: false})
    this.props.form.resetFields()
  }

  handleOk() {
    const {formitem,method} = this.props.store.state
    const {
      validateFieldsAndScroll
    } = this.props.form
    validateFieldsAndScroll((errors, values) => {
      if (errors) {
        return console.log('errors', errors)
      }
      if(method=='update')values._id = formitem._id
      this.props.store.postUser(values)
      this.props.form.resetFields()

    })
  }

  render() {
    const {state, enumRole} = this.props.store
    const {getFieldDecorator} = this.props.form
    const formitem = state.formitem

    return (
      <Modal
        visible={state.modal}
        onOk={this.handleOk.bind(this)}
        onCancel={this.handleCancel.bind(this)}
        confirmLoading={state.confirmLoading}
        maskClosable={false}
        title={state.modalTitle}>
        <Form layout="horizontal">
          <Item label="账号" {...formItemLayout} hasFeedback>
            {getFieldDecorator('passport', {
              rules: [
                {required: true, message: '账号必填!'}
              ],
              initialValue: formitem.passport
            })
            (<Input  />)}
          </Item>
          {(<Item label="密码" {...formItemLayout} hasFeedback>
            {getFieldDecorator('password', {
              rules: [
                {required: true, message: '密码必填!'},
              ],
              initialValue: formitem.password
            })
            (<Input type="password"/>)}
          </Item>)}
          <Item label="角色" {...formItemLayout} hasFeedback>
            {getFieldDecorator('role', {
              rules: [
                {required: true, message: '角色必填!'},
              ],
              initialValue: formitem.role.toString()
            })
            (<Radio.Group>
              {Object.keys(enumRole).map((key) => (<Radio.Button value={key}>{enumRole[key]}</Radio.Button>))}
            </Radio.Group>)}
          </Item>
        </Form>

      </Modal>
    )
  }
}
<commit_msg>平台登陆功能<commit_after>/**
 * Created by ken on 2017/5/15.
 */
import React from 'react'
import {inject, observer} from 'store/index'
import {Modal, Row, Col, Form, Button, Input, InputNumber, Radio} from 'antd'
const {create, Item} = Form
const formItemLayout = {
  labelCol: {span: 4},
  wrapperCol: {span: 18},
}

@create()
@observer
export default class extends React.Component {

  handleCancel() {
    this.props.store.changeState({modal: false})
    this.props.form.resetFields()
  }

  handleOk() {
    const {formitem,method} = this.props.store.state
    const {
      validateFieldsAndScroll
    } = this.props.form
    validateFieldsAndScroll((errors, values) => {
      if (errors) {
        return console.log('errors', errors)
      }
      if(method=='update')values._id = formitem._id
      this.props.store.postUser(values)
      this.props.form.resetFields()

    })
  }

  render() {
    const {state, enumRole} = this.props.store
    const {getFieldDecorator} = this.props.form
    const formitem = state.formitem

    return (
      <Modal
        visible={state.modal}
        onOk={this.handleOk.bind(this)}
        onCancel={this.handleCancel.bind(this)}
        confirmLoading={state.confirmLoading}
        maskClosable={false}
        title={state.modalTitle}>
        <Form layout="horizontal">
          <Item label="账号" {...formItemLayout} hasFeedback>
            {getFieldDecorator('passport', {
              rules: [
                {required: true, message: '账号必填!'}
              ],
              initialValue: formitem.passport
            })
            (<Input  />)}
          </Item>
          {(<Item label="密码" {...formItemLayout} hasFeedback>
            {getFieldDecorator('password', {
              rules: [
                {required: true, message: '密码必填!'},
              ],
              initialValue: formitem.password
            })
            (<Input type="password"/>)}
          </Item>)}
          <Item label="角色" {...formItemLayout} hasFeedback>
            {getFieldDecorator('role', {
              rules: [
                {required: true, message: '角色必填!'},
              ],
              initialValue: formitem.role && formitem.role.toString()
            })
            (<Radio.Group>
              {Object.keys(enumRole).map((key) => (<Radio.Button value={key}>{enumRole[key]}</Radio.Button>))}
            </Radio.Group>)}
          </Item>
        </Form>

      </Modal>
    )
  }
}
<|endoftext|>


<commit_before>/*
Copyright 2016 OpenMarket 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.
*/

import React from 'react';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';

const DEFAULT_ICON_URL = "img/network-matrix.svg";

export default class NetworkDropdown extends React.Component {
    constructor(props) {
        super(props);

        this.dropdownRootElement = null;
        this.ignoreEvent = null;

        this.onInputClick = this.onInputClick.bind(this);
        this.onRootClick = this.onRootClick.bind(this);
        this.onDocumentClick = this.onDocumentClick.bind(this);
        this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
        this.onMenuOptionClickProtocolInstance = this.onMenuOptionClickProtocolInstance.bind(this);
        this.onInputKeyUp = this.onInputKeyUp.bind(this);
        this.collectRoot = this.collectRoot.bind(this);
        this.collectInputTextBox = this.collectInputTextBox.bind(this);

        this.inputTextBox = null;

        const server = MatrixClientPeg.getHomeServerName();
        let defaultNetwork = null;
        if (
            this.props.config.serverConfig &&
            this.props.config.serverConfig[server] &&
            this.props.config.serverConfig[server].networks &&
            this.props.config.serverConfig[server].networks.indexOf('_matrix') > -1
        ) {
            defaultNetwork = '_matrix';
        }

        this.state = {
            expanded: false,
            selectedServer: server,
            selectedNetwork: defaultNetwork,
        };
    }

    componentWillMount() {
        // Listen for all clicks on the document so we can close the
        // menu when the user clicks somewhere else
        document.addEventListener('click', this.onDocumentClick, false);

        // fire this now so the defaults can be set up
        this.props.onOptionChange(this.state.selectedServer, this.state.selectedNetwork);
    }

    componentWillUnmount() {
        document.removeEventListener('click', this.onDocumentClick, false);
    }

    componentDidUpdate() {
        if (this.state.expanded && this.inputTextBox) {
            this.inputTextBox.focus();
        }
    }

    onDocumentClick(ev) {
        // Close the dropdown if the user clicks anywhere that isn't
        // within our root element
        if (ev !== this.ignoreEvent) {
            this.setState({
                expanded: false,
            });
        }
    }

    onRootClick(ev) {
        // This captures any clicks that happen within our elements,
        // such that we can then ignore them when they're seen by the
        // click listener on the document handler, ie. not close the
        // dropdown immediately after opening it.
        // NB. We can't just stopPropagation() because then the event
        // doesn't reach the React onClick().
        this.ignoreEvent = ev;
    }

    onInputClick(ev) {
        this.setState({
            expanded: !this.state.expanded,
        });
        ev.preventDefault();
    }

    onMenuOptionClick(server, network) {
        this.setState({
            expanded: false,
            selectedServer: server,
            selectedNetwork: network,
            selectedInstanceId: null,
        });
        this.props.onOptionChange(server, network);
    }

    onMenuOptionClickProtocolInstance(server, instance_id) {
        this.setState({
            expanded: false,
            selectedServer: server,
            selectedNetwork: null,
            selectedInstanceId: instance_id,
        });
        this.props.onOptionChange(server, null, instance_id);
    }

    onInputKeyUp(e) {
        if (e.key == 'Enter') {
            this.setState({
                expanded: false,
                selectedServer: e.target.value,
                selectedNetwork: null,
            });
            this.props.onOptionChange(e.target.value, null);
        }
    }

    collectRoot(e) {
        if (this.dropdownRootElement) {
            this.dropdownRootElement.removeEventListener('click', this.onRootClick, false);
        }
        if (e) {
            e.addEventListener('click', this.onRootClick, false);
        }
        this.dropdownRootElement = e;
    }

    collectInputTextBox(e) {
        this.inputTextBox = e;
    }

    _getMenuOptions() {
        const options = [];

        let servers = [];
        if (this.props.config.servers) {
            servers = servers.concat(this.props.config.servers);
        }

        if (servers.indexOf(MatrixClientPeg.getHomeServerName()) == -1) {
            servers.unshift(MatrixClientPeg.getHomeServerName());
        }

        // if the thirdparty/protocols entries have instance_ids,
        // we can get the local server listings from here. If not,
        // the server is too old.
        let use_protocols = true;
        for (const proto of Object.keys(this.props.protocols)) {
            if (!this.props.protocols[proto].instances) continue;
            for (const instance of this.props.protocols[proto].instances) {
                if (!instance.instance_id) use_protocols = false;
            }
        }

        // For our own HS, we can use the instance_ids given in the third party protocols
        // response to get the server to filter the room list by network for us (if the
        // server is new enough), although for now we prefer the config if it exists.
        // For remote HSes, we use the data from the config.
        for (const server of servers) {
            options.push(this._makeMenuOption(server, null));
            if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
                for (const network of this.props.config.serverConfig[server].networks) {
                    options.push(this._makeMenuOption(server, network));
                }
            } else if (server == MatrixClientPeg.getHomeServerName() && use_protocols) {
                options.push(this._makeMenuOption(server, '_matrix'));
                for (const proto of Object.keys(this.props.protocols)) {
                    if (!this.props.protocols[proto].instances) continue;
                    for (const instance of this.props.protocols[proto].instances) {
                        options.push(this._makeMenuOptionFromProtocolInstance(server, this.props.protocols[proto], instance));
                    }
                }
            }
        }

        return options;
    }

    _makeMenuOptionFromProtocolInstance(server, protocol, instance, handleClicks) {
        if (handleClicks === undefined) handleClicks = true;

        const name = instance.desc;
        const icon = ;
        const key = instance.instance_id;
        const click_handler = handleClicks ? this.onMenuOptionClickProtocolInstance.bind(this, server, instance.instance_id) : null;

        return

            {icon}
            {name}

;
    }

    _makeMenuOption(server, network, handleClicks) {
        if (handleClicks === undefined) wire_onclick = true;
        let icon;
        let name;
        let span_class;

        if (network === null) {
            name = server;
            span_class = 'mx_NetworkDropdown_menu_all';
        } else if (network == '_matrix') {
            name = 'Matrix';
            icon = ;
            span_class = 'mx_NetworkDropdown_menu_network';
        } else {
            if (this.props.config.networks[network] === undefined) {
                throw new Error(network + ' network missing from config');
            }
            if (this.props.config.networks[network].name) {
                name = this.props.config.networks[network].name;
            } else {
                name = network;
            }
            if (this.props.config.networks[network].icon) {
                // omit height here so if people define a non-square logo in the config, it
                // will keep the aspect when it scales
                icon = ;
            } else {
                icon = ;
            }

            span_class = 'mx_NetworkDropdown_menu_network';
        }

        const click_handler = handleClicks ? this.onMenuOptionClick.bind(this, server, network) : null;

        let key = server;
        if (network !== null) {
            key += '_' + network;
        }

        return

            {icon}
            {name}

;
    }

    _protocolNameForInstanceId(instance_id) {
        for (const proto of Object.keys(this.props.protocols)) {
            if (!this.props.protocols[proto].instances) continue;
            for (const instance of this.props.protocols[proto].instances) {
                if (instance.instance_id == instance_id) return proto;
            }
        }
    }

    instanceForInstanceId(instance_id) {
        for (const proto of Object.keys(this.props.protocols)) {
            if (!this.props.protocols[proto].instances) continue;
            for (const instance of this.props.protocols[proto].instances) {
                if (instance.instance_id == instance_id) return instance;
            }
        }
    }

    render() {
        let current_value;

        let menu;
        if (this.state.expanded) {
            const menu_options = this._getMenuOptions();
            menu =

                {menu_options}

;
            current_value = <input type="text" className="mx_NetworkDropdown_networkoption"
                ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
                placeholder="matrix.org" // 'matrix.org' as an example of an HS name
            />
        } else {
            if (this.state.selectedInstanceId) {
                const protocolName = this._protocolNameForInstanceId(this.state.selectedInstanceId);
                const instance = this.instanceForInstanceId(this.state.selectedInstanceId);
                current_value = this._makeMenuOptionFromProtocolInstance(
                    this.state.selectedServer, this.props.protocols[protocolName], instance, false
                );
            } else {
                current_value = this._makeMenuOption(
                    this.state.selectedServer, this.state.selectedNetwork, false
                );
            }
        }

        return

                {current_value}

                {menu}

;
    }
}

NetworkDropdown.propTypes = {
    onOptionChange: React.PropTypes.func.isRequired,
    config: React.PropTypes.object,
    protocols: React.PropTypes.object,
};

NetworkDropdown.defaultProps = {
    config: {
        networks: [],
    },
    protocols: {},
};

<commit_msg>Missed a wire_onclick<commit_after>/*
Copyright 2016 OpenMarket 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.
*/

import React from 'react';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';

const DEFAULT_ICON_URL = "img/network-matrix.svg";

export default class NetworkDropdown extends React.Component {
    constructor(props) {
        super(props);

        this.dropdownRootElement = null;
        this.ignoreEvent = null;

        this.onInputClick = this.onInputClick.bind(this);
        this.onRootClick = this.onRootClick.bind(this);
        this.onDocumentClick = this.onDocumentClick.bind(this);
        this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
        this.onMenuOptionClickProtocolInstance = this.onMenuOptionClickProtocolInstance.bind(this);
        this.onInputKeyUp = this.onInputKeyUp.bind(this);
        this.collectRoot = this.collectRoot.bind(this);
        this.collectInputTextBox = this.collectInputTextBox.bind(this);

        this.inputTextBox = null;

        const server = MatrixClientPeg.getHomeServerName();
        let defaultNetwork = null;
        if (
            this.props.config.serverConfig &&
            this.props.config.serverConfig[server] &&
            this.props.config.serverConfig[server].networks &&
            this.props.config.serverConfig[server].networks.indexOf('_matrix') > -1
        ) {
            defaultNetwork = '_matrix';
        }

        this.state = {
            expanded: false,
            selectedServer: server,
            selectedNetwork: defaultNetwork,
        };
    }

    componentWillMount() {
        // Listen for all clicks on the document so we can close the
        // menu when the user clicks somewhere else
        document.addEventListener('click', this.onDocumentClick, false);

        // fire this now so the defaults can be set up
        this.props.onOptionChange(this.state.selectedServer, this.state.selectedNetwork);
    }

    componentWillUnmount() {
        document.removeEventListener('click', this.onDocumentClick, false);
    }

    componentDidUpdate() {
        if (this.state.expanded && this.inputTextBox) {
            this.inputTextBox.focus();
        }
    }

    onDocumentClick(ev) {
        // Close the dropdown if the user clicks anywhere that isn't
        // within our root element
        if (ev !== this.ignoreEvent) {
            this.setState({
                expanded: false,
            });
        }
    }

    onRootClick(ev) {
        // This captures any clicks that happen within our elements,
        // such that we can then ignore them when they're seen by the
        // click listener on the document handler, ie. not close the
        // dropdown immediately after opening it.
        // NB. We can't just stopPropagation() because then the event
        // doesn't reach the React onClick().
        this.ignoreEvent = ev;
    }

    onInputClick(ev) {
        this.setState({
            expanded: !this.state.expanded,
        });
        ev.preventDefault();
    }

    onMenuOptionClick(server, network) {
        this.setState({
            expanded: false,
            selectedServer: server,
            selectedNetwork: network,
            selectedInstanceId: null,
        });
        this.props.onOptionChange(server, network);
    }

    onMenuOptionClickProtocolInstance(server, instance_id) {
        this.setState({
            expanded: false,
            selectedServer: server,
            selectedNetwork: null,
            selectedInstanceId: instance_id,
        });
        this.props.onOptionChange(server, null, instance_id);
    }

    onInputKeyUp(e) {
        if (e.key == 'Enter') {
            this.setState({
                expanded: false,
                selectedServer: e.target.value,
                selectedNetwork: null,
            });
            this.props.onOptionChange(e.target.value, null);
        }
    }

    collectRoot(e) {
        if (this.dropdownRootElement) {
            this.dropdownRootElement.removeEventListener('click', this.onRootClick, false);
        }
        if (e) {
            e.addEventListener('click', this.onRootClick, false);
        }
        this.dropdownRootElement = e;
    }

    collectInputTextBox(e) {
        this.inputTextBox = e;
    }

    _getMenuOptions() {
        const options = [];

        let servers = [];
        if (this.props.config.servers) {
            servers = servers.concat(this.props.config.servers);
        }

        if (servers.indexOf(MatrixClientPeg.getHomeServerName()) == -1) {
            servers.unshift(MatrixClientPeg.getHomeServerName());
        }

        // if the thirdparty/protocols entries have instance_ids,
        // we can get the local server listings from here. If not,
        // the server is too old.
        let use_protocols = true;
        for (const proto of Object.keys(this.props.protocols)) {
            if (!this.props.protocols[proto].instances) continue;
            for (const instance of this.props.protocols[proto].instances) {
                if (!instance.instance_id) use_protocols = false;
            }
        }

        // For our own HS, we can use the instance_ids given in the third party protocols
        // response to get the server to filter the room list by network for us (if the
        // server is new enough), although for now we prefer the config if it exists.
        // For remote HSes, we use the data from the config.
        for (const server of servers) {
            options.push(this._makeMenuOption(server, null));
            if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
                for (const network of this.props.config.serverConfig[server].networks) {
                    options.push(this._makeMenuOption(server, network));
                }
            } else if (server == MatrixClientPeg.getHomeServerName() && use_protocols) {
                options.push(this._makeMenuOption(server, '_matrix'));
                for (const proto of Object.keys(this.props.protocols)) {
                    if (!this.props.protocols[proto].instances) continue;
                    for (const instance of this.props.protocols[proto].instances) {
                        options.push(this._makeMenuOptionFromProtocolInstance(server, this.props.protocols[proto], instance));
                    }
                }
            }
        }

        return options;
    }

    _makeMenuOptionFromProtocolInstance(server, protocol, instance, handleClicks) {
        if (handleClicks === undefined) handleClicks = true;

        const name = instance.desc;
        const icon = ;
        const key = instance.instance_id;
        const click_handler = handleClicks ? this.onMenuOptionClickProtocolInstance.bind(this, server, instance.instance_id) : null;

        return

            {icon}
            {name}

;
    }

    _makeMenuOption(server, network, handleClicks) {
        if (handleClicks === undefined) handleClicks = true;
        let icon;
        let name;
        let span_class;

        if (network === null) {
            name = server;
            span_class = 'mx_NetworkDropdown_menu_all';
        } else if (network == '_matrix') {
            name = 'Matrix';
            icon = ;
            span_class = 'mx_NetworkDropdown_menu_network';
        } else {
            if (this.props.config.networks[network] === undefined) {
                throw new Error(network + ' network missing from config');
            }
            if (this.props.config.networks[network].name) {
                name = this.props.config.networks[network].name;
            } else {
                name = network;
            }
            if (this.props.config.networks[network].icon) {
                // omit height here so if people define a non-square logo in the config, it
                // will keep the aspect when it scales
                icon = ;
            } else {
                icon = ;
            }

            span_class = 'mx_NetworkDropdown_menu_network';
        }

        const click_handler = handleClicks ? this.onMenuOptionClick.bind(this, server, network) : null;

        let key = server;
        if (network !== null) {
            key += '_' + network;
        }

        return

            {icon}
            {name}

;
    }

    _protocolNameForInstanceId(instance_id) {
        for (const proto of Object.keys(this.props.protocols)) {
            if (!this.props.protocols[proto].instances) continue;
            for (const instance of this.props.protocols[proto].instances) {
                if (instance.instance_id == instance_id) return proto;
            }
        }
    }

    instanceForInstanceId(instance_id) {
        for (const proto of Object.keys(this.props.protocols)) {
            if (!this.props.protocols[proto].instances) continue;
            for (const instance of this.props.protocols[proto].instances) {
                if (instance.instance_id == instance_id) return instance;
            }
        }
    }

    render() {
        let current_value;

        let menu;
        if (this.state.expanded) {
            const menu_options = this._getMenuOptions();
            menu =

                {menu_options}

;
            current_value = <input type="text" className="mx_NetworkDropdown_networkoption"
                ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
                placeholder="matrix.org" // 'matrix.org' as an example of an HS name
            />
        } else {
            if (this.state.selectedInstanceId) {
                const protocolName = this._protocolNameForInstanceId(this.state.selectedInstanceId);
                const instance = this.instanceForInstanceId(this.state.selectedInstanceId);
                current_value = this._makeMenuOptionFromProtocolInstance(
                    this.state.selectedServer, this.props.protocols[protocolName], instance, false
                );
            } else {
                current_value = this._makeMenuOption(
                    this.state.selectedServer, this.state.selectedNetwork, false
                );
            }
        }

        return

                {current_value}

                {menu}

;
    }
}

NetworkDropdown.propTypes = {
    onOptionChange: React.PropTypes.func.isRequired,
    config: React.PropTypes.object,
    protocols: React.PropTypes.object,
};

NetworkDropdown.defaultProps = {
    config: {
        networks: [],
    },
    protocols: {},
};

<|endoftext|>