<commit_before>module.exports = {
  appToDist: {
    files:[{
      expand: true,
      cwd: 'src/app/',
      src: ['**'],
      dest: 'dist/emp3-map'
    }, {
      expand: true,
      cwd: 'dist/emp3/',
      src: ['**'],
      dest: 'dist/emp3-map/emp3/'
    }]
  },
  urlProxyToEMP: {
    expand: true,
    cwd: 'src/app/',
    src: ['urlproxy.jsp'],
    dest: 'dist/emp3'
  },
  leafletSrc: {
    expand: true,
    cwd: 'src/mapengine/leaflet/',
    src: ['**'],
    dest: 'dist/emp3/emp3-leaflet'
  },
  cesiumSrc: {
    expand: true,
    cwd: 'src/mapengine/cesium/',
    src: ['**'],
    dest: 'dist/emp3/emp3-cesium'
  },
  worldwindRequired: {
    expand: true,
    cwd: 'src/mapengine/worldwind/',
    src: ['manifest.js', 'emp3-worldwind.min.js', 'emp3-worldwind.min.js.map', 'worldwindlib.js', 'images/**'],
    dest: 'dist/emp3/emp3-worldwind'
  },
  min: {
    expand: true,
    cwd: 'dist/emp3/',
    src: ['**'],
    dest: 'dist/emp3-map/'
  },
  vendorFilesToUnitTests: {
    expand: true,
    cwd: 'src/app/vendor/',
    src: ['mil-sym/**'],
    dest: 'test/vendor/'
  },
  vendorFilesToValidation: {
    files: [{
      expand: true,
      cwd: 'src/app/vendor',
      src: ['mil-sym/**', 'jquery*'],
      dest: 'src/validation/vendor/'
    }, {
      expand: true,
      cwd: 'src/app/vendor',
      src: ['mil-sym/**', 'jquery*'],
      dest: 'dist/validation/vendor/'
    }]
  },
  cesiumV2: {
    expand: true,
    cwd: 'dist/',
    src: 'emp3-cesium.war',
    rename: function() {
      return 'dist/emp-engine-cesium.war';
    }
  },
  validationToDist: {
    files: [{
      expand: true,
      cwd: 'src/validation',
      src: ['config.json', 'images/**', 'resources/**'],
      dest: 'dist/validation/'
    }]
  },
  devguide: {
    files: [{
      expand: true,
      cwd: 'devguide/',
      src: ['**'],
      dest: 'dist/devguide'
    }, {
      expand: true,
      cwd: 'dist/emp3/',
      src: ['**'],
      dest: 'dist/devguide/emp3/'
    }, {
      expand: true,
      cwd: 'dist/docs/',
      src: ['**'],
      dest: 'dist/devguide/docs'
    }]
  },
  licenses: {
    files: [{
      expand: true,
      src: ['LICENSE', 'LICENSE-3RD-PARTY'],
      dest: 'dist/emp3'
    }]
  },
  emp3ToValidation: {
    expand: true,
    cwd: 'dist/',
    src: ['emp3/**'],
    dest: 'dist/validation/'
  }
};
<commit_msg>-- Removed the test folder from the distribution. Removed from the dist folder the IAU2006_XYS, maki, and NaturalEarthII folders that were inside the sdk. Size was reduced by 2.4 MB.<commit_after>module.exports = {
  appToDist: {
    files:[{
      expand: true,
      cwd: 'src/app/',
      src: ['**'],
      dest: 'dist/emp3-map'
    }, {
      expand: true,
      cwd: 'dist/emp3/',
      src: ['**'],
      dest: 'dist/emp3-map/emp3/'
    }]
  },
  urlProxyToEMP: {
    expand: true,
    cwd: 'src/app/',
    src: ['urlproxy.jsp'],
    dest: 'dist/emp3'
  },
  leafletSrc: {
    expand: true,
    cwd: 'src/mapengine/leaflet/',
    src: ['**'],
    dest: 'dist/emp3/emp3-leaflet'
  },
  cesiumSrc: {
    expand: true,
    cwd: 'src/mapengine/cesium/',
    src: ['**'],
    src: ['manifest.js', 'emp3-cesium.min.js', 'emp3-cesium.min.js.map','emp3-cesium.min.css', 'emp3-cesium.min.css.map', 'js/**', '!**js/lib/cesium/Assets/Textures/maki/**', '!**js/lib/cesium/Assets/Textures/NaturalEarthII/**', '!**js/lib/cesium/Assets/IAU2006_XYS/**' ,'!**/test/**'],
    dest: 'dist/emp3/emp3-cesium'
  },
  worldwindRequired: {
    expand: true,
    cwd: 'src/mapengine/worldwind/',
    src: ['manifest.js', 'emp3-worldwind.min.js', 'emp3-worldwind.min.js.map', 'worldwindlib.js', 'images/**'],
    dest: 'dist/emp3/emp3-worldwind'
  },
  min: {
    expand: true,
    cwd: 'dist/emp3/',
    src: ['**'],
    dest: 'dist/emp3-map/'
  },
  vendorFilesToUnitTests: {
    expand: true,
    cwd: 'src/app/vendor/',
    src: ['mil-sym/**'],
    dest: 'test/vendor/'
  },
  vendorFilesToValidation: {
    files: [{
      expand: true,
      cwd: 'src/app/vendor',
      src: ['mil-sym/**', 'jquery*'],
      dest: 'src/validation/vendor/'
    }, {
      expand: true,
      cwd: 'src/app/vendor',
      src: ['mil-sym/**', 'jquery*'],
      dest: 'dist/validation/vendor/'
    }]
  },
  cesiumV2: {
    expand: true,
    cwd: 'dist/',
    src: 'emp3-cesium.war',
    rename: function() {
      return 'dist/emp-engine-cesium.war';
    }
  },
  validationToDist: {
    files: [{
      expand: true,
      cwd: 'src/validation',
      src: ['config.json', 'images/**', 'resources/**'],
      dest: 'dist/validation/'
    }]
  },
  devguide: {
    files: [{
      expand: true,
      cwd: 'devguide/',
      src: ['**'],
      dest: 'dist/devguide'
    }, {
      expand: true,
      cwd: 'dist/emp3/',
      src: ['**'],
      dest: 'dist/devguide/emp3/'
    }, {
      expand: true,
      cwd: 'dist/docs/',
      src: ['**'],
      dest: 'dist/devguide/docs'
    }]
  },
  licenses: {
    files: [{
      expand: true,
      src: ['LICENSE', 'LICENSE-3RD-PARTY'],
      dest: 'dist/emp3'
    }]
  },
  emp3ToValidation: {
    expand: true,
    cwd: 'dist/',
    src: ['emp3/**'],
    dest: 'dist/validation/'
  }
};
<|endoftext|>


<commit_before>module.exports = {
    angular: {
        files: [{
            expand: true,
            src: "**",
            cwd: 'bower_components/bootstrap/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular/',
            dest: "angular/bower_components/videogular"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/jquery.sparkline/dist/',
            dest: "angular/bower_components/jquery.sparkline/dist"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/angularjs-toaster/',
            dest: "angular/bower_components/angularjs-toaster"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/footable/dist/',
            dest: "angular/bower_components/footable/dist/"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-buffering/',
            dest: "angular/bower_components/videogular-buffering"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/screenfull/',
            dest: "angular/bower_components/screenfull"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-controls/',
            dest: "angular/bower_components/videogular-controls"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-poster/',
            dest: "angular/bower_components/videogular-poster"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-overlay-play/',
            dest: "angular/bower_components/videogular-overlay-play"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/font-awesome/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/jquery.sparkline/dist',
            dest: "angular/bower_components/jquery.sparkline/dist"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/simple-line-icons/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/l10n',
            dest: "angular/l10n"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/img',
            dest: "angular/img"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/js',
            dest: "angular/js"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/tpl',
            dest: "angular/tpl"
        }, {
            src: 'src/index.min.html',
            dest: 'angular/index.html'
        }]
    },
    html: {
        files: [{
            expand: true,
            src: "**",
            cwd: 'bower_components/bootstrap/fonts',
            dest: "html/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/font-awesome/fonts',
            dest: "html/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/Simple-Line-Icons/fonts',
            dest: "html/fonts"
        }, {
            expand: true,
            src: '**',
            cwd: 'src/fonts/',
            dest: 'html/fonts/'
        }, {
            expand: true,
            src: "**",
            cwd: 'src/api',
            dest: "html/api"
        }, {
            expand: true,
            src: '**',
            cwd: 'src/img/',
            dest: 'html/img/'
        }, {
            expand: true,
            src: '*.css',
            cwd: 'src/css/',
            dest: 'html/css/'
        }, {
            expand: true,
            src: '**',
            cwd: 'swig/js/',
            dest: 'html/js/'
        }]
    },
    landing: {
        files: [{
            expand: true,
            src: "**",
            cwd: 'bower_components/bootstrap/fonts',
            dest: "landing/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/font-awesome/fonts',
            dest: "landing/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/simple-line-icons/fonts',
            dest: "landing/fonts"
        }, {
            expand: true,
            src: '**',
            cwd: 'src/fonts/',
            dest: 'landing/fonts/'
        }, {
            expand: true,
            src: '*.css',
            cwd: 'src/css/',
            dest: 'landing/css/'
        }, {
            src: 'html/css/app.min.css',
            dest: 'landing/css/app.min.css'
        }]
    }

};<commit_msg>copy all bower components! bang<commit_after>module.exports = {
    angular: {
        files: [{
            expand: true,
            src: "**",
            cwd: 'bower_components/bootstrap/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular/',
            dest: "angular/bower_components/videogular"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/jquery.sparkline/dist/',
            dest: "angular/bower_components/jquery.sparkline/dist"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/angularjs-toaster/',
            dest: "angular/bower_components/angularjs-toaster"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/',
            dest: "angular/bower_components"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-buffering/',
            dest: "angular/bower_components/videogular-buffering"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/screenfull/',
            dest: "angular/bower_components/screenfull"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-controls/',
            dest: "angular/bower_components/videogular-controls"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-poster/',
            dest: "angular/bower_components/videogular-poster"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/videogular-overlay-play/',
            dest: "angular/bower_components/videogular-overlay-play"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/font-awesome/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/jquery.sparkline/dist',
            dest: "angular/bower_components/jquery.sparkline/dist"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/simple-line-icons/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/fonts',
            dest: "angular/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/l10n',
            dest: "angular/l10n"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/img',
            dest: "angular/img"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/js',
            dest: "angular/js"
        }, {
            expand: true,
            src: "**",
            cwd: 'src/tpl',
            dest: "angular/tpl"
        }, {
            src: 'src/index.min.html',
            dest: 'angular/index.html'
        }]
    },
    html: {
        files: [{
            expand: true,
            src: "**",
            cwd: 'bower_components/bootstrap/fonts',
            dest: "html/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/font-awesome/fonts',
            dest: "html/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/Simple-Line-Icons/fonts',
            dest: "html/fonts"
        }, {
            expand: true,
            src: '**',
            cwd: 'src/fonts/',
            dest: 'html/fonts/'
        }, {
            expand: true,
            src: "**",
            cwd: 'src/api',
            dest: "html/api"
        }, {
            expand: true,
            src: '**',
            cwd: 'src/img/',
            dest: 'html/img/'
        }, {
            expand: true,
            src: '*.css',
            cwd: 'src/css/',
            dest: 'html/css/'
        }, {
            expand: true,
            src: '**',
            cwd: 'swig/js/',
            dest: 'html/js/'
        }]
    },
    landing: {
        files: [{
            expand: true,
            src: "**",
            cwd: 'bower_components/bootstrap/fonts',
            dest: "landing/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/font-awesome/fonts',
            dest: "landing/fonts"
        }, {
            expand: true,
            src: "**",
            cwd: 'bower_components/simple-line-icons/fonts',
            dest: "landing/fonts"
        }, {
            expand: true,
            src: '**',
            cwd: 'src/fonts/',
            dest: 'landing/fonts/'
        }, {
            expand: true,
            src: '*.css',
            cwd: 'src/css/',
            dest: 'landing/css/'
        }, {
            src: 'html/css/app.min.css',
            dest: 'landing/css/app.min.css'
        }]
    }

};<|endoftext|>


<commit_before>// COPY
// Copies remaining files to places other tasks can use
module.exports = function(grunt) {

    'use strict';

    // Read manifest files from plugins and copies assets to destination (it existing)
    grunt.registerTask('copy:plugins', function (dest) {
        var settings = grunt.config.get('settings');
        var dir = '.tmp';
        if(dest === 'dist') {
            dir = grunt.config.get('goteo').dist;
        }

        for(var plugin in settings.plugins) {
            if(settings.plugins[plugin].active && grunt.file.exists('extend/' + plugin + '/manifest.yml')) {
                grunt.file.setBase('extend/' + plugin);
                var manifest = grunt.file.readYAML('manifest.yml');
                if(manifest.assets) {
                    for(var origin in manifest.assets) {
                        var destination = '../../' + dir + '/' + manifest.assets[origin];
                        if(!grunt.file.exists(origin)) {
                            grunt.fail.warn('Plugin asset [extend/' + plugin + '/' + origin + '] not found');
                        }
                        if(grunt.file.isFile(origin)) {
                            grunt.verbose.writeln('Found plugin [' + plugin + '] with asset [' + origin + '] , copying to [' + destination + ']');
                            grunt.file.copy(origin, destination);
                        }
                        else {
                            var files = grunt.file.expandMapping('**/*', destination, {cwd: origin});
                            for(var i in files) {
                                var o = files[i].src;
                                var d = files[i].dest;
                                // console.log('COPY',o,'TO',d);
                                if(grunt.file.isFile(o.toString())) {
                                    grunt.verbose.writeln('Found plugin [' + plugin + '] with asset [' + o + '] , copying to [' + d + ']');
                                    grunt.file.copy(o.toString(), d);
                                }
                            }
                        }
                    }
                }
                grunt.file.setBase('../../');
            }
        }
    });

    grunt.config('copy', {
        devel: {
            expand: true,
            dot: true,
            cwd: '<%= goteo.app %>',
            dest: '.tmp',
            // CSS is copied by SASS plugin
            src: [ '*', 'assets/js/**/*', 'assets/vendor/**/*', 'assets/img/**/*', 'templates/**/*', 'view/**/*' ]

        },

        dist: {
            expand: true,
            dot: true,
            cwd: '<%= goteo.app %>',
            dest: '<%= goteo.dist %>',
            src: [ '*', 'assets/js/*/*', 'assets/vendor/**/*', 'assets/img/**/*', 'templates/**/*', 'view/**/*' ]
        },

        fonts: {
            files: [{
                expand: true,
                flatten: true,
                dot: true,
                cwd: '<%= goteo.app %>/assets/vendor/',
                dest: '<%= goteo.dist %>/assets/fonts/',
                src: [ '**/fonts/*' ]
            }, {
	            expand: true,
	            flatten: true,
	            dot: true,
	            cwd: '<%= goteo.app %>/assets/vendor/slick-carousel/',
	            dest: '<%= goteo.dist %>/assets/css/fonts/',
	            src: [ '**/fonts/*' ]
	        }, {
                expand: true,
                flatten: true,
                dot: true,
                cwd: '<%= goteo.app %>/assets/vendor/summernote/dist/font/',
                dest: '<%= goteo.dist %>/assets/css/font/',
                src: [ '*' ]
            }]
        }
    });
    grunt.loadNpmTasks('grunt-contrib-copy');
};
<commit_msg>grunt copy fonts for slick carousel<commit_after>// COPY
// Copies remaining files to places other tasks can use
module.exports = function(grunt) {

    'use strict';

    // Read manifest files from plugins and copies assets to destination (it existing)
    grunt.registerTask('copy:plugins', function (dest) {
        var settings = grunt.config.get('settings');
        var dir = '.tmp';
        if(dest === 'dist') {
            dir = grunt.config.get('goteo').dist;
        }

        for(var plugin in settings.plugins) {
            if(settings.plugins[plugin].active && grunt.file.exists('extend/' + plugin + '/manifest.yml')) {
                grunt.file.setBase('extend/' + plugin);
                var manifest = grunt.file.readYAML('manifest.yml');
                if(manifest.assets) {
                    for(var origin in manifest.assets) {
                        var destination = '../../' + dir + '/' + manifest.assets[origin];
                        if(!grunt.file.exists(origin)) {
                            grunt.fail.warn('Plugin asset [extend/' + plugin + '/' + origin + '] not found');
                        }
                        if(grunt.file.isFile(origin)) {
                            grunt.verbose.writeln('Found plugin [' + plugin + '] with asset [' + origin + '] , copying to [' + destination + ']');
                            grunt.file.copy(origin, destination);
                        }
                        else {
                            var files = grunt.file.expandMapping('**/*', destination, {cwd: origin});
                            for(var i in files) {
                                var o = files[i].src;
                                var d = files[i].dest;
                                // console.log('COPY',o,'TO',d);
                                if(grunt.file.isFile(o.toString())) {
                                    grunt.verbose.writeln('Found plugin [' + plugin + '] with asset [' + o + '] , copying to [' + d + ']');
                                    grunt.file.copy(o.toString(), d);
                                }
                            }
                        }
                    }
                }
                grunt.file.setBase('../../');
            }
        }
    });

    grunt.config('copy', {
        devel: {
            expand: true,
            dot: true,
            cwd: '<%= goteo.app %>',
            dest: '.tmp',
            // CSS is copied by SASS plugin
            src: [ '*', 'assets/js/**/*', 'assets/vendor/**/*', 'assets/img/**/*', 'templates/**/*', 'view/**/*' ]

        },

        dist: {
            expand: true,
            dot: true,
            cwd: '<%= goteo.app %>',
            dest: '<%= goteo.dist %>',
            src: [ '*', 'assets/js/*/*', 'assets/vendor/**/*', 'assets/img/**/*', 'templates/**/*', 'view/**/*' ]
        },

        fonts: {
            files: [{
                expand: true,
                flatten: true,
                dot: true,
                cwd: '<%= goteo.app %>/assets/vendor/',
                dest: '<%= goteo.dist %>/assets/fonts/',
                src: [ '**/fonts/*' ]
            }, {
	            expand: true,
	            flatten: true,
	            dot: true,
	            cwd: '<%= goteo.app %>/assets/vendor/slick-carousel/',
	            dest: '<%= goteo.dist %>/assets/css/fonts/',
	            src: [ '**/fonts/*' ]
	        }, {
                expand: true,
                flatten: true,
                dot: true,
                cwd: '<%= goteo.app %>/assets/vendor/slick-carousel/slick/fonts/',
                dest: '<%= goteo.dist %>/assets/css/fonts/',
                src: [ '*' ]
            },{
                expand: true,
                flatten: true,
                dot: true,
                cwd: '<%= goteo.app %>/assets/vendor/summernote/dist/font/',
                dest: '<%= goteo.dist %>/assets/css/font/',
                src: [ '*' ]
            }]
        }
    });
    grunt.loadNpmTasks('grunt-contrib-copy');
};
<|endoftext|>


<commit_before>Rickshaw.namespace('Rickshaw.Graph.RangeSlider');

Rickshaw.Graph.RangeSlider = Rickshaw.Class.create({

	initialize: function(args) {

		var $ = jQuery;
		var self = this;
		var element = this.element = args.element;
		var graphs = this.graphs = args.graphs;
		if (!graphs) {
			graphs = this.graph = args.graph;
		}
		if (graphs.constructor !== Array) {
			graphs = [graphs];
		}
		this.graph = graphs[0];

		this.slideCallbacks = [];

		this.build();

		for (var i = 0; i < graphs.length; i++) {
			graphs[i].onUpdate(function() {
				self.update();
			}.bind(self));

			graphs[i].onConfigure(function() {
				$(element)[0].style.width = graphs[i].width + 'px';
			}.bind(self));
		}

	},

	build: function() {

		var domain;
		var element = this.element;
		var $ = jQuery;
		var self = this;
		var graphs = this.graphs || this.graph;

		if (graphs.constructor !== Array) {
			graphs = [graphs];
		}

		// base the slider's min/max on the first graph
		this.graph = graphs[0];
		domain = graphs[0].dataDomain();

		$(function() {
			$(element).slider({
				range: true,
				min: domain[0],
				max: domain[1],
				values: [
					domain[0],
					domain[1]
				],
				start: function(event, ui) {
					self.slideStarted({ event: event, ui: ui });
				},
				stop: function(event, ui) {
					self.slideFinished({ event: event, ui: ui });
				},
				slide: function(event, ui) {
					if (!self.slideShouldUpdate(event, ui))
						return;

					if (ui.values[1] <= ui.values[0]) return;

					for (var i = 0; i < graphs.length; i++) {
						self.processSlideChange({
							event: event,
							ui: ui,
							graph: graphs[i]
						});
					}
				}
			} );
		} );

		graphs[0].onConfigure(function() {
			$(element)[0].style.width = graphs[0].width + 'px';
		}.bind(this));

	},

	update: function() {

		var element = this.element;
		var graph = this.graph;
		var $ = jQuery;

		var values = $(element).slider('option', 'values');

		var domain = graph.dataDomain();

		$(element).slider('option', 'min', domain[0]);
		$(element).slider('option', 'max', domain[1]);

		if (graph.window.xMin == null) {
			values[0] = domain[0];
		}
		if (graph.window.xMax == null) {
			values[1] = domain[1];
		}

		$(element).slider('option', 'values', values);
	},

	onSlide: function(callback) {
		this.slideCallbacks.push(callback);
	},

	processSlideChange: function(args) {
		var event = args.event;
		var ui = args.ui;
		var graph = args.graph;

		graph.window.xMin = ui.values[0];
		graph.window.xMax = ui.values[1];
		graph.update();

		var domain = graph.dataDomain();

		// if we're at an extreme, stick there
		if (domain[0] == ui.values[0]) {
			graph.window.xMin = undefined;
		}

		if (domain[1] == ui.values[1]) {
			graph.window.xMax = undefined;
		}

		this.slideCallbacks.forEach(function(callback) {
			callback(graph, graph.window.xMin, graph.window.xMax);
		});

	},

	// allows the slide updates to bail out if sliding is not permitted
	slideShouldUpdate: function() {
		return true;
	},

	slideStarted: function() {
		return;
	},

	slideFinished: function() {
		return;
	}
});

<commit_msg>Create a locally scoped copy of the loop-index var to prevent accessing out-of-bound index in the onConfigure callback<commit_after>Rickshaw.namespace('Rickshaw.Graph.RangeSlider');

Rickshaw.Graph.RangeSlider = Rickshaw.Class.create({

	initialize: function(args) {

		var $ = jQuery;
		var self = this;
		var element = this.element = args.element;
		var graphs = this.graphs = args.graphs;
		if (!graphs) {
			graphs = this.graph = args.graph;
		}
		if (graphs.constructor !== Array) {
			graphs = [graphs];
		}
		this.graph = graphs[0];

		this.slideCallbacks = [];

		this.build();

		for (var i = 0; i < graphs.length; i++) {
			// When the loop exits, the value of i would be an out-of-bound index for the
			// graphs array, which would cause problems when it's used in the onConfigure
			// callback below. Since there are no block scopes in JS. Hence, a locally scoped
			// copy.
			var idx = i;
			graphs[i].onUpdate(function() {
				self.update();
			}.bind(self));

			graphs[i].onConfigure(function() {
				$(element)[0].style.width = graphs[idx].width + 'px';
			}.bind(self));
		}

	},

	build: function() {

		var domain;
		var element = this.element;
		var $ = jQuery;
		var self = this;
		var graphs = this.graphs || this.graph;

		if (graphs.constructor !== Array) {
			graphs = [graphs];
		}

		// base the slider's min/max on the first graph
		this.graph = graphs[0];
		domain = graphs[0].dataDomain();

		$(function() {
			$(element).slider({
				range: true,
				min: domain[0],
				max: domain[1],
				values: [
					domain[0],
					domain[1]
				],
				start: function(event, ui) {
					self.slideStarted({ event: event, ui: ui });
				},
				stop: function(event, ui) {
					self.slideFinished({ event: event, ui: ui });
				},
				slide: function(event, ui) {
					if (!self.slideShouldUpdate(event, ui))
						return;

					if (ui.values[1] <= ui.values[0]) return;

					for (var i = 0; i < graphs.length; i++) {
						self.processSlideChange({
							event: event,
							ui: ui,
							graph: graphs[i]
						});
					}
				}
			} );
		} );

		graphs[0].onConfigure(function() {
			$(element)[0].style.width = graphs[0].width + 'px';
		}.bind(this));

	},

	update: function() {

		var element = this.element;
		var graph = this.graph;
		var $ = jQuery;

		var values = $(element).slider('option', 'values');

		var domain = graph.dataDomain();

		$(element).slider('option', 'min', domain[0]);
		$(element).slider('option', 'max', domain[1]);

		if (graph.window.xMin == null) {
			values[0] = domain[0];
		}
		if (graph.window.xMax == null) {
			values[1] = domain[1];
		}

		$(element).slider('option', 'values', values);
	},

	onSlide: function(callback) {
		this.slideCallbacks.push(callback);
	},

	processSlideChange: function(args) {
		var event = args.event;
		var ui = args.ui;
		var graph = args.graph;

		graph.window.xMin = ui.values[0];
		graph.window.xMax = ui.values[1];
		graph.update();

		var domain = graph.dataDomain();

		// if we're at an extreme, stick there
		if (domain[0] == ui.values[0]) {
			graph.window.xMin = undefined;
		}

		if (domain[1] == ui.values[1]) {
			graph.window.xMax = undefined;
		}

		this.slideCallbacks.forEach(function(callback) {
			callback(graph, graph.window.xMin, graph.window.xMax);
		});

	},

	// allows the slide updates to bail out if sliding is not permitted
	slideShouldUpdate: function() {
		return true;
	},

	slideStarted: function() {
		return;
	},

	slideFinished: function() {
		return;
	}
});

<|endoftext|>


<commit_before>import classNames from 'classnames';
import React from 'react';
import {Link, RouteHandler} from 'react-router';
import {StoreMixin} from 'mesosphere-shared-reactjs';

import AlertPanel from '../../components/AlertPanel';
import Breadcrumbs from '../../components/Breadcrumbs';
import DCOSStore from '../../stores/DCOSStore';
import FilterBar from '../../components/FilterBar';
import FilterHeadline from '../../components/FilterHeadline';
import Icon from '../../components/Icon';
import QueryParamsMixin from '../../mixins/QueryParamsMixin';
import RequestErrorMsg from '../../components/RequestErrorMsg';
import SaveStateMixin from '../../mixins/SaveStateMixin';
import {
  SERVICE_FORM_MODAL,
  SERVICE_GROUP_FORM_MODAL
} from '../../constants/ModalKeys';
import Service from '../../structs/Service';
import ServiceDetail from '../../components/ServiceDetail';
import ServiceFilterTypes from '../../constants/ServiceFilterTypes';
import ServiceFormModal from '../../components/modals/ServiceFormModal';
import ServiceSearchFilter from '../../components/ServiceSearchFilter';
import ServiceSidebarFilters from '../../components/ServiceSidebarFilters';
import ServiceGroupFormModal from '../../components/modals/ServiceGroupFormModal';
import ServicesTable from '../../components/ServicesTable';
import ServiceTree from '../../structs/ServiceTree';
import SidebarActions from '../../events/SidebarActions';

var DEFAULT_FILTER_OPTIONS = {
  filterHealth: null,
  filterOther: null,
  filterStatus: null,
  filterLabels: null,
  searchString: ''
};

let saveState_properties = Object.keys(DEFAULT_FILTER_OPTIONS);

var ServicesTab = React.createClass({

  displayName: 'ServicesTab',

  saveState_key: 'servicesPage',

  saveState_properties,

  mixins: [SaveStateMixin, StoreMixin, QueryParamsMixin],

  statics: {
    // Static life cycle method from react router, that will be called
    // 'when a handler is about to render', i.e. on route change:
    // https://github.com/rackt/react-router/
    // blob/master/docs/api/components/RouteHandler.md
    willTransitionTo: function () {
      SidebarActions.close();
    }
  },

  contextTypes: {
    router: React.PropTypes.func
  },

  getInitialState: function () {
    return Object.assign({}, DEFAULT_FILTER_OPTIONS, {
      marathonErrorCount: 0,
      isServiceGroupFormModalShown: false,
      isServiceFormModalShown: false
    });
  },

  componentWillMount: function () {
    this.store_listeners = [
      {name: 'dcos', events: ['change']},
      {name: 'marathon', events: ['groupsSuccess', 'groupsError']}
    ];
  },

  componentDidMount: function () {
    let {state} = this;
    Object.keys(DEFAULT_FILTER_OPTIONS).forEach((saveStateKey) => {
      const queryParams = this.getQueryParamObject();
      let saveStateValue = state[saveStateKey];
      if (saveStateValue !== queryParams[saveStateKey]) {
        this.setQueryParam(saveStateKey, saveStateValue);
      }
    });
  },

  onMarathonStoreGroupsError: function () {
    this.setState({marathonErrorCount: this.state.marathonErrorCount + 1});
  },

  onMarathonStoreGroupsSuccess: function () {
    this.setState({marathonErrorCount: 0});
  },

  handleCloseServiceFormModal: function () {
    this.setState({isServiceFormModalShown: false});
  },

  handleCloseGroupFormModal: function () {
    this.setState({isServiceGroupFormModalShown: false});
  },

  handleFilterChange: function (filterValues, filterType) {
    var stateChanges = Object.assign({}, this.state);
    stateChanges[filterType] = filterValues;

    this.setState(stateChanges);
  },

  handleOpenModal: function (id) {
    let modalStates = {
      isServiceFormModalShown: SERVICE_FORM_MODAL === id,
      isServiceGroupFormModalShown: SERVICE_GROUP_FORM_MODAL === id
    };

    this.setState(modalStates);
  },

  resetFilterQueryParams: function () {
    let router = this.context.router;
    let queryParams = router.getCurrentQuery();

    Object.values(ServiceFilterTypes).forEach(function (filterKey) {
      delete queryParams[filterKey];
    });

    router.transitionTo(router.getCurrentPathname(), {}, queryParams);
  },

  resetFilter: function () {
    var state = Object.assign({}, this.state, DEFAULT_FILTER_OPTIONS);
    this.setState(state, this.resetFilterQueryParams);
  },

  getAlertPanelFooter: function () {
    return (

        <button className="button button-stroke button-inverse"
          onClick={() => this.handleOpenModal(SERVICE_GROUP_FORM_MODAL)}>
          Create Group
        </button>
        <button className="button button-success"
          onClick={() => this.handleOpenModal(SERVICE_FORM_MODAL)}>
          Deploy Service
        </button>

    );
  },

  getNotFoundFooter: function () {
    return (
      <Link to="services-page" className="button button-stroke button-inverse">
        Go back to Services Page
      </Link>
    );
  },

  getServiceNotFound: function (id) {
    return (
      <AlertPanel
        title="Not Found"
        footer={this.getNotFoundFooter()}
        icon={<Icon id="services" color="white" size="jumbo" />}>

          {`Service '${id}' was not found.`}

      </AlertPanel>
    );
  },

  getContents: function (item) {
    if (this.state.marathonErrorCount > 3) {
      return (

          <RequestErrorMsg />

      );
    }

    // Render loading screen
    if (!DCOSStore.dataProcessed) {
      return (

      );
    }

    let {id} = this.props.params;
    id = id && decodeURIComponent(id);
    let itemFound = !!DCOSStore.serviceTree.findItemById(id);
    if (id && this.props.params.id !== '/' && !itemFound) {
      return this.getServiceNotFound(id);
    }

    // TODO (DCOS-7580): Clean up ServicesTab routed and unrouted views
    if (this.props.params.taskID || this.props.params.volumeID) {
      return (
        <RouteHandler service={item} />
      );
    }

    // Render service detail
    if (item instanceof Service) {
      return (<ServiceDetail service={item} />);
    }

    // Render service table or empty service table if only id is available
    if ((item instanceof ServiceTree && item.getItems().length > 0) || id) {
      return this.getServiceTreeView(item);
    }

    // Render empty root panel
    return (

        <AlertPanel
          title="No Services Deployed"
          footer={this.getAlertPanelFooter()}
          icon={<Icon id="services" color="white" size="jumbo" />}>

            Create groups to organize your services or
            deploy a new service.

        </AlertPanel>

    );
  },

  getHeadline: function (services, filteredServices, hasFiltersApplied) {
    if (hasFiltersApplied) {
      return (
        <FilterHeadline
          className="breadcrumb-style-headline"
          inverseStyle={true}
          onReset={this.resetFilter}
          name="Service"
          currentLength={filteredServices.length}
          totalLength={services.length} />
      );
    }

    return (
      <Breadcrumbs />
    );
  },

  getServiceTreeView(serviceTree) {
    const {state} = this;
    const hasFiltersApplied = Object.keys(DEFAULT_FILTER_OPTIONS)
      .some(function (filterKey) {
        return state[filterKey] != null && state[filterKey].length > 0;
      });

    let allServices = serviceTree.flattenItems().getItems();
    let filteredServices = serviceTree.getItems();

    if (hasFiltersApplied) {
      filteredServices = serviceTree.filterItemsByFilter({
        health: state.filterHealth,
        labels: state.filterLabels,
        other: state.filterOther,
        status: state.filterStatus,
        id: state.searchString
      });

      if (!state.searchString) {
        filteredServices = filteredServices.flattenItems();
      }

      filteredServices = filteredServices.getItems();
    }

    return (

        <ServiceSidebarFilters
          handleFilterChange={this.handleFilterChange}
          services={allServices} />

          {this.getHeadline(allServices, filteredServices, hasFiltersApplied)}
          <FilterBar rightAlignLastNChildren={2}>
            <ServiceSearchFilter
              handleFilterChange={this.handleFilterChange} />
            <button className="button button-stroke button-inverse"
              onClick={() => this.handleOpenModal(SERVICE_GROUP_FORM_MODAL)}>
              Create Group
            </button>
            <button className="button button-success"
              onClick={() => this.handleOpenModal(SERVICE_FORM_MODAL)}>
              Deploy Service
            </button>
          </FilterBar>
          <ServicesTable services={filteredServices}
            isFiltered={hasFiltersApplied} />

    );
  },

  render: function () {
    let {id} = this.props.params;
    id = decodeURIComponent(id);
    let {state} = this;

    // Find item in root tree
    let item = DCOSStore.serviceTree.findItemById(id) || DCOSStore.serviceTree;

    // The regular expression `/^(\/.+)$/` is looking for the beginning of the
    // string and matches if the string starts with a `/` and does contain more
    // characters after the slash. This is combined into a group and then
    // replaced with the first group which is the complete string and a `/` is
    // appended. This is needed because in most case a path like
    // `/group/another-group` will be given by `getId` except on root then the
    // return value of `getId` would be `/` so in most cases we want to append a
    // `/` so that the user can begin typing the `id` of their application.
    let serviceId = item.getId().replace(/^(\/.+)$/, '$1/');

    // Make sure to grow when logs are displayed
    let routes = this.context.router.getCurrentRoutes();
    let classes = classNames({
      'flex-container-col flex-grow flex-shrink': routes[routes.length - 1].dontScroll
    });

    return (

        {this.getContents(item)}
        <ServiceGroupFormModal
          open={state.isServiceGroupFormModalShown}
          parentGroupId={item.getId()}
          onClose={this.handleCloseGroupFormModal}/>
        <ServiceFormModal open={state.isServiceFormModalShown}
          id={serviceId}
          onClose={this.handleCloseServiceFormModal}/>

    );
  }

});

module.exports = ServicesTab;
<commit_msg>Reset filters when query params are removed<commit_after>import classNames from 'classnames';
import React from 'react';
import {Link, RouteHandler} from 'react-router';
import {StoreMixin} from 'mesosphere-shared-reactjs';

import AlertPanel from '../../components/AlertPanel';
import Breadcrumbs from '../../components/Breadcrumbs';
import DCOSStore from '../../stores/DCOSStore';
import FilterBar from '../../components/FilterBar';
import FilterHeadline from '../../components/FilterHeadline';
import Icon from '../../components/Icon';
import QueryParamsMixin from '../../mixins/QueryParamsMixin';
import RequestErrorMsg from '../../components/RequestErrorMsg';
import SaveStateMixin from '../../mixins/SaveStateMixin';
import {
  SERVICE_FORM_MODAL,
  SERVICE_GROUP_FORM_MODAL
} from '../../constants/ModalKeys';
import Service from '../../structs/Service';
import ServiceDetail from '../../components/ServiceDetail';
import ServiceFilterTypes from '../../constants/ServiceFilterTypes';
import ServiceFormModal from '../../components/modals/ServiceFormModal';
import ServiceSearchFilter from '../../components/ServiceSearchFilter';
import ServiceSidebarFilters from '../../components/ServiceSidebarFilters';
import ServiceGroupFormModal from '../../components/modals/ServiceGroupFormModal';
import ServicesTable from '../../components/ServicesTable';
import ServiceTree from '../../structs/ServiceTree';
import SidebarActions from '../../events/SidebarActions';

var DEFAULT_FILTER_OPTIONS = {
  filterHealth: null,
  filterOther: null,
  filterStatus: null,
  filterLabels: null,
  searchString: ''
};

let saveState_properties = Object.keys(DEFAULT_FILTER_OPTIONS);

var ServicesTab = React.createClass({

  displayName: 'ServicesTab',

  saveState_key: 'servicesPage',

  saveState_properties,

  mixins: [SaveStateMixin, StoreMixin, QueryParamsMixin],

  statics: {
    // Static life cycle method from react router, that will be called
    // 'when a handler is about to render', i.e. on route change:
    // https://github.com/rackt/react-router/
    // blob/master/docs/api/components/RouteHandler.md
    willTransitionTo: function () {
      SidebarActions.close();
    }
  },

  contextTypes: {
    router: React.PropTypes.func
  },

  getInitialState: function () {
    return Object.assign({}, DEFAULT_FILTER_OPTIONS, {
      marathonErrorCount: 0,
      isServiceGroupFormModalShown: false,
      isServiceFormModalShown: false
    });
  },

  componentWillMount: function () {
    this.store_listeners = [
      {name: 'dcos', events: ['change']},
      {name: 'marathon', events: ['groupsSuccess', 'groupsError']}
    ];
  },

  componentDidMount: function () {
    let {state} = this;
    Object.keys(DEFAULT_FILTER_OPTIONS).forEach((saveStateKey) => {
      const queryParams = this.getQueryParamObject();
      let saveStateValue = state[saveStateKey];
      if (saveStateValue !== queryParams[saveStateKey]) {
        this.setQueryParam(saveStateKey, saveStateValue);
      }
    });
  },

  componentWillReceiveProps: function () {
    const queryParams = this.getQueryParamObject();
    const {state} = this;

    // Reset filter defaults when query params are deleted externally
    Object.keys(DEFAULT_FILTER_OPTIONS).forEach(stateKey => {
      if (queryParams[stateKey] == null &&
        (state[stateKey] != null && state[stateKey].length > 0)) {
        this.setState({
          [stateKey]: DEFAULT_FILTER_OPTIONS[stateKey]
        });
      }
    });
  },

  onMarathonStoreGroupsError: function () {
    this.setState({marathonErrorCount: this.state.marathonErrorCount + 1});
  },

  onMarathonStoreGroupsSuccess: function () {
    this.setState({marathonErrorCount: 0});
  },

  handleCloseServiceFormModal: function () {
    this.setState({isServiceFormModalShown: false});
  },

  handleCloseGroupFormModal: function () {
    this.setState({isServiceGroupFormModalShown: false});
  },

  handleFilterChange: function (filterValues, filterType) {
    var stateChanges = Object.assign({}, this.state);
    stateChanges[filterType] = filterValues;

    this.setState(stateChanges);
  },

  handleOpenModal: function (id) {
    let modalStates = {
      isServiceFormModalShown: SERVICE_FORM_MODAL === id,
      isServiceGroupFormModalShown: SERVICE_GROUP_FORM_MODAL === id
    };

    this.setState(modalStates);
  },

  resetFilterQueryParams: function () {
    let router = this.context.router;
    let queryParams = router.getCurrentQuery();

    Object.values(ServiceFilterTypes).forEach(function (filterKey) {
      delete queryParams[filterKey];
    });

    router.transitionTo(router.getCurrentPathname(), {}, queryParams);
  },

  resetFilter: function () {
    var state = Object.assign({}, this.state, DEFAULT_FILTER_OPTIONS);
    this.setState(state, this.resetFilterQueryParams);
  },

  getAlertPanelFooter: function () {
    return (

        <button className="button button-stroke button-inverse"
          onClick={() => this.handleOpenModal(SERVICE_GROUP_FORM_MODAL)}>
          Create Group
        </button>
        <button className="button button-success"
          onClick={() => this.handleOpenModal(SERVICE_FORM_MODAL)}>
          Deploy Service
        </button>

    );
  },

  getNotFoundFooter: function () {
    return (
      <Link to="services-page" className="button button-stroke button-inverse">
        Go back to Services Page
      </Link>
    );
  },

  getServiceNotFound: function (id) {
    return (
      <AlertPanel
        title="Not Found"
        footer={this.getNotFoundFooter()}
        icon={<Icon id="services" color="white" size="jumbo" />}>

          {`Service '${id}' was not found.`}

      </AlertPanel>
    );
  },

  getContents: function (item) {
    if (this.state.marathonErrorCount > 3) {
      return (

          <RequestErrorMsg />

      );
    }

    // Render loading screen
    if (!DCOSStore.dataProcessed) {
      return (

      );
    }

    let {id} = this.props.params;
    id = id && decodeURIComponent(id);
    let itemFound = !!DCOSStore.serviceTree.findItemById(id);
    if (id && this.props.params.id !== '/' && !itemFound) {
      return this.getServiceNotFound(id);
    }

    // TODO (DCOS-7580): Clean up ServicesTab routed and unrouted views
    if (this.props.params.taskID || this.props.params.volumeID) {
      return (
        <RouteHandler service={item} />
      );
    }

    // Render service detail
    if (item instanceof Service) {
      return (<ServiceDetail service={item} />);
    }

    // Render service table or empty service table if only id is available
    if ((item instanceof ServiceTree && item.getItems().length > 0) || id) {
      return this.getServiceTreeView(item);
    }

    // Render empty root panel
    return (

        <AlertPanel
          title="No Services Deployed"
          footer={this.getAlertPanelFooter()}
          icon={<Icon id="services" color="white" size="jumbo" />}>

            Create groups to organize your services or
            deploy a new service.

        </AlertPanel>

    );
  },

  getHeadline: function (services, filteredServices, hasFiltersApplied) {
    if (hasFiltersApplied) {
      return (
        <FilterHeadline
          className="breadcrumb-style-headline"
          inverseStyle={true}
          onReset={this.resetFilter}
          name="Service"
          currentLength={filteredServices.length}
          totalLength={services.length} />
      );
    }

    return (
      <Breadcrumbs />
    );
  },

  getServiceTreeView(serviceTree) {
    const {state} = this;
    const hasFiltersApplied = Object.keys(DEFAULT_FILTER_OPTIONS)
      .some(function (filterKey) {
        return state[filterKey] != null && state[filterKey].length > 0;
      });

    let allServices = serviceTree.flattenItems().getItems();
    let filteredServices = serviceTree.getItems();

    if (hasFiltersApplied) {
      filteredServices = serviceTree.filterItemsByFilter({
        health: state.filterHealth,
        labels: state.filterLabels,
        other: state.filterOther,
        status: state.filterStatus,
        id: state.searchString
      });

      if (!state.searchString) {
        filteredServices = filteredServices.flattenItems();
      }

      filteredServices = filteredServices.getItems();
    }

    return (

        <ServiceSidebarFilters
          handleFilterChange={this.handleFilterChange}
          services={allServices} />

          {this.getHeadline(allServices, filteredServices, hasFiltersApplied)}
          <FilterBar rightAlignLastNChildren={2}>
            <ServiceSearchFilter
              handleFilterChange={this.handleFilterChange} />
            <button className="button button-stroke button-inverse"
              onClick={() => this.handleOpenModal(SERVICE_GROUP_FORM_MODAL)}>
              Create Group
            </button>
            <button className="button button-success"
              onClick={() => this.handleOpenModal(SERVICE_FORM_MODAL)}>
              Deploy Service
            </button>
          </FilterBar>
          <ServicesTable services={filteredServices}
            isFiltered={hasFiltersApplied} />

    );
  },

  render: function () {
    let {id} = this.props.params;
    id = decodeURIComponent(id);
    let {state} = this;

    // Find item in root tree
    let item = DCOSStore.serviceTree.findItemById(id) || DCOSStore.serviceTree;

    // The regular expression `/^(\/.+)$/` is looking for the beginning of the
    // string and matches if the string starts with a `/` and does contain more
    // characters after the slash. This is combined into a group and then
    // replaced with the first group which is the complete string and a `/` is
    // appended. This is needed because in most case a path like
    // `/group/another-group` will be given by `getId` except on root then the
    // return value of `getId` would be `/` so in most cases we want to append a
    // `/` so that the user can begin typing the `id` of their application.
    let serviceId = item.getId().replace(/^(\/.+)$/, '$1/');

    // Make sure to grow when logs are displayed
    let routes = this.context.router.getCurrentRoutes();
    let classes = classNames({
      'flex-container-col flex-grow flex-shrink': routes[routes.length - 1].dontScroll
    });

    return (

        {this.getContents(item)}
        <ServiceGroupFormModal
          open={state.isServiceGroupFormModalShown}
          parentGroupId={item.getId()}
          onClose={this.handleCloseGroupFormModal}/>
        <ServiceFormModal open={state.isServiceFormModalShown}
          id={serviceId}
          onClose={this.handleCloseServiceFormModal}/>

    );
  }

});

module.exports = ServicesTab;
<|endoftext|>


<commit_before>import SocketService from './SocketService';
import ChatActionsCreators from '../actions/ChatActionCreators';

class ChatSocketService extends SocketService {

    constructor() {
        super();
        this._name = 'chat';
    }

    sendMessage(userTo, messageText) {
        this._socket.emit('sendMessage', userTo, messageText, (error) => {
            console.log('Error from sockets', error);
        });
    }

    getMessages(userId, offset) {
        this._socket.emit('getMessages', userId, offset, () => {
            ChatActionsCreators.noMoreMessages(userId);
        });
    }

    markAsReaded(userId, timestamp) {
        this._socket.emit('markAsReaded', userId, timestamp);
    }

    bind() {

        var socket = this._socket;

        socket.on('messages', function(messages, fresh) {
            ChatActionsCreators.messages(messages, fresh);
        });

        socket.on('no-messages', function() {
            ChatActionsCreators.noMessages();
        });

        socket.on('userStatus', function(user, status) {
            ChatActionsCreators.userStatus(user, status);
        });
    }

}

export default new ChatSocketService();<commit_msg>QS-1296: Display alert modal if a socket error is received<commit_after>import SocketService from './SocketService';
import ChatActionsCreators from '../actions/ChatActionCreators';

class ChatSocketService extends SocketService {

    constructor() {
        super();
        this._name = 'chat';
    }

    sendMessage(userTo, messageText) {
        this._socket.emit('sendMessage', userTo, messageText, (error) => {
            console.log('Error from sockets', error);
            nekunoApp.alert('Error: ' + error);
        });
    }

    getMessages(userId, offset) {
        this._socket.emit('getMessages', userId, offset, () => {
            ChatActionsCreators.noMoreMessages(userId);
        });
    }

    markAsReaded(userId, timestamp) {
        this._socket.emit('markAsReaded', userId, timestamp);
    }

    bind() {

        var socket = this._socket;

        socket.on('messages', function(messages, fresh) {
            ChatActionsCreators.messages(messages, fresh);
        });

        socket.on('no-messages', function() {
            ChatActionsCreators.noMessages();
        });

        socket.on('userStatus', function(user, status) {
            ChatActionsCreators.userStatus(user, status);
        });
    }

}

export default new ChatSocketService();<|endoftext|>


<commit_before>'use strict';

angular.module('copayApp.services').factory('backButton', function($log, $rootScope, gettextCatalog, $deepStateRedirect, $document, $timeout, go) {
	var root = {};

	root.menuOpened = false;

	var arrHistory = [];
	var body = $document.find('body').eq(0);
	var shownExitMessage = false;

	window.addEventListener("hashchange", function() {
		var path = location.hash.replace(/\//g, '.');
		if (path == arrHistory[arrHistory.length - 2]) {
			arrHistory.pop();
		}
		else {
			arrHistory.push(path);
		}
	}, false);

	function back() {
		if (body.hasClass('modal-open')) {
			$rootScope.$emit('closeModal');
		}
		else if (root.menuOpened) {
			go.swipe();
			root.menuOpened = false;
		}
		else if (location.hash == '#/') {
			if (shownExitMessage) {
				navigator.app.exitApp();
			}
			else {
				shownExitMessage = true;
				window.plugins.toast.showShortBottom(gettextCatalog.getString('Press again to exit'));
				$timeout(function() {
					shownExitMessage = false;
				}, 2000);
			}
		}
		else {
			var path = arrHistory[arrHistory.length - 2].substr(2);
			if (path) {
				if (/\//.test(path)) {
					go.path(path);
				}
				else {
					$deepStateRedirect.reset(path);
					go.path(path);
				}
			}
			else {
				go.walletHome()
			}
		}
	}

	document.addEventListener('backbutton', function() {
		back();
	}, false);

	root.back = back;
	root.arrHistory = arrHistory;
	return root;
});<commit_msg>fix back button<commit_after>'use strict';

angular.module('copayApp.services').factory('backButton', function($log, $rootScope, gettextCatalog, $deepStateRedirect, $document, $timeout, go) {
	var root = {};

	root.menuOpened = false;

	var arrHistory = [];
	var body = $document.find('body').eq(0);
	var shownExitMessage = false;

	window.addEventListener("hashchange", function() {
		var path = location.hash.replace(/\//g, '.');
		if (path == arrHistory[arrHistory.length - 2]) {
			arrHistory.pop();
		}
		else {
			arrHistory.push(path);
		}
	}, false);

	function back() {
		if (body.hasClass('modal-open')) {
			$rootScope.$emit('closeModal');
		}
		else if (root.menuOpened) {
			go.swipe();
			root.menuOpened = false;
		}
		else if (location.hash == '#/' && arrHistory.length == 1) {
			if (shownExitMessage) {
				navigator.app.exitApp();
			}
			else {
				shownExitMessage = true;
				window.plugins.toast.showShortBottom(gettextCatalog.getString('Press again to exit'));
				$timeout(function() {
					shownExitMessage = false;
				}, 2000);
			}
		}
		else {
			var path = arrHistory[arrHistory.length - 2].substr(2);
			if (path) {
				if (/\//.test(path)) {
					go.path(path);
				}
				else {
					$deepStateRedirect.reset(path);
					go.path(path);
				}
			}
			else {
				go.walletHome()
			}
		}
	}

	document.addEventListener('backbutton', function() {
		back();
	}, false);

	root.back = back;
	root.arrHistory = arrHistory;
	return root;
});<|endoftext|>


<commit_before>/* Copyright (c) 2011 by The Authors.
 * Published under the LGPL 2.1 license.
 * See /license-notice.txt for the full text of the license notice.
 * See /license.txt for the full text of the license.
 */

/**
 * A GraphComponent is the parent class for the objects' that form a graph. Each
 * GraphComponent can carry a Label.
 *
 * @constructor
 */
jsts.geomgraph.GraphComponent = function(label) {
  this.label = label;
};

/**
 * @type {Label}
 * @protected
 */
jsts.geomgraph.GraphComponent.prototype.label = null;

/**
 * isInResult indicates if this component has already been included in the
 * result
 *
 * @type {boolean}
 * @private
 */
jsts.geomgraph.GraphComponent.prototype._isInResult = false;

/**
 * @type {boolean}
 * @private
 */
jsts.geomgraph.GraphComponent.prototype._isCovered = false;

/**
 * @type {boolean}
 * @private
 */
jsts.geomgraph.GraphComponent.prototype._isCoveredSet = false;

/**
 * @type {boolean}
 * @private
 */
jsts.geomgraph.GraphComponent.prototype._isVisited = false;

jsts.geomgraph.GraphComponent.prototype.getLabel = function() {
  return this.label;
};
jsts.geomgraph.GraphComponent.prototype.setLabel = function(label) {
  if (arguments.length === 2) {
    this.setLabel2.apply(this, arguments);
    return;
  }

  this.label = label;
};

/**
 * @param {boolean}
 *          isInResult
 */
jsts.geomgraph.GraphComponent.prototype.setInResult = function(isInResult) {
  this._isInResult = isInResult;
};

/**
 * @return {boolean}
 */
jsts.geomgraph.GraphComponent.prototype.isInResult = function() {
  return this._isInResult;
};

/**
 * @param {boolean}
 *          isCovered
 */
jsts.geomgraph.GraphComponent.prototype.setCovered = function(isCovered) {
  this._isCovered = isCovered;
  this._isCoveredSet = true;
};

/**
 * @return {boolean}
 */
jsts.geomgraph.GraphComponent.prototype.isCovered = function() {
  return this._isCovered;
};

/**
 * @return {boolean}
 */
jsts.geomgraph.GraphComponent.prototype.isCoveredSet = function() {
  return this._isCoveredSet;
};

/**
 * @return {boolean}
 */
jsts.geomgraph.GraphComponent.prototype.isVisited = function() {
  return this._isVisited;
};

/**
 * @param {boolean}
 *          isVisited
 */
jsts.geomgraph.GraphComponent.prototype.setVisited = function(isVisited) {
  this._isVisited = isVisited;
};

/**
 * @return {Coordinate} a coordinate in this component (or null, if there are
 *         none).
 */
jsts.geomgraph.GraphComponent.prototype.getCoordinate = function() {
  throw new jsts.error.AbstractMethodInvocationError();
};

/**
 * compute the contribution to an IM for this component
 *
 * @param {IntersectionMatrix}
 *          im
 * @protected
 */
jsts.geomgraph.GraphComponent.prototype.computeIM = function(im) {
  throw new jsts.error.AbstractMethodInvocationError();
};

/**
 * An isolated component is one that does not intersect or touch any other
 * component. This is the case if the label has valid locations for only a
 * single Geometry.
 *
 * @return true if this component is isolated.
 */
jsts.geomgraph.GraphComponent.prototype.isIsolated = function() {
  throw new jsts.error.AbstractMethodInvocationError();
};

/**
 * Update the IM with the contribution for this component. A component only
 * contributes if it has a labelling for both parent geometries
 *
 * @param {IntersectionMatrix}
 *          im
 */
jsts.geomgraph.GraphComponent.prototype.updateIM = function(im) {
  jsts.util.Assert.isTrue(this.label.getGeometryCount() >= 2, 'found partial label');
  this.computeIM(im);
};
<commit_msg>Refactored GraphComponent.<commit_after>/* Copyright (c) 2011 by The Authors.
 * Published under the LGPL 2.1 license.
 * See /license-notice.txt for the full text of the license notice.
 * See /license.txt for the full text of the license.
 */

(function() {

  /**
   * @requires jsts/util/Assert.js
   */

  var Assert = jsts.util.Assert;

  /**
   * A GraphComponent is the parent class for the objects' that form a graph.
   * Each GraphComponent can carry a Label.
   *
   * @constructor
   */
  var GraphComponent = function(label) {
    this.label = label;
  };

  /**
   * @type {Label}
   * @protected
   */
  GraphComponent.prototype.label = null;

  /**
   * isInResult indicates if this component has already been included in the
   * result
   *
   * @type {boolean}
   * @private
   */
  GraphComponent.prototype._isInResult = false;

  /**
   * @type {boolean}
   * @private
   */
  GraphComponent.prototype._isCovered = false;

  /**
   * @type {boolean}
   * @private
   */
  GraphComponent.prototype._isCoveredSet = false;

  /**
   * @type {boolean}
   * @private
   */
  GraphComponent.prototype._isVisited = false;

  GraphComponent.prototype.getLabel = function() {
    return this.label;
  };
  GraphComponent.prototype.setLabel = function(label) {
    if (arguments.length === 2) {
      this.setLabel2.apply(this, arguments);
      return;
    }

    this.label = label;
  };

  /**
   * @param {boolean}
   *          isInResult
   */
  GraphComponent.prototype.setInResult = function(isInResult) {
    this._isInResult = isInResult;
  };

  /**
   * @return {boolean}
   */
  GraphComponent.prototype.isInResult = function() {
    return this._isInResult;
  };

  /**
   * @param {boolean}
   *          isCovered
   */
  GraphComponent.prototype.setCovered = function(isCovered) {
    this._isCovered = isCovered;
    this._isCoveredSet = true;
  };

  /**
   * @return {boolean}
   */
  GraphComponent.prototype.isCovered = function() {
    return this._isCovered;
  };

  /**
   * @return {boolean}
   */
  GraphComponent.prototype.isCoveredSet = function() {
    return this._isCoveredSet;
  };

  /**
   * @return {boolean}
   */
  GraphComponent.prototype.isVisited = function() {
    return this._isVisited;
  };

  /**
   * @param {boolean}
   *          isVisited
   */
  GraphComponent.prototype.setVisited = function(isVisited) {
    this._isVisited = isVisited;
  };

  /**
   * @return {Coordinate} a coordinate in this component (or null, if there are
   *         none).
   */
  GraphComponent.prototype.getCoordinate = function() {
    throw new jsts.error.AbstractMethodInvocationError();
  };

  /**
   * compute the contribution to an IM for this component
   *
   * @param {IntersectionMatrix}
   *          im
   * @protected
   */
  GraphComponent.prototype.computeIM = function(im) {
    throw new jsts.error.AbstractMethodInvocationError();
  };

  /**
   * An isolated component is one that does not intersect or touch any other
   * component. This is the case if the label has valid locations for only a
   * single Geometry.
   *
   * @return true if this component is isolated.
   */
  GraphComponent.prototype.isIsolated = function() {
    throw new jsts.error.AbstractMethodInvocationError();
  };

  /**
   * Update the IM with the contribution for this component. A component only
   * contributes if it has a labelling for both parent geometries
   *
   * @param {IntersectionMatrix}
   *          im
   */
  GraphComponent.prototype.updateIM = function(im) {
    Assert.isTrue(this.label.getGeometryCount() >= 2, 'found partial label');
    this.computeIM(im);
  };

  jsts.geomgraph.GraphComponent = GraphComponent;

})();
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const [,, ...args] = process.argv;

if (args.length === 2) {
  const [month, year] = args;

  console.log(`generateMonth(${year}, ${month})`);
} else if (args.length === 1) {
  const [year] = args;

  console.log(`generateYear(${year})`);
} else {
  console.log('dun broke it');
  process.exit(64);
}
<commit_msg>re-add --harmony's to shebang<commit_after>#!/usr/bin/env node  --harmony_destructuring --harmony_rest_parameters

'use strict';

const [,, ...args] = process.argv;

if (args.length === 2) {
  const [month, year] = args;

  console.log(`generateMonth(${year}, ${month})`);
} else if (args.length === 1) {
  const [year] = args;

  console.log(`generateYear(${year})`);
} else {
  console.log('dun broke it');
  process.exit(64);
}
<|endoftext|>


<commit_before>// Copyright 2016 Hound Technology, Inc. All rights reserved.
// Use of this source code is governed by the Apache License 2.0
// license that can be found in the LICENSE file.

/* global global, process */

/**
 * @module
 */
import superagent from "superagent";
import urljoin from "urljoin";

const USER_AGENT = "libhoney-js/<@LIBHONEY_JS_VERSION@>";

const _global =
  typeof window !== "undefined"
    ? window
    : typeof global !== "undefined"
    ? global
    : undefined;

// how many events to collect in a batch
const batchSizeTrigger = 50; // either when the eventQueue is > this length
const batchTimeTrigger = 100; // or it's been more than this many ms since the first push

// how many batches to maintain in parallel
const maxConcurrentBatches = 10;

// how many events to queue up for busy batches before we start dropping
const pendingWorkCapacity = 10000;

// how long (in ms) to give a single POST before we timeout
const deadlineTimeoutMs = 60000;

const emptyResponseCallback = function() {};

const eachPromise = (arr, iteratorFn) =>
  arr.reduce((p, item) => {
    return p.then(() => {
      return iteratorFn(item);
    });
  }, Promise.resolve());

const partition = (arr, keyfn, createfn, addfn) => {
  let result = Object.create(null);
  arr.forEach(v => {
    let key = keyfn(v);
    if (!result[key]) {
      result[key] = createfn(v);
    } else {
      addfn(result[key], v);
    }
  });
  return result;
};

class BatchEndpointAggregator {
  constructor(events) {
    this.batches = partition(
      events,
      /* keyfn */
      ev => `${ev.apiHost}_${ev.writeKey}_${ev.dataset}`,
      /* createfn */
      ev => ({
        apiHost: ev.apiHost,
        writeKey: ev.writeKey,
        dataset: ev.dataset,
        events: [ev]
      }),
      /* addfn */
      (batch, ev) => batch.events.push(ev)
    );
  }

  encodeBatchEvents(events) {
    let first = true;
    let numEncoded = 0;
    let encodedEvents = events.reduce((acc, ev) => {
      try {
        let encodedEvent = JSON.stringify(ev);
        numEncoded++;
        let newAcc = acc + (!first ? "," : "") + encodedEvent;
        first = false;
        return newAcc;
      } catch (e) {
        ev.encodeError = e;
        return acc;
      }
    }, "");

    let encoded = "[" + encodedEvents + "]";
    return { encoded, numEncoded };
  }
}

/**
 * @private
 */
export class ValidatedEvent {
  constructor({
    timestamp,
    apiHost,
    postData,
    writeKey,
    dataset,
    sampleRate,
    metadata
  }) {
    this.timestamp = timestamp;
    this.apiHost = apiHost;
    this.postData = postData;
    this.writeKey = writeKey;
    this.dataset = dataset;
    this.sampleRate = sampleRate;
    this.metadata = metadata;
  }

  toJSON() {
    let json = {};
    if (this.timestamp) {
      json.time = this.timestamp;
    }
    if (this.sampleRate) {
      json.samplerate = this.sampleRate;
    }
    if (this.postData) {
      json.data = this.postData;
    }
    return json;
  }

  toBrokenJSON() {
    let fields = [];
    if (this.timestamp) {
      fields.push(`"time":${JSON.stringify(this.timestamp)}`);
    }
    if (this.sampleRate) {
      fields.push(`"samplerate":${JSON.stringify(this.sampleRate)}`);
    }
    if (this.postData) {
      fields.push(`"data":${JSON.stringify(this.postData)}`);
    }
    return `{${fields.join(",")}}`;
  }
}

export class MockTransmission {
  constructor(options) {
    this.constructorArg = options;
    this.events = [];
  }

  sendEvent(ev) {
    this.events.push(ev);
  }

  sendPresampledEvent(ev) {
    this.events.push(ev);
  }

  reset() {
    this.constructorArg = null;
    this.events = [];
  }
}

// deprecated.  Use ConsoleTransmission instead.
export class WriterTransmission {
  sendEvent(ev) {
    console.log(JSON.stringify(ev.toBrokenJSON()));
  }

  sendPresampledEvent(ev) {
    console.log(JSON.stringify(ev.toBrokenJSON()));
  }
}

export class ConsoleTransmission {
  sendEvent(ev) {
    console.log(JSON.stringify(ev));
  }

  sendPresampledEvent(ev) {
    console.log(JSON.stringify(ev));
  }
}

export class NullTransmission {
  sendEvent(_ev) {}

  sendPresampledEvent(_ev) {}
}

/**
 * @private
 */
export class Transmission {
  constructor(options) {
    this._responseCallback = emptyResponseCallback;
    this._batchSizeTrigger = batchSizeTrigger;
    this._batchTimeTrigger = batchTimeTrigger;
    this._maxConcurrentBatches = maxConcurrentBatches;
    this._pendingWorkCapacity = pendingWorkCapacity;
    this._timeout = deadlineTimeoutMs;
    this._sendTimeoutId = -1;
    this._eventQueue = [];
    this._batchCount = 0;

    if (typeof options.responseCallback === "function") {
      this._responseCallback = options.responseCallback;
    }
    if (typeof options.batchSizeTrigger === "number") {
      this._batchSizeTrigger = Math.max(options.batchSizeTrigger, 1);
    }
    if (typeof options.batchTimeTrigger === "number") {
      this._batchTimeTrigger = options.batchTimeTrigger;
    }
    if (typeof options.maxConcurrentBatches === "number") {
      this._maxConcurrentBatches = options.maxConcurrentBatches;
    }
    if (typeof options.pendingWorkCapacity === "number") {
      this._pendingWorkCapacity = options.pendingWorkCapacity;
    }
    if (typeof options.timeout === "number") {
      this._timeout = options.timeout;
    }

    this._userAgentAddition = options.userAgentAddition || "";
    this._proxy = options.proxy;

    // Included for testing; to stub out randomness and verify that an event
    // was dropped.
    this._randomFn = Math.random;
  }

  _droppedCallback(ev, reason) {
    this._responseCallback([
      {
        metadata: ev.metadata,
        error: new Error(reason)
      }
    ]);
  }

  sendEvent(ev) {
    // bail early if we aren't sampling this event
    if (!this._shouldSendEvent(ev)) {
      this._droppedCallback(ev, "event dropped due to sampling");
      return;
    }

    this.sendPresampledEvent(ev);
  }

  sendPresampledEvent(ev) {
    if (this._eventQueue.length >= this._pendingWorkCapacity) {
      this._droppedCallback(ev, "queue overflow");
      return;
    }
    this._eventQueue.push(ev);
    if (this._eventQueue.length >= this._batchSizeTrigger) {
      this._sendBatch();
    } else {
      this._ensureSendTimeout();
    }
  }

  flush() {
    if (this._eventQueue.length === 0 && this._batchCount === 0) {
      // we're not currently waiting on anything, we're done!
      return Promise.resolve();
    }

    return new Promise(resolve => {
      this.flushCallback = () => {
        this.flushCallback = null;
        resolve();
      };
    });
  }

  _sendBatch() {
    if (this._batchCount === maxConcurrentBatches) {
      // don't start up another concurrent batch.  the next timeout/sendEvent or batch completion
      // will cause us to send another
      return;
    }

    this._clearSendTimeout();

    this._batchCount++;

    let batchAgg = new BatchEndpointAggregator(
      this._eventQueue.splice(0, this._batchSizeTrigger)
    );

    const finishBatch = () => {
      this._batchCount--;

      let queueLength = this._eventQueue.length;
      if (queueLength > 0) {
        if (queueLength >= this._batchSizeTrigger) {
          this._sendBatch();
        } else {
          this._ensureSendTimeout();
        }
        return;
      }

      if (this._batchCount === 0 && this.flushCallback) {
        this.flushCallback();
      }
    };

    let batches = Object.keys(batchAgg.batches).map(k => batchAgg.batches[k]);
    eachPromise(batches, batch => {
      let url = urljoin(batch.apiHost, "/1/batch", batch.dataset);
      let postReq = superagent.post(url);

      let reqPromise;
      if (process.env.LIBHONEY_TARGET === "browser") {
        reqPromise = Promise.resolve({ req: postReq });
      } else {
        reqPromise = Promise.resolve(
          this._proxy
            ? import("superagent-proxy").then(({ default: proxy }) => ({
                req: proxy(postReq, this._proxy)
              }))
            : { req: postReq }
        );
      }
      let { encoded, numEncoded } = batchAgg.encodeBatchEvents(batch.events);
      return reqPromise.then(
        ({ req }) =>
          new Promise(resolve => {
            // if we failed to encode any of the events, no point in sending anything to honeycomb
            if (numEncoded === 0) {
              this._responseCallback(
                batch.events.map(ev => ({
                  metadata: ev.metadata,
                  error: ev.encodeError
                }))
              );
              resolve();
              return;
            }

            let userAgent = USER_AGENT;
            let trimmedAddition = this._userAgentAddition.trim();
            if (trimmedAddition) {
              userAgent = `${USER_AGENT} ${trimmedAddition}`;
            }

            let start = Date.now();
            req
              .set("X-Honeycomb-Team", batch.writeKey)
              .set(
                process.env.LIBHONEY_TARGET === "browser"
                  ? "X-Honeycomb-UserAgent"
                  : "User-Agent",
                userAgent
              )
              .type("json")
              .timeout(this._timeout)
              .send(encoded)
              .end((err, res) => {
                let end = Date.now();

                if (err) {
                  this._responseCallback(
                    batch.events.map(ev => ({
                      // eslint-disable-next-line camelcase
                      status_code: ev.encodeError ? undefined : err.status,
                      duration: end - start,
                      metadata: ev.metadata,
                      error: ev.encodeError || err
                    }))
                  );
                } else {
                  let response = JSON.parse(res.text);
                  let respIdx = 0;
                  this._responseCallback(
                    batch.events.map(ev => {
                      if (ev.encodeError) {
                        return {
                          duration: end - start,
                          metadata: ev.metadata,
                          error: ev.encodeError
                        };
                      } else {
                        let nextResponse = response[respIdx++];
                        return {
                          // eslint-disable-next-line camelcase
                          status_code: nextResponse.status,
                          duration: end - start,
                          metadata: ev.metadata,
                          error: nextResponse.err
                        };
                      }
                    })
                  );
                }
                // we resolve unconditionally to continue the iteration in eachSeries.  errors will cause
                // the event to be re-enqueued/dropped.
                resolve();
              });
          })
      );
    })
      .then(finishBatch)
      .catch(finishBatch);
  }

  _shouldSendEvent(ev) {
    let { sampleRate } = ev;
    if (sampleRate <= 1) {
      return true;
    }
    return this._randomFn() < 1 / sampleRate;
  }

  _ensureSendTimeout() {
    if (this._sendTimeoutId === -1) {
      this._sendTimeoutId = _global.setTimeout(
        () => this._sendBatch(),
        this._batchTimeTrigger
      );
    }
  }

  _clearSendTimeout() {
    if (this._sendTimeoutId !== -1) {
      _global.clearTimeout(this._sendTimeoutId);
      this._sendTimeoutId = -1;
    }
  }
}
<commit_msg>Use doc comment for WriterTransmission deprecation (#92)<commit_after>// Copyright 2016 Hound Technology, Inc. All rights reserved.
// Use of this source code is governed by the Apache License 2.0
// license that can be found in the LICENSE file.

/* global global, process */

/**
 * @module
 */
import superagent from "superagent";
import urljoin from "urljoin";

const USER_AGENT = "libhoney-js/<@LIBHONEY_JS_VERSION@>";

const _global =
  typeof window !== "undefined"
    ? window
    : typeof global !== "undefined"
    ? global
    : undefined;

// how many events to collect in a batch
const batchSizeTrigger = 50; // either when the eventQueue is > this length
const batchTimeTrigger = 100; // or it's been more than this many ms since the first push

// how many batches to maintain in parallel
const maxConcurrentBatches = 10;

// how many events to queue up for busy batches before we start dropping
const pendingWorkCapacity = 10000;

// how long (in ms) to give a single POST before we timeout
const deadlineTimeoutMs = 60000;

const emptyResponseCallback = function() {};

const eachPromise = (arr, iteratorFn) =>
  arr.reduce((p, item) => {
    return p.then(() => {
      return iteratorFn(item);
    });
  }, Promise.resolve());

const partition = (arr, keyfn, createfn, addfn) => {
  let result = Object.create(null);
  arr.forEach(v => {
    let key = keyfn(v);
    if (!result[key]) {
      result[key] = createfn(v);
    } else {
      addfn(result[key], v);
    }
  });
  return result;
};

class BatchEndpointAggregator {
  constructor(events) {
    this.batches = partition(
      events,
      /* keyfn */
      ev => `${ev.apiHost}_${ev.writeKey}_${ev.dataset}`,
      /* createfn */
      ev => ({
        apiHost: ev.apiHost,
        writeKey: ev.writeKey,
        dataset: ev.dataset,
        events: [ev]
      }),
      /* addfn */
      (batch, ev) => batch.events.push(ev)
    );
  }

  encodeBatchEvents(events) {
    let first = true;
    let numEncoded = 0;
    let encodedEvents = events.reduce((acc, ev) => {
      try {
        let encodedEvent = JSON.stringify(ev);
        numEncoded++;
        let newAcc = acc + (!first ? "," : "") + encodedEvent;
        first = false;
        return newAcc;
      } catch (e) {
        ev.encodeError = e;
        return acc;
      }
    }, "");

    let encoded = "[" + encodedEvents + "]";
    return { encoded, numEncoded };
  }
}

/**
 * @private
 */
export class ValidatedEvent {
  constructor({
    timestamp,
    apiHost,
    postData,
    writeKey,
    dataset,
    sampleRate,
    metadata
  }) {
    this.timestamp = timestamp;
    this.apiHost = apiHost;
    this.postData = postData;
    this.writeKey = writeKey;
    this.dataset = dataset;
    this.sampleRate = sampleRate;
    this.metadata = metadata;
  }

  toJSON() {
    let json = {};
    if (this.timestamp) {
      json.time = this.timestamp;
    }
    if (this.sampleRate) {
      json.samplerate = this.sampleRate;
    }
    if (this.postData) {
      json.data = this.postData;
    }
    return json;
  }

  /** @deprecated Used by the deprecated WriterTransmission. Use ConsoleTransmission instead. */
  toBrokenJSON() {
    let fields = [];
    if (this.timestamp) {
      fields.push(`"time":${JSON.stringify(this.timestamp)}`);
    }
    if (this.sampleRate) {
      fields.push(`"samplerate":${JSON.stringify(this.sampleRate)}`);
    }
    if (this.postData) {
      fields.push(`"data":${JSON.stringify(this.postData)}`);
    }
    return `{${fields.join(",")}}`;
  }
}

export class MockTransmission {
  constructor(options) {
    this.constructorArg = options;
    this.events = [];
  }

  sendEvent(ev) {
    this.events.push(ev);
  }

  sendPresampledEvent(ev) {
    this.events.push(ev);
  }

  reset() {
    this.constructorArg = null;
    this.events = [];
  }
}

/** @deprecated Use ConsoleTransmission instead. */
export class WriterTransmission {
  sendEvent(ev) {
    console.log(JSON.stringify(ev.toBrokenJSON()));
  }

  sendPresampledEvent(ev) {
    console.log(JSON.stringify(ev.toBrokenJSON()));
  }
}

export class ConsoleTransmission {
  sendEvent(ev) {
    console.log(JSON.stringify(ev));
  }

  sendPresampledEvent(ev) {
    console.log(JSON.stringify(ev));
  }
}

export class NullTransmission {
  sendEvent(_ev) {}

  sendPresampledEvent(_ev) {}
}

/**
 * @private
 */
export class Transmission {
  constructor(options) {
    this._responseCallback = emptyResponseCallback;
    this._batchSizeTrigger = batchSizeTrigger;
    this._batchTimeTrigger = batchTimeTrigger;
    this._maxConcurrentBatches = maxConcurrentBatches;
    this._pendingWorkCapacity = pendingWorkCapacity;
    this._timeout = deadlineTimeoutMs;
    this._sendTimeoutId = -1;
    this._eventQueue = [];
    this._batchCount = 0;

    if (typeof options.responseCallback === "function") {
      this._responseCallback = options.responseCallback;
    }
    if (typeof options.batchSizeTrigger === "number") {
      this._batchSizeTrigger = Math.max(options.batchSizeTrigger, 1);
    }
    if (typeof options.batchTimeTrigger === "number") {
      this._batchTimeTrigger = options.batchTimeTrigger;
    }
    if (typeof options.maxConcurrentBatches === "number") {
      this._maxConcurrentBatches = options.maxConcurrentBatches;
    }
    if (typeof options.pendingWorkCapacity === "number") {
      this._pendingWorkCapacity = options.pendingWorkCapacity;
    }
    if (typeof options.timeout === "number") {
      this._timeout = options.timeout;
    }

    this._userAgentAddition = options.userAgentAddition || "";
    this._proxy = options.proxy;

    // Included for testing; to stub out randomness and verify that an event
    // was dropped.
    this._randomFn = Math.random;
  }

  _droppedCallback(ev, reason) {
    this._responseCallback([
      {
        metadata: ev.metadata,
        error: new Error(reason)
      }
    ]);
  }

  sendEvent(ev) {
    // bail early if we aren't sampling this event
    if (!this._shouldSendEvent(ev)) {
      this._droppedCallback(ev, "event dropped due to sampling");
      return;
    }

    this.sendPresampledEvent(ev);
  }

  sendPresampledEvent(ev) {
    if (this._eventQueue.length >= this._pendingWorkCapacity) {
      this._droppedCallback(ev, "queue overflow");
      return;
    }
    this._eventQueue.push(ev);
    if (this._eventQueue.length >= this._batchSizeTrigger) {
      this._sendBatch();
    } else {
      this._ensureSendTimeout();
    }
  }

  flush() {
    if (this._eventQueue.length === 0 && this._batchCount === 0) {
      // we're not currently waiting on anything, we're done!
      return Promise.resolve();
    }

    return new Promise(resolve => {
      this.flushCallback = () => {
        this.flushCallback = null;
        resolve();
      };
    });
  }

  _sendBatch() {
    if (this._batchCount === maxConcurrentBatches) {
      // don't start up another concurrent batch.  the next timeout/sendEvent or batch completion
      // will cause us to send another
      return;
    }

    this._clearSendTimeout();

    this._batchCount++;

    let batchAgg = new BatchEndpointAggregator(
      this._eventQueue.splice(0, this._batchSizeTrigger)
    );

    const finishBatch = () => {
      this._batchCount--;

      let queueLength = this._eventQueue.length;
      if (queueLength > 0) {
        if (queueLength >= this._batchSizeTrigger) {
          this._sendBatch();
        } else {
          this._ensureSendTimeout();
        }
        return;
      }

      if (this._batchCount === 0 && this.flushCallback) {
        this.flushCallback();
      }
    };

    let batches = Object.keys(batchAgg.batches).map(k => batchAgg.batches[k]);
    eachPromise(batches, batch => {
      let url = urljoin(batch.apiHost, "/1/batch", batch.dataset);
      let postReq = superagent.post(url);

      let reqPromise;
      if (process.env.LIBHONEY_TARGET === "browser") {
        reqPromise = Promise.resolve({ req: postReq });
      } else {
        reqPromise = Promise.resolve(
          this._proxy
            ? import("superagent-proxy").then(({ default: proxy }) => ({
                req: proxy(postReq, this._proxy)
              }))
            : { req: postReq }
        );
      }
      let { encoded, numEncoded } = batchAgg.encodeBatchEvents(batch.events);
      return reqPromise.then(
        ({ req }) =>
          new Promise(resolve => {
            // if we failed to encode any of the events, no point in sending anything to honeycomb
            if (numEncoded === 0) {
              this._responseCallback(
                batch.events.map(ev => ({
                  metadata: ev.metadata,
                  error: ev.encodeError
                }))
              );
              resolve();
              return;
            }

            let userAgent = USER_AGENT;
            let trimmedAddition = this._userAgentAddition.trim();
            if (trimmedAddition) {
              userAgent = `${USER_AGENT} ${trimmedAddition}`;
            }

            let start = Date.now();
            req
              .set("X-Honeycomb-Team", batch.writeKey)
              .set(
                process.env.LIBHONEY_TARGET === "browser"
                  ? "X-Honeycomb-UserAgent"
                  : "User-Agent",
                userAgent
              )
              .type("json")
              .timeout(this._timeout)
              .send(encoded)
              .end((err, res) => {
                let end = Date.now();

                if (err) {
                  this._responseCallback(
                    batch.events.map(ev => ({
                      // eslint-disable-next-line camelcase
                      status_code: ev.encodeError ? undefined : err.status,
                      duration: end - start,
                      metadata: ev.metadata,
                      error: ev.encodeError || err
                    }))
                  );
                } else {
                  let response = JSON.parse(res.text);
                  let respIdx = 0;
                  this._responseCallback(
                    batch.events.map(ev => {
                      if (ev.encodeError) {
                        return {
                          duration: end - start,
                          metadata: ev.metadata,
                          error: ev.encodeError
                        };
                      } else {
                        let nextResponse = response[respIdx++];
                        return {
                          // eslint-disable-next-line camelcase
                          status_code: nextResponse.status,
                          duration: end - start,
                          metadata: ev.metadata,
                          error: nextResponse.err
                        };
                      }
                    })
                  );
                }
                // we resolve unconditionally to continue the iteration in eachSeries.  errors will cause
                // the event to be re-enqueued/dropped.
                resolve();
              });
          })
      );
    })
      .then(finishBatch)
      .catch(finishBatch);
  }

  _shouldSendEvent(ev) {
    let { sampleRate } = ev;
    if (sampleRate <= 1) {
      return true;
    }
    return this._randomFn() < 1 / sampleRate;
  }

  _ensureSendTimeout() {
    if (this._sendTimeoutId === -1) {
      this._sendTimeoutId = _global.setTimeout(
        () => this._sendBatch(),
        this._batchTimeTrigger
      );
    }
  }

  _clearSendTimeout() {
    if (this._sendTimeoutId !== -1) {
      _global.clearTimeout(this._sendTimeoutId);
      this._sendTimeoutId = -1;
    }
  }
}
<|endoftext|>


<commit_before>define(function () {
	var commentRegExp = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,
		cjsRequireRegExp = /require\(["']([^'"\s]+)["']\)/g;

	return {
		load: function (target, require, load) {
			// fetch the raw text
			require(['text!' + target + '.js'], function (source) {
				// start with the "standard" dependencies
				var deps = ['require', 'exports', 'module'];

				// scan the source for other dependencies
				source.replace(commentRegExp, '').replace(cjsRequireRegExp, function (match, dep) {
					deps.push('cjs!' + dep);
				});

				// simulate injecting the wrapped source
				load.fromText('cjs!' + target, "define(['" + deps.join("','") + "'],function (req, exports, module) {" +
					"function require(id) {" +
						"return req('cjs!'+ id);" +
					"}" +
					source +
				'});\n//@ sourceURL=' + require.toUrl(target));

				// get the module we just defined and return it via load
				require(['cjs!' + target], load);
			});
		}
	};
});
<commit_msg>add code to prevent sourceURL trick in IE with conditional comments. thanks @jrburke<commit_after>define(function () {
	var commentRegExp = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,
		cjsRequireRegExp = /require\(["']([^'"\s]+)["']\)/g;

	return {
		load: function (target, require, load) {
			// fetch the raw text
			require(['text!' + target + '.js'], function (source) {
				// start with the "standard" dependencies
				var deps = ['require', 'exports', 'module'],
					wrapped;

				// scan the source for other dependencies
				source.replace(commentRegExp, '').replace(cjsRequireRegExp, function (match, dep) {
					deps.push('cjs!' + dep);
				});

				wrapped = "define(['" + deps.join("','") + "'],function (req, exports, module) {" +
					"function require(id) {" +
						"return req('cjs!'+ id);" +
					"}" +
					source +
				'});';

				// workaround IE conditional comments
				/*@if (@_jscript) @else @*/
				wrapped += '\n//@ sourceURL=' + require.toUrl(target);
				/*@end@*/

				// simulate injecting the wrapped source
				load.fromText('cjs!' + target, wrapped);

				// get the module we just defined and return it via load
				require(['cjs!' + target], load);
			});
		}
	};
});
<|endoftext|>