<commit_before>define([
	'dojo/_base/declare',
	'dijit/_WidgetBase',
	'dijit/_TemplatedMixin',
	'dijit/_WidgetsInTemplateMixin',
	'dijit/form/Button',
	'dojo/_base/lang',
	'dojo/_base/Color',
	'esri/toolbars/draw',
	'esri/layers/GraphicsLayer',
	'esri/graphic',
	'esri/renderers/SimpleRenderer',
	'dojo/text!./Draw/templates/Draw.html',
	'esri/renderers/UniqueValueRenderer',
	'esri/symbols/SimpleMarkerSymbol',
	'esri/symbols/SimpleLineSymbol',
	'esri/symbols/SimpleFillSymbol',
	'esri/layers/FeatureLayer',
	'dojo/topic',
	'dojo/aspect',
	'gis/dijit/_FloatingWidgetMixin',
	'xstyle/css!./Draw/css/Draw.css'
], function(declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Button, lang, Color, Draw, GraphicsLayer, Graphic, SimpleRenderer, drawTemplate, UniqueValueRenderer, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, FeatureLayer, topic, aspect, _FloatingWidgetMixin, css) {

	// main draw dijit
	return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _FloatingWidgetMixin], {
		widgetsInTemplate: true,
		templateString: drawTemplate,
		drawToolbar: null,
		graphics: null,
		mapClickMode: null,
		postCreate: function() {
			this.inherited(arguments);
			this.drawToolbar = new Draw(this.map);

			this.pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 1), new Color([255, 0, 0, 1.0]));

			this.polylineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASH, new Color([255, 0, 0]), 1);

			this.polygonSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.0]));

			this.pointGraphics = new GraphicsLayer({
				id: 'drawGraphics_point',
				title: 'Draw Graphics'
			});
			this.pointRenderer = new SimpleRenderer(this.pointSymbol);
			this.pointRenderer.label = 'User drawn points';
			this.pointRenderer.description = 'User drawn points';
			this.pointGraphics.setRenderer(this.pointRenderer);
			this.map.addLayer(this.pointGraphics);

			this.polylineGraphics = new GraphicsLayer({
				id: 'drawGraphics_line',
				title: 'Draw Graphics'
			});
			this.polylineRenderer = new SimpleRenderer(this.polylineSymbol);
			this.polylineRenderer.label = 'User drawn lines';
			this.polylineRenderer.description = 'User drawn lines';
			this.polylineGraphics.setRenderer(this.polylineRenderer);
			this.map.addLayer(this.polylineGraphics);

			this.polygonGraphics = new FeatureLayer({
				layerDefinition: {
					geometryType: 'esriGeometryPolygon',
					fields: [{
						name: 'OBJECTID',
						type: 'esriFieldTypeOID',
						alias: 'OBJECTID',
						domain: null,
						editable: false,
						nullable: false
					}, {
						name: 'ren',
						type: 'esriFieldTypeInteger',
						alias: 'ren',
						domain: null,
						editable: true,
						nullable: false
					}]
				},
				featureSet: null
			}, {
				id: 'drawGraphics_poly',
				title: 'Draw Graphics',
				mode: FeatureLayer.MODE_SNAPSHOT
			});
			//this.polygonRenderer = new SimpleRenderer(this.polygonSymbol);
			this.polygonRenderer = new UniqueValueRenderer(new SimpleFillSymbol(), 'ren', null, null, ', ');
			this.polygonRenderer.addValue({
				value: 1,
				symbol: new SimpleFillSymbol({
					color: [
						255,
						170,
						0,
						255
					],
					outline: {
						color: [
							255,
							170,
							0,
							255
						],
						width: 1,
						type: 'esriSLS',
						style: 'esriSLSSolid'
					},
					type: 'esriSFS',
					style: 'esriSFSForwardDiagonal'
				}),
				label: 'User drawn polygons',
				description: 'User drawn polygons'
			});
			//this.polygonRenderer.label = 'User drawn polygons';
			//this.polygonRenderer.description = 'User drawn polygons';
			this.polygonGraphics.setRenderer(this.polygonRenderer);
			this.map.addLayer(this.polygonGraphics);

			this.own(topic.subscribe('mapClickMode/currentSet', lang.hitch(this, 'setMapClickMode')));
			if (this.parentWidget && this.parentWidget.toggleable) {
				this.own(aspect.after(this.parentWidget, 'toggle', lang.hitch(this, function() {
					this.onLayoutChange(this.parentWidget.open);
				})));
			}
			this.drawToolbar.on('draw-end', lang.hitch(this, 'onDrawToolbarDrawEnd'));
		},
		drawPoint: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.POINT);
		},
		drawCircle: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.CIRCLE);
		},
		drawLine: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.POLYLINE);
		},
		drawFreehandLine: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.FREEHAND_POLYLINE);
		},
		drawPolygon: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.POLYGON);
		},
		drawFreehandPolygon: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.FREEHAND_POLYGON);
		},
		disconnectMapClick: function() {
			topic.publish('mapClickMode/setCurrent', 'draw');
			// dojo.disconnect(this.mapClickEventHandle);
			// this.mapClickEventHandle = null;
		},
		connectMapClick: function() {
			topic.publish('mapClickMode/setDefault');
			// if (this.mapClickEventHandle === null) {
			//     this.mapClickEventHandle = dojo.connect(this.map, 'onClick', this.mapClickEventListener);
			// }
		},
		onDrawToolbarDrawEnd: function(evt) {
			this.drawToolbar.deactivate();
			this.connectMapClick();
			var graphic;
			switch (evt.geometry.type) {
				case 'point':
					graphic = new Graphic(evt.geometry);
					this.pointGraphics.add(graphic);
					break;
				case 'polyline':
					graphic = new Graphic(evt.geometry);
					this.polylineGraphics.add(graphic);
					break;
				case 'polygon':
					graphic = new Graphic(evt.geometry, null, {
						ren: 1
					});
					this.polygonGraphics.add(graphic);
					break;
				default:
			}
		},
		clearGraphics: function () {
			this.endDrawing();
			this.connectMapClick();
		},
		endDrawing: function() {
			this.pointGraphics.clear();
			this.polylineGraphics.clear();
			this.polygonGraphics.clear();
			this.drawToolbar.deactivate();
		},
	  	onLayoutChange: function (open) {
	  		// end drawing on close of title pane
			if (!open) {
				this.endDrawing();
				if (this.mapClickMode === 'draw') {
					topic.publish('mapClickMode/setDefault');
				}
			}
	  	},
		setMapClickMode: function (mode) {
			this.mapClickMode = mode;
		}
	});
});
<commit_msg>remove unused vars.<commit_after>define([
	'dojo/_base/declare',
	'dijit/_WidgetBase',
	'dijit/_TemplatedMixin',
	'dijit/_WidgetsInTemplateMixin',
	'dojo/_base/lang',
	'dojo/_base/Color',
	'esri/toolbars/draw',
	'esri/layers/GraphicsLayer',
	'esri/graphic',
	'esri/renderers/SimpleRenderer',
	'dojo/text!./Draw/templates/Draw.html',
	'esri/renderers/UniqueValueRenderer',
	'esri/symbols/SimpleMarkerSymbol',
	'esri/symbols/SimpleLineSymbol',
	'esri/symbols/SimpleFillSymbol',
	'esri/layers/FeatureLayer',
	'dojo/topic',
	'dojo/aspect',
	'dijit/form/Button',
	'xstyle/css!./Draw/css/Draw.css'
], function(declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, lang, Color, Draw, GraphicsLayer, Graphic, SimpleRenderer, drawTemplate, UniqueValueRenderer, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, FeatureLayer, topic, aspect) {

	// main draw dijit
	return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
		widgetsInTemplate: true,
		templateString: drawTemplate,
		drawToolbar: null,
		graphics: null,
		mapClickMode: null,
		postCreate: function() {
			this.inherited(arguments);
			this.drawToolbar = new Draw(this.map);

			this.pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 1), new Color([255, 0, 0, 1.0]));

			this.polylineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASH, new Color([255, 0, 0]), 1);

			this.polygonSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.0]));

			this.pointGraphics = new GraphicsLayer({
				id: 'drawGraphics_point',
				title: 'Draw Graphics'
			});
			this.pointRenderer = new SimpleRenderer(this.pointSymbol);
			this.pointRenderer.label = 'User drawn points';
			this.pointRenderer.description = 'User drawn points';
			this.pointGraphics.setRenderer(this.pointRenderer);
			this.map.addLayer(this.pointGraphics);

			this.polylineGraphics = new GraphicsLayer({
				id: 'drawGraphics_line',
				title: 'Draw Graphics'
			});
			this.polylineRenderer = new SimpleRenderer(this.polylineSymbol);
			this.polylineRenderer.label = 'User drawn lines';
			this.polylineRenderer.description = 'User drawn lines';
			this.polylineGraphics.setRenderer(this.polylineRenderer);
			this.map.addLayer(this.polylineGraphics);

			this.polygonGraphics = new FeatureLayer({
				layerDefinition: {
					geometryType: 'esriGeometryPolygon',
					fields: [{
						name: 'OBJECTID',
						type: 'esriFieldTypeOID',
						alias: 'OBJECTID',
						domain: null,
						editable: false,
						nullable: false
					}, {
						name: 'ren',
						type: 'esriFieldTypeInteger',
						alias: 'ren',
						domain: null,
						editable: true,
						nullable: false
					}]
				},
				featureSet: null
			}, {
				id: 'drawGraphics_poly',
				title: 'Draw Graphics',
				mode: FeatureLayer.MODE_SNAPSHOT
			});
			//this.polygonRenderer = new SimpleRenderer(this.polygonSymbol);
			this.polygonRenderer = new UniqueValueRenderer(new SimpleFillSymbol(), 'ren', null, null, ', ');
			this.polygonRenderer.addValue({
				value: 1,
				symbol: new SimpleFillSymbol({
					color: [
						255,
						170,
						0,
						255
					],
					outline: {
						color: [
							255,
							170,
							0,
							255
						],
						width: 1,
						type: 'esriSLS',
						style: 'esriSLSSolid'
					},
					type: 'esriSFS',
					style: 'esriSFSForwardDiagonal'
				}),
				label: 'User drawn polygons',
				description: 'User drawn polygons'
			});
			//this.polygonRenderer.label = 'User drawn polygons';
			//this.polygonRenderer.description = 'User drawn polygons';
			this.polygonGraphics.setRenderer(this.polygonRenderer);
			this.map.addLayer(this.polygonGraphics);

			this.own(topic.subscribe('mapClickMode/currentSet', lang.hitch(this, 'setMapClickMode')));
			if (this.parentWidget && this.parentWidget.toggleable) {
				this.own(aspect.after(this.parentWidget, 'toggle', lang.hitch(this, function() {
					this.onLayoutChange(this.parentWidget.open);
				})));
			}
			this.drawToolbar.on('draw-end', lang.hitch(this, 'onDrawToolbarDrawEnd'));
		},
		drawPoint: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.POINT);
		},
		drawCircle: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.CIRCLE);
		},
		drawLine: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.POLYLINE);
		},
		drawFreehandLine: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.FREEHAND_POLYLINE);
		},
		drawPolygon: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.POLYGON);
		},
		drawFreehandPolygon: function() {
			this.disconnectMapClick();
			this.drawToolbar.activate(Draw.FREEHAND_POLYGON);
		},
		disconnectMapClick: function() {
			topic.publish('mapClickMode/setCurrent', 'draw');
			// dojo.disconnect(this.mapClickEventHandle);
			// this.mapClickEventHandle = null;
		},
		connectMapClick: function() {
			topic.publish('mapClickMode/setDefault');
			// if (this.mapClickEventHandle === null) {
			//     this.mapClickEventHandle = dojo.connect(this.map, 'onClick', this.mapClickEventListener);
			// }
		},
		onDrawToolbarDrawEnd: function(evt) {
			this.drawToolbar.deactivate();
			this.connectMapClick();
			var graphic;
			switch (evt.geometry.type) {
				case 'point':
					graphic = new Graphic(evt.geometry);
					this.pointGraphics.add(graphic);
					break;
				case 'polyline':
					graphic = new Graphic(evt.geometry);
					this.polylineGraphics.add(graphic);
					break;
				case 'polygon':
					graphic = new Graphic(evt.geometry, null, {
						ren: 1
					});
					this.polygonGraphics.add(graphic);
					break;
				default:
			}
		},
		clearGraphics: function () {
			this.endDrawing();
			this.connectMapClick();
		},
		endDrawing: function() {
			this.pointGraphics.clear();
			this.polylineGraphics.clear();
			this.polygonGraphics.clear();
			this.drawToolbar.deactivate();
		},
	  	onLayoutChange: function (open) {
	  		// end drawing on close of title pane
			if (!open) {
				this.endDrawing();
				if (this.mapClickMode === 'draw') {
					topic.publish('mapClickMode/setDefault');
				}
			}
	  	},
		setMapClickMode: function (mode) {
			this.mapClickMode = mode;
		}
	});
});
<|endoftext|>


<commit_before><commit_msg>geo<commit_after><|endoftext|>


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

/* Copyright 2012, Jonathan Cheung Licensed and released under the MIT
   license. Refer to MIT-LICENSE.txt.

   A nodejs script that allows you to watch a folder for changes and
   compile the less css files into another folder.

   Always give credit where it's due. Parts of this script is modified
   from Mikeal Rogers's watch script (https://github.com/mikeal/watch)

   Usage:     node less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT
   Example:   'node less-watch-compiler.js less css' will watch ./less folder
              and compile the less css files into ./css when they are added/changed
*/
var sys = require('util')
  , fs = require('fs')
  , path = require('path')
  , events = require('events')
  , exec = require('child_process').exec
  , data = fs.readFileSync('config.json')
  , config = {};

// Check if we could load config.json
try {
  config = JSON.parse(data);
}
catch (err) {
  console.log('There was an error parsing config.json.')
  console.log(err);
}
// Check to see if we have the correct number of arguments
var argvs = process.argv.slice(2);
var watchFolder, outputFolder;
try{
  watchFolder = argvs[0] || config.defaults.watchFolder;
  outputFolder = argvs[1] || config.defaults.outputFolder;
}
catch(e){}

// console.log(watchFolder)
// console.log(outputFolder)
if ( !watchFolder || !outputFolder ){
  console.log('Missing arguments. Example:');
  console.log('\tnode less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT');
  console.log('\tExample 1: To watch all files under the folder "less" and compile all into a folder "css".');
  console.log('\t\t node less-watch-compiler.js less css');
  process.exit(1);
}

// Walk the directory tree
function walk (dir, options, callback, initCallback) {
  if (!callback) {callback = options; options = {}}
  if (!callback.files) callback.files = {};
  if (!callback.pending) callback.pending = 0;
  callback.pending += 1;
  fs.stat(dir, function (err, stat) {
    if (err) return callback(err);
    callback.files[dir] = stat;
    fs.readdir(dir, function (err, files) {
      if (err) return callback(err);
      callback.pending -= 1;
      files.forEach(function (f, index) {
        f = path.join(dir, f);
        callback.pending += 1;
        fs.stat(f, function (err, stat) {
          var enoent = false
            , done = false;

          if (err) {
            if (err.code !== 'ENOENT') {
              return callback(err);
            } else {
              enoent = true;
            }
          }
          callback.pending -= 1;
          done = callback.pending === 0;
          if (!enoent) {
            if (options.ignoreDotFiles && path.basename(f)[0] === '.') return done && callback(null, callback.files);
            if (options.filter && options.filter(f, stat)) return done && callback(null, callback.files);
            callback.files[f] = stat;
            if (stat.isDirectory()) {
              walk(f, options, callback);
            }else{
              initCallback&&initCallback(f);
            }

            if (done) callback(null, callback.files);
          }
        })
      })
      if (callback.pending === 0) callback(null, callback.files);
    })
    if (callback.pending === 0) callback(null, callback.files);
  })

}

//Setup fs.watchFile() for each file.
var watchTree = function ( root, options, watchCallback, initCallback ) {
  if (!watchCallback) {watchCallback = options; options = {}}
  walk(root, options, function (err, files) {
    if (err) throw err;
    var fileWatcher = function (f) {
      fs.watchFile(f, options, function (c, p) {
        // Check if anything actually changed in stat
        if (files[f] && !files[f].isDirectory() && c.nlink !== 0 && files[f].mtime.getTime() == c.mtime.getTime()) return;
        files[f] = c;
        if (!files[f].isDirectory()) {
          if(options.ignoreDotFiles && (path.basename(f)[0] === '.')) return;
          if(options.filter&& options.filter(f, files[f])) return;
          watchCallback(f, c, p);
        }else {
          fs.readdir(f, function (err, nfiles) {
            if (err) return;
            nfiles.forEach(function (b) {
              var file = path.join(f, b);
              if (!files[file]) {
                fs.stat(file, function (err, stat) {
                  if(options.ignoreDotFiles && (path.basename(b)[0] === '.')) return;
                  if(options.filter&& options.filter(b, files[b])) return;
                  watchCallback(file, stat, null);
                  files[file] = stat;
                  fileWatcher(file);
                })
              }
            })
          })
        }
        if (c.nlink === 0) {
          // unwatch removed files.
          delete files[f]
          fs.unwatchFile(f);
        }
      })
    }

    fileWatcher(root);
    for (var i in files) {
      fileWatcher(i);
    }
    watchCallback(files, null, null);
  },
  initCallback);
}

// String function to retrieve the filename without the extension
function getFilenameWithoutExtention(string){
  //extract filename (xxx.less)
  //strip out the extension
  var filename = string.replace(/^.*[\\\/]/, '').split('.')[0];
  return filename
}

// String function to retrieve the file's extension
function getFileExtension(string){
  var extension = string.split('.').pop();
  if (extension == string) return ''
  else
  return extension;
}

// Here's where we run the less compiler
function compileCSS(file){
    var filename = getFilenameWithoutExtention(file);
    var command = 'lessc -x '+file.replace(/\s+/g,'\\ ')+' '+outputFolder+'/'+filename.replace(/\s+/g,'\\ ')+'.css';
    // Run the command
    exec(command, function (error, stdout, stderr){
      if (error !== null)
        console.log(error);
      if(stdout)
          console.error(stdout);
  });
}

// This is the function we use to filter the files to watch.
function filterFiles(f, stat){
  var filename = getFilenameWithoutExtention(f);
  var extension = getFileExtension(f);
  if (filename.substr(0,1) == '_' ||
      filename.substr(0,1) == '.' ||
      filename == '' ||
      config.allowedExtensions.indexOf(extension) == -1
      )
    return true;
  else{
    return false;
  }
}

function getDateTime() {

    var date = new Date();
    var hour = date.getHours();
    hour = (hour < 10 ? "0" : "") + hour;
    var min  = date.getMinutes();
    min = (min < 10 ? "0" : "") + min;
    var sec  = date.getSeconds();
    sec = (sec < 10 ? "0" : "") + sec;
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    month = (month < 10 ? "0" : "") + month;
    var day  = date.getDate();
    day = (day < 10 ? "0" : "") + day;
    return hour + ":" + min + ":" + sec + " on " + day + '/' + month + "/" + year;

}

// Here's where we setup the watch function
console.log('Watching directory for file changes.');
console.log('');
watchTree(
  watchFolder,
  {interval: 200, ignoreDotFiles: true, filter:filterFiles},
  function (f, curr, prev) {
    if (typeof f == 'object' && prev === null && curr === null) {
      // Finished walking the tree
      return;
    } else if (curr.nlink === 0) {
      // f was removed
      console.log(f +' was removed.')
    } else {
      // f is a new file or changed
      console.log('The file: ' + f + ' was changed. Recompiling CSS at ' + getDateTime());
      compileCSS(f);
    }
  },
  function(f){
     compileCSS(f);
  }
);
<commit_msg>Fix problem where subdirectories changes were ignored.<commit_after>#!/usr/bin/env node

/* Copyright 2012, Jonathan Cheung Licensed and released under the MIT
   license. Refer to MIT-LICENSE.txt.

   A nodejs script that allows you to watch a folder for changes and
   compile the less css files into another folder.

   Always give credit where it's due. Parts of this script is modified
   from Mikeal Rogers's watch script (https://github.com/mikeal/watch)

   Usage:     node less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT
   Example:   'node less-watch-compiler.js less css' will watch ./less folder
              and compile the less css files into ./css when they are added/changed
*/
var sys = require('util')
  , fs = require('fs')
  , path = require('path')
  , events = require('events')
  , exec = require('child_process').exec
  , data = fs.readFileSync('config.json')
  , config = {};

// Check if we could load config.json
try {
  config = JSON.parse(data);
}
catch (err) {
  console.log('There was an error parsing config.json.')
  console.log(err);
}
// Check to see if we have the correct number of arguments
var argvs = process.argv.slice(2);
var watchFolder, outputFolder;
try{
  watchFolder = argvs[0] || config.defaults.watchFolder;
  outputFolder = argvs[1] || config.defaults.outputFolder;
}
catch(e){}

// console.log(watchFolder)
// console.log(outputFolder)
if ( !watchFolder || !outputFolder ){
  console.log('Missing arguments. Example:');
  console.log('\tnode less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT');
  console.log('\tExample 1: To watch all files under the folder "less" and compile all into a folder "css".');
  console.log('\t\t node less-watch-compiler.js less css');
  process.exit(1);
}

// Walk the directory tree
function walk (dir, options, callback, initCallback) {
  if (!callback) {callback = options; options = {}}
  if (!callback.files) callback.files = {};
  if (!callback.pending) callback.pending = 0;
  callback.pending += 1;
  fs.stat(dir, function (err, stat) {
    if (err) return callback(err);
    callback.files[dir] = stat;
    fs.readdir(dir, function (err, files) {
      if (err) return callback(err);
      callback.pending -= 1;
      files.forEach(function (f, index) {
        f = path.join(dir, f);
        callback.pending += 1;
        fs.stat(f, function (err, stat) {
          var enoent = false
            , done = false;

          if (err) {
            if (err.code !== 'ENOENT') {
              return callback(err);
            } else {
              enoent = true;
            }
          }
          callback.pending -= 1;
          done = callback.pending === 0;
          if (!enoent) {
            callback.files[f] = stat;
            if (stat.isDirectory()) {
              walk(f, options, callback);
            }else{
            if (options.ignoreDotFiles && path.basename(f)[0] === '.') return done && callback(null, callback.files);
            if (options.filter && options.filter(f, stat)) return done && callback(null, callback.files);
              initCallback&&initCallback(f);
            }

            if (done) callback(null, callback.files);
          }
        })
      })
      if (callback.pending === 0) callback(null, callback.files);
    })
    if (callback.pending === 0) callback(null, callback.files);
  })

}

//Setup fs.watchFile() for each file.
var watchTree = function ( root, options, watchCallback, initCallback ) {
  if (!watchCallback) {watchCallback = options; options = {}}
  walk(root, options, function (err, files) {
    if (err) throw err;
    var fileWatcher = function (f) {
      fs.watchFile(f, options, function (c, p) {
        // Check if anything actually changed in stat
        if (files[f] && !files[f].isDirectory() && c.nlink !== 0 && files[f].mtime.getTime() == c.mtime.getTime()) return;
        files[f] = c;
        if (!files[f].isDirectory()) {
          if(options.ignoreDotFiles && (path.basename(f)[0] === '.')) return;
          if(options.filter&& options.filter(f, files[f])) return;
          watchCallback(f, c, p);
        }else {
          fs.readdir(f, function (err, nfiles) {
            if (err) return;
            nfiles.forEach(function (b) {
              var file = path.join(f, b);
              if (!files[file]) {
                fs.stat(file, function (err, stat) {
                  if(options.ignoreDotFiles && (path.basename(b)[0] === '.')) return;
                  if(options.filter&& options.filter(b, files[b])) return;
                  watchCallback(file, stat, null);
                  files[file] = stat;
                  fileWatcher(file);
                })
              }
            })
          })
        }
        if (c.nlink === 0) {
          // unwatch removed files.
          delete files[f]
          fs.unwatchFile(f);
        }
      })
    }

    fileWatcher(root);
    for (var i in files) {
      fileWatcher(i);
    }
    watchCallback(files, null, null);
  },
  initCallback);
}

// String function to retrieve the filename without the extension
function getFilenameWithoutExtention(string){
  //extract filename (xxx.less)
  //strip out the extension
  var filename = string.replace(/^.*[\\\/]/, '').split('.')[0];
  return filename
}

// String function to retrieve the file's extension
function getFileExtension(string){
  var extension = string.split('.').pop();
  if (extension == string) return ''
  else
  return extension;
}

// Here's where we run the less compiler
function compileCSS(file){
    var filename = getFilenameWithoutExtention(file);
    var command = 'lessc -x '+file.replace(/\s+/g,'\\ ')+' '+outputFolder+'/'+filename.replace(/\s+/g,'\\ ')+'.css';
    // Run the command
    exec(command, function (error, stdout, stderr){
      if (error !== null)
        console.log(error);
      if(stdout)
          console.error(stdout);
  });
}

// This is the function we use to filter the files to watch.
function filterFiles(f, stat){
  var filename = getFilenameWithoutExtention(f);
  var extension = getFileExtension(f);
  if (filename.substr(0,1) == '_' ||
      filename.substr(0,1) == '.' ||
      filename == '' ||
      config.allowedExtensions.indexOf(extension) == -1
      )
    return true;
  else{
    return false;
  }
}

function getDateTime() {

    var date = new Date();
    var hour = date.getHours();
    hour = (hour < 10 ? "0" : "") + hour;
    var min  = date.getMinutes();
    min = (min < 10 ? "0" : "") + min;
    var sec  = date.getSeconds();
    sec = (sec < 10 ? "0" : "") + sec;
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    month = (month < 10 ? "0" : "") + month;
    var day  = date.getDate();
    day = (day < 10 ? "0" : "") + day;
    return hour + ":" + min + ":" + sec + " on " + day + '/' + month + "/" + year;

}

// Here's where we setup the watch function
console.log('Watching directory for file changes.');
console.log('');
watchTree(
  watchFolder,
  {interval: 200, ignoreDotFiles: true, filter:filterFiles},
  function (f, curr, prev) {
    if (typeof f == 'object' && prev === null && curr === null) {
      // Finished walking the tree
      return;
    } else if (curr.nlink === 0) {
      // f was removed
      console.log(f +' was removed.')
    } else {
      // f is a new file or changed
      console.log('The file: ' + f + ' was changed. Recompiling CSS at ' + getDateTime());
      compileCSS(f);
    }
  },
  function(f){
     compileCSS(f);
  }
);
<|endoftext|>


<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * for parsing listener attribute : e.g. .click('foo(bar, 12)')
 */

var elenpi = require('elenpi'),
	r = elenpi.r,
	Parser = elenpi.Parser,
	primitiveArguments = require('./primitive-argument-rules');

var rules = {
	path: r()
		.oneOrMore(null, r().regExp(/^[\w-_\$]+/, false, function(descriptor, cap) {
			(descriptor.path = descriptor.path ||  []).push(cap[0]);
		}), r().regExp(/^\./)),

	call: r()
		.rule('path')
		.done(function(string, descriptor) {
			descriptor.method = descriptor.path;
			descriptor.path = null;
			descriptor.arguments = [];
			return string;
		})
		.zeroOrOne(null,
			r()
			.regExp(/^\s*\(\s*/)
			.zeroOrMore(null,
				r().oneOf(['integer', 'float', 'bool', 'singlestring', 'doublestring', r().rule('path')
					.done(function(string, descriptor) {
						descriptor.arguments.push(descriptor.path);
						descriptor.path = null;
						return string;
					})
				]),
				r().regExp(/^\s*,\s*/)
			)
			.regExp(/^\s*\)/)
		)
};

for (var i in primitiveArguments)
	rules[i] = primitiveArguments[i];

var parser = new Parser(rules, 'call');

parser.parseListener = function(string) {
	var parsed = this.parse(string);
	if (!parsed.method)
		throw new Error('yamvish listener badly formatted : ' + string);
	return function(e) {
		var handler = this.get(parsed.method);
		if (!handler)
			throw new Error('yamvish listener not found : ' + string);
		if (!parsed.arguments)
			return handler.call(this, e);
		var args = [e];
		for (var i = 0, len = parsed.arguments.length; i < len; ++i) {
			var arg = parsed.arguments[i];
			args.push(arg.forEach ? this.get(arg) : arg);
		}
		return handler.apply(this, args);
	};
};

module.exports = parser;
<commit_msg>listenerCall : catch parent as call context if needed<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * for parsing listener attribute : e.g. .click('foo(bar, 12)')
 */

var elenpi = require('elenpi'),
	r = elenpi.r,
	Parser = elenpi.Parser,
	primitiveArguments = require('./primitive-argument-rules');

var rules = {
	path: r()
		.oneOrMore(null, r().regExp(/^[\w-_\$]+/, false, function(descriptor, cap) {
			(descriptor.path = descriptor.path ||  []).push(cap[0]);
		}), r().regExp(/^\./)),

	call: r()
		.rule('path')
		.done(function(string, descriptor) {
			descriptor.method = descriptor.path;
			descriptor.path = null;
			descriptor.arguments = [];
			return string;
		})
		.zeroOrOne(null,
			r()
			.regExp(/^\s*\(\s*/)
			.zeroOrMore(null,
				r().oneOf(['integer', 'float', 'bool', 'singlestring', 'doublestring', r().rule('path')
					.done(function(string, descriptor) {
						descriptor.arguments.push(descriptor.path);
						descriptor.path = null;
						return string;
					})
				]),
				r().regExp(/^\s*,\s*/)
			)
			.regExp(/^\s*\)/)
		)
};

for (var i in primitiveArguments)
	rules[i] = primitiveArguments[i];

var parser = new Parser(rules, 'call');

parser.parseListener = function(string) {
	var parsed = this.parse(string);
	if (!parsed.method)
		throw new Error('yamvish listener call badly formatted : ' + string);
	return function(e) {
		var self = this;
		if (parsed.method[0] === '$parent') {
			var count = 0;
			while (self && parsed.method[count] === '$parent') {
				count++;
				self = this.parent;
			}
			if (!self)
				throw new Error('yamvish listener call could not find parent : ' + string);
		}
		var handler = this.get(parsed.method);
		if (!handler)
			throw new Error('yamvish listener not found : ' + string);
		if (!parsed.arguments)
			return handler.call(this, e);
		var args = [e];
		for (var i = 0, len = parsed.arguments.length; i < len; ++i) {
			var arg = parsed.arguments[i];
			args.push(arg.forEach ? this.get(arg) : arg);
		}
		return handler.apply(self, args);
	};
};

module.exports = parser;
<|endoftext|>


<commit_before>/**
 * states.js
 * Created by anonymous on 09/12/15 13:11.
 */

(function() {
    'use strict';

    angular
        .module('dashboard')
        .config(dashboardRouter);

    dashboardRouter.$inject = ['$stateProvider', '$urlRouterProvider', 'layoutProvider'];

    /* @ngInject */
    function dashboardRouter($stateProvider, $urlRouterProvider, layoutProvider) {
        $urlRouterProvider.otherwise('/');

        $stateProvider
            .state('dashboard', {
                abstract: true,
                url     : '/dashboard',
                views   : {
                    'layout@'          : {
                        templateUrl : layoutProvider.layout('minimalist.theme'),
                        controller  : 'DashboardController',
                        controllerAs: 'dashboard'
                    },
                    'header@dashboard' : {
                        templateUrl : layoutProvider.layout('minimalist.header'),
                        controller  : 'HeaderController',
                        controllerAs: 'header'
                    },
                    'sidenav@dashboard': {
                        templateUrl : layoutProvider.layout('minimalist.sidenav'),
                        controller  : 'SidenavController',
                        controllerAs: 'sidenav'
                    },
                    'aside@dashboard'  : {
                        templateUrl : layoutProvider.layout('minimalist.aside'),
                        controller  : 'AsideController',
                        controllerAs: 'aside'
                    },
                    'footer@dashboard' : {
                        templateUrl : layoutProvider.layout('minimalist.footer'),
                        controller  : 'FooterController',
                        controllerAs: 'footer'
                    },
                    'main@dashboard'   : {}
                }
            })
            .state('dashboard.home', {
                url  : '/',
                data : {pageName: 'Overview'},
                views: {

                    'sidenav@dashboard': {
                        templateUrl : layoutProvider.view('dashboard.sidenav'),
                        controller  : 'DashboardSidenavController',
                        controllerAs: 'sidenav'
                    },
                    'main@dashboard'   : {
                        templateUrl : layoutProvider.view('dashboard.home'),
                        controller  : 'DashboardHomeController',
                        controllerAs: 'home'
                    }
                }
            });

    }

})();

<commit_msg>Modified states<commit_after>/**
 * states.js
 * Created by anonymous on 09/12/15 13:11.
 */

(function() {
    'use strict';

    angular
        .module('dashboard')
        .config(dashboardRouter);

    dashboardRouter.$inject = ['$stateProvider', '$urlRouterProvider', 'layoutProvider'];

    /* @ngInject */
    function dashboardRouter($stateProvider, $urlRouterProvider, layoutProvider) {

        $urlRouterProvider.otherwise('/');

        $stateProvider
            .state('dashboard', {
                abstract: true,
                url     : '/dashboard',
                views   : {
                    'layout@'          : {
                        templateUrl : layoutProvider.layout('minimalist.theme'),
                        controller  : 'DashboardController',
                        controllerAs: 'dashboard'
                    },
                    'header@dashboard' : {
                        templateUrl : layoutProvider.layout('minimalist.header'),
                        controller  : 'HeaderController',
                        controllerAs: 'header'
                    },
                    'sidenav@dashboard': {
                        templateUrl : layoutProvider.view('dashboard.sidenav'),
                        controller  : 'DashboardSidenavController',
                        controllerAs: 'sidenav'
                    },
                    'aside@dashboard'  : {
                        templateUrl : layoutProvider.layout('minimalist.aside'),
                        controller  : 'AsideController',
                        controllerAs: 'aside'
                    },
                    'footer@dashboard' : {
                        templateUrl : layoutProvider.layout('minimalist.footer'),
                        controller  : 'FooterController',
                        controllerAs: 'footer'
                    },
                    'main@dashboard'   : {}
                }
            })
            .state('dashboard.home', {
                url  : '/',
                data : {pageName: 'Overview'},
                views: {
                    'main@dashboard'   : {
                        templateUrl : layoutProvider.view('dashboard.home'),
                        controller  : 'DashboardHomeController',
                        controllerAs: 'home'
                    }
                }
            });

    }

})();

<|endoftext|>


<commit_before>if(typeof exports === 'object') {
	var assert = require("assert");
	var alasql = require('..');
	var DOMStorage = require("dom-storage");
	global.localStorage = new DOMStorage("./test381.json", { strict: false, ws: '' });
};

/*
 This sample beased on this article:

	http://stackoverflow.com/questions/30442969/group-by-in-angularjs

*/

describe('Test 385 - Nested Search (issue #495)', function() {

  it('1. CREATE DATABASE',function(done){
    alasql('CREATE DATABASE test385;USE test385');
    done();
  });

	it('2. Create table issue - one statement', function(done){

    // Source data

    var data1 = {
    "_id" : "2mA82CTSeeTrvMxfR",
    "playlists" :
      [
          {
              "name" : "Electro",
              "songs" :
              [
                  {
                      "id" : "dMEwEdkoPLw",
                      "name" : "Moe Shop - You Look So Good",
                      "position" : "1"
                  },
                  {
                      "id" : "S927n1xUkAM",
                      "name" : "Vexento - Magenta",
                      "position" : "2"
                  }
              ]
          }
      ]
    };

    // Result data

    var data2 = {
    "_id" : "2mA82CTSeeTrvMxfR",
    "playlists" :
      [
          {
              "name" : "Electro",
              "songs" :
              [
                  {
                      "id" : "dMEwEdkoPLw",
                      "name" : "Moe Shop - You Look So Good",
                      "position" : "2"
                  },
                  {
                      "id" : "S927n1xUkAM",
                      "name" : "Vexento - Magenta",
                      "position" : "1"
                  }
              ]
          }
      ]
    };

    alasql('SEARCH playlists/songs/WHERE(id=$1) SET(position=$2) FROM $0',[data1,"S927n1xUkAM","1"]);
    alasql('SEARCH playlists/songs/WHERE(id=$1) SET(position=$2) FROM $0',[data1,"dMEwEdkoPLw","2"]);

    assert.deepEqual(data1,data2);
		done();
	});

  it('99. DROP DATABASE',function(done){
    alasql('DROP DATABASE test385');
    done();
  });

});
<commit_msg>Changed test385<commit_after>if(typeof exports === 'object') {
	var assert = require("assert");
	var alasql = require('..');
	var DOMStorage = require("dom-storage");
	global.localStorage = new DOMStorage("./test381.json", { strict: false, ws: '' });
};

/*
 This sample beased on this article:

	http://stackoverflow.com/questions/30442969/group-by-in-angularjs

*/

describe('Test 385 - Nested Search (issue #495)', function() {

  it('1. CREATE DATABASE',function(done){
    alasql('CREATE DATABASE test385;USE test385');
    done();
  });

	it('2. Create table issue - one statement', function(done){

    // Source data

    var data1 = [{
    "_id" : "2mA82CTSeeTrvMxfR",
    "playlists" :
      [
          {
              "name" : "Electro",
              "songs" :
              [
                  {
                      "id" : "dMEwEdkoPLw",
                      "name" : "Moe Shop - You Look So Good",
                      "position" : "1"
                  },
                  {
                      "id" : "S927n1xUkAM",
                      "name" : "Vexento - Magenta",
                      "position" : "2"
                  }
              ]
          }
      ]
    }];

    // Result data

    var data2 = [{
    "_id" : "2mA82CTSeeTrvMxfR",
    "playlists" :
      [
          {
              "name" : "Electro",
              "songs" :
              [
                  {
                      "id" : "dMEwEdkoPLw",
                      "name" : "Moe Shop - You Look So Good",
                      "position" : "2"
                  },
                  {
                      "id" : "S927n1xUkAM",
                      "name" : "Vexento - Magenta",
                      "position" : "1"
                  }
              ]
          }
      ]
    }];

    alasql('SEARCH /playlists/songs/WHERE(id=$1) SET(position=$2) FROM $0',[data1,"S927n1xUkAM","1"]);
    alasql('SEARCH /playlists/songs/WHERE(id=$1) SET(position=$2) FROM $0',[data1,"dMEwEdkoPLw","2"]);

    assert.deepEqual(data1,data2);
		done();
	});

  it('99. DROP DATABASE',function(done){
    alasql('DROP DATABASE test385');
    done();
  });

});
<|endoftext|>


<commit_before>import React from "react-native";
import SignInButton from "./sign-in-button";
import Home from "./home";
import GoogleLogin from "../../modules/google-login";
import FacebookLogin from "../../modules/facebook-login";

const {
    StyleSheet,
    View,
    Text,
    Image,
    Dimensions
} = React;

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    cover: {
        flex: 1,
        resizeMode: "cover"
    },
    overlay: {
        flex: 1,
        alignItems: "stretch",
        justifyContent: "center",
        padding: 32,
        backgroundColor: "rgba(0, 0, 0, 0.5)"
    },
    image: {
        resizeMode: "contain"
    },
    logoContainer: {
        flex: 1,
        alignItems: "center",
        justifyContent: "center",
        marginTop: 96
    },
    tip: {
        color: "#fff",
        textAlign: "center",
        paddingHorizontal: 4,
        marginVertical: 8
    },
    buttonContainer: {
        alignItems: "stretch"
    },
    facebook: {
        backgroundColor: "#3B5998"
    },
    google: {
        backgroundColor: "#488EF1"
    }
});

export default class SignIn extends React.Component {
    _onSignIn() {
        this.props.navigator.replace({ component: Home });
    }

    _onSignUp() {

    }

    _onFacebookPress() {
        FacebookLogin.pickAccount(e => console.log(e));
    }

    _onGooglePress() {
        GoogleLogin.pickAccount(e => console.log(e));
    }

    render() {
        const win = Dimensions.get("window");

        return (
            <View style={styles.container}>
                <Image source={require("image!signin_bg")} style={[ styles.cover, { height: win.height, width: win.width } ]}>
                    <View style={styles.overlay}>
                        <View style={styles.logoContainer}>
                            <Image source={require("image!logo")} style={styles.image} />
                            <Image source={require("image!logotype")} style={styles.image} />
                        </View>
                        <View style={styles.buttonContainer}>
                            <Text style={styles.tip}>SIGN IN OR SIGN UP WITH</Text>
                            <SignInButton
                                style={styles.facebook}
                                text="Facebook"
                                onPress={this._onFacebookPress.bind(this)}
                            />
                            <SignInButton
                                style={styles.google}
                                text="Google"
                                onPress={this._onGooglePress.bind(this)}
                            />
                        </View>
                    </View>
                </Image>
            </View>
        );
    }
}

SignIn.propTypes = {
    navigator: React.PropTypes.object.isRequired
};
<commit_msg>Fix login screen<commit_after>import React from "react-native";
import SignInButton from "./sign-in-button";
import Home from "./home";
import GoogleLogin from "../../modules/google-login";
import FacebookLogin from "../../modules/facebook-login";

const {
    StyleSheet,
    View,
    Text,
    Image,
    Dimensions
} = React;

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    cover: {
        flex: 1
    },
    overlay: {
        flex: 1,
        alignItems: "stretch",
        justifyContent: "center",
        padding: 32,
        backgroundColor: "rgba(0, 0, 0, 0.5)"
    },
    image: {
        resizeMode: "contain",
        margin: 4
    },
    imageLogo: {
        height: 59,
        width: 108
    },
    imageLogoType: {
        height: 35,
        width: 219
    },
    logoContainer: {
        flex: 1,
        alignItems: "center",
        justifyContent: "center",
        marginTop: 96
    },
    tip: {
        color: "#fff",
        textAlign: "center",
        paddingHorizontal: 4,
        marginVertical: 8
    },
    buttonContainer: {
        alignItems: "stretch"
    },
    facebook: {
        backgroundColor: "#3B5998"
    },
    google: {
        backgroundColor: "#488EF1"
    }
});

export default class SignIn extends React.Component {
    _onSignIn() {
        this.props.navigator.replace({ component: Home });
    }

    _onSignUp() {

    }

    _onFacebookPress() {
        FacebookLogin.pickAccount(e => console.log(e));
    }

    _onGooglePress() {
        GoogleLogin.pickAccount(e => console.log(e));
    }

    render() {
        const win = Dimensions.get("window");

        return (
            <View style={styles.container}>
                <Image source={require("image!signin_bg")} style={[ styles.cover, { height: win.height, width: win.width } ]}>
                    <View style={styles.overlay}>
                        <View style={styles.logoContainer}>
                            <Image source={require("image!logo")} style={[ styles.image, styles.imageLogo ]} />
                            <Image source={require("image!logotype")} style={[ styles.image, styles.imageLogoType ]} />
                        </View>
                        <View style={styles.buttonContainer}>
                            <Text style={styles.tip}>SIGN IN OR SIGN UP WITH</Text>
                            <SignInButton
                                style={styles.facebook}
                                text="Facebook"
                                onPress={this._onFacebookPress.bind(this)}
                            />
                            <SignInButton
                                style={styles.google}
                                text="Google"
                                onPress={this._onGooglePress.bind(this)}
                            />
                        </View>
                    </View>
                </Image>
            </View>
        );
    }
}

SignIn.propTypes = {
    navigator: React.PropTypes.object.isRequired
};
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var Participant = require('participant-view');
var request = require('request');
var template = require('./template');
var bus = require('bus');
var t = require('t');
var citizen = require('citizen');
var View = require('view');

module.exports = ParticipantsBox;

function ParticipantsBox(participants) {
  if (!(this instanceof ParticipantsBox)) {
    return new ParticipantsBox(participants);
  };

  View.call(this, template, { participants: participants });
  this.participants = participants;
}

/**
 * Inherit from View
 */

View(ParticipantsBox);

ParticipantsBox.prototype.onvote = function() {
  var id = citizen.id;
  var ids = this.participants.map(function(c) { return 'object' === typeof c ? c._id : c; });

  if (!~ids.indexOf(id)) this.participants.push(id);
  this.fetch();
}

ParticipantsBox.prototype.switchOn = function() {
  this.on('fetch', this.load.bind(this));
  bus.on('vote', this.bound('onvote'));
  this.bind('click', 'a.view-more', 'more');
}

ParticipantsBox.prototype.fetch = function() {
  var view = this;

  request
  .post('/api/citizen/lookup')
  .send({ ids: this.participants })
  .end(function(err, res) {
    if (err || !res.ok) {
      return log('Fetch error: %s', err || res.error);
    };
    if (res.body && res.body.error) {
      return log('Error: %o', res.body.error);
    };

    view.emit('fetch', res.body || []);
  });
}

ParticipantsBox.prototype.load = function(participants) {
  participants.forEach(function(p, i) {
    var participant = new Participant(p, i);
    participant.appendTo(this.find('.participants-container')[0]);
  }, this);

  // Update counter
  participantsCounter = this.find('.participants-container span')[0];
  var cardinality = 1 === participants.length ? 'singular' : 'plural';
  participantsCounter.innerHTML = participants.length + ' ' + t('proposal-article.participant.' + cardinality);

  // Hellip
  if (participants.length > 5)
    this.find('a.view-more.hellip')[0].classList.remove('hide');
}

ParticipantsBox.prototype.more = function(ev) {
  ev.preventDefault();

  var btn = this.find('a.view-more');
  btn.addClass('hide');

  var hiddens = this.find('a.participant-profile.hide') || [];
  hiddens.removeClass('hide');
}<commit_msg>[participants] Fixed repeated bubbles.<commit_after>/**
 * Module dependencies.
 */

var Participant = require('participant-view');
var request = require('request');
var template = require('./template');
var bus = require('bus');
var t = require('t');
var citizen = require('citizen');
var View = require('view');

module.exports = ParticipantsBox;

function ParticipantsBox(participants) {
  if (!(this instanceof ParticipantsBox)) {
    return new ParticipantsBox(participants);
  };

  View.call(this, template, { participants: participants });
  this.participants = participants;
}

/**
 * Inherit from View
 */

View(ParticipantsBox);

ParticipantsBox.prototype.onvote = function() {
  var id = citizen.id;
  var ids = this.participants.map(function(c) { return 'object' === typeof c ? c._id : c; });

  if (!~ids.indexOf(id)) this.participants.push(id);
  this.fetch();
}

ParticipantsBox.prototype.switchOn = function() {
  this.on('fetch', this.load.bind(this));
  bus.on('vote', this.bound('onvote'));
  this.bind('click', 'a.view-more', 'more');
}

ParticipantsBox.prototype.fetch = function() {
  var view = this;

  request
  .post('/api/citizen/lookup')
  .send({ ids: this.participants })
  .end(function(err, res) {
    if (err || !res.ok) {
      return log('Fetch error: %s', err || res.error);
    };
    if (res.body && res.body.error) {
      return log('Error: %o', res.body.error);
    };

    view.emit('fetch', res.body || []);
  });
}

ParticipantsBox.prototype.load = function(participants) {
  var container = this.find('.participants-container')[0];
  // Remove existent bubbles
  this.find('a', container).remove();

  participants.forEach(function(p, i) {
    var participant = new Participant(p, i);
    participant.appendTo(container);
  }, this);

  // Update counter
  participantsCounter = this.find('.participants-container span')[0];
  var cardinality = 1 === participants.length ? 'singular' : 'plural';
  participantsCounter.innerHTML = participants.length + ' ' + t('proposal-article.participant.' + cardinality);

  // Hellip
  if (participants.length > 5)
    this.find('a.view-more.hellip')[0].classList.remove('hide');
}

ParticipantsBox.prototype.more = function(ev) {
  ev.preventDefault();

  var btn = this.find('a.view-more');
  btn.addClass('hide');

  var hiddens = this.find('a.participant-profile.hide') || [];
  hiddens.removeClass('hide');
}<|endoftext|>


<commit_before>function QTopologyDashboardViewModel(divIdTarget) {
    this.target_div = divIdTarget;

    this.workers = ko.observableArray();
    this.topologies = ko.observableArray();
    this.storage_props = ko.observableArray();

    // blade worker
    this.selected_worker = ko.observable();
    // blade topology
    this.selected_topology = ko.observable();

    this.bladeWorker = "bladeWorker";
    this.bladeTopology = "bladeTopology";

    this.blades = [this.bladeWorker, this.bladeTopology];
    this.prepareBlades();
}
QTopologyDashboardViewModel.prototype.formatDateGui = function (d) {
    let dd = new Date(d.getTime());
    dd.setMinutes(dd.getMinutes() - dd.getTimezoneOffset());
    return dd.toISOString()
        .replace("T", " ")
        .substr(0,19);
}
QTopologyDashboardViewModel.prototype.post = function (cmd, data, callback) {
    $.ajax({
        url: "/" + cmd,
        type: "POST",
        dataType: "json",
        data: JSON.stringify(data),
        success: callback
    });
}
QTopologyDashboardViewModel.prototype.loadData = function (callback) {
    var self = this;
    self.post("topology-status", {}, function (data_topologies) {
        self.mergeTopologies(data_topologies);
        self.post("worker-status", {}, function (data_workers) {
            self.mergeWorkers(data_workers);
            if (callback) {
                callback();
            }
        });
    });
    self.post("storage-info", {}, function (props) {
        // here, it is OK to just overwrite stuff
        self.storage_props.removeAll();
        for (var prop of props.data) {
            self.storage_props.push(prop);
        }
    });
}
QTopologyDashboardViewModel.prototype.mergeTopologies = function (new_data) {
    var self = this;
    var existing_topologies = this.topologies.removeAll();
    for (var d of new_data) {
        var hits = existing_topologies.filter(x => x.uuid() == d.uuid);
        var obj = null;
        if (hits.length == 0) {
            var uuid = d.uuid;
            var rec = {
                uuid: ko.observable(uuid),
                enabled: ko.observable(d.enabled),
                status: ko.observable(d.status),
                config: ko.observable(""),
                error: ko.observable(d.error || "-"),
                worker: ko.observable(d.worker || "-"),
                history: ko.observableArray(),
                open: function () { self.showTopologyInfo(uuid); },
                set_enabled: function () { self.setTopologyEnabled(uuid); },
                set_disabled: function () { self.setTopologyDisabled(uuid); },
                clear_error: function () { self.clearTopologyError(uuid); },
                stop: function () { self.stopTopology(uuid); }
            };
            obj = rec;
        } else {
            var hit = hits[0];
            hit.enabled(d.enabled);
            hit.status(d.status || "-");
            hit.error(d.error || "-");
            hit.worker(d.worker || "-");
            obj = hit;
        }
        this.topologies.push(obj);
    }
}
QTopologyDashboardViewModel.prototype.mergeWorkers = function (new_data) {
    var self = this;
    var existing_workers = self.workers.removeAll();
    for (var d of new_data) {
        var hits = existing_workers.filter(x => x.name() == d.name);
        var obj = null;
        var name = d.name;
        if (hits.length == 0) {
            var rec = {
                name: ko.observable(name),
                last_ping: ko.observable(new Date(d.last_ping)),
                status: ko.observable(d.status),
                lstatus: ko.observable(d.lstatus || "-"),
                lstatus_ts: ko.observable(new Date(d.lstatus_ts)),
                topologies_count: ko.observable(0),
                topologies: ko.observableArray(),
                history: ko.observableArray(),
                open: function () { self.showWorkerInfo(name); },
                shut_down: function () { self.shutDownWorker(name); },
                remove: function () { self.deleteWorker(name); }
            };
            rec.last_ping_s = ko.computed(function () {
                return self.formatDateGui(rec.last_ping());
            });
            obj = rec;
        } else {
            var hit = hits[0];
            hit.last_ping(new Date(d.last_ping));
            hit.status(d.status);
            hit.lstatus(d.lstatus || "-");
            hit.lstatus_ts(new Date(d.lstatus_ts));
            obj = hit;
        }
        // match with topologies
        obj.topologies.removeAll();
        self.topologies().forEach(function (x) {
            if (x.worker() == name) {
                obj.topologies.push(x);
            }
        });
        obj.topologies_count(obj.topologies().length);
        self.workers.push(obj);
    }
}
QTopologyDashboardViewModel.prototype.init = function (callback) {
    this.loadData(callback);
}
QTopologyDashboardViewModel.prototype.showBlade = function (name) {
    for (var blade_name of this.blades) {
        $("#" + blade_name).hide();
    }
    $("#" + name).show();
}
QTopologyDashboardViewModel.prototype.showWorkerInfo = function (name) {
    var self = this;
    var worker = this.workers().filter(function (x) { return x.name() == name; })[0];
    this.selected_worker(worker);
    this.showBlade(this.bladeWorker);
    self.post("worker-history", { name: name }, function (data) {
        worker.history.removeAll();
        data.forEach(function (x) {
            var d = new Date(x.ts);
            x.ts_d = d;
            x.ts_s = self.formatDateGui(d);
            worker.history.push(x);
        });
        // sort descending in time
        worker.history.sort(function (a, b) {
            return (a.ts_d < b.ts_d ? 1 : (a.ts_d > b.ts_d ? -1 : 0));
        });
    });
}
QTopologyDashboardViewModel.prototype.showTopologyInfo = function (uuid) {
    var self = this;
    var topology = self.topologies().filter(function (x) { return x.uuid() == uuid; })[0];
    self.selected_topology(topology);
    self.showBlade(self.bladeTopology);
    self.post("topology-info", { uuid: uuid }, function (data) {
        topology.config(data.config);
    });
    self.post("topology-history", { uuid: uuid }, function (data) {
        topology.history.removeAll();
        data.forEach(function (x) {
            var d = new Date(x.ts);
            x.ts_d = d;
            x.ts_s = self.formatDateGui(d);
            topology.history.push(x);
        });
        // sort descending in time
        topology.history.sort(function (a, b) {
            return (a.ts_d < b.ts_d ? 1 : (a.ts_d > b.ts_d ? -1 : 0));
        });
    });
}

QTopologyDashboardViewModel.prototype.prepareBlades = function () {
    var self = this;
    for (var ii = 0; ii < self.blades.length; ii++) (function (i) {
        var blade_name = self.blades[i];
        var blade_obj = $("#" + blade_name);
        blade_obj.hide();
        // prepend close buttons
        blade_obj.find(".blade-close").click(function () {
            blade_obj.hide();
        })
    })(ii);
    $(document).keyup(function (e) {
        if (e.keyCode === 27) {
            $(".blade").hide();
        }
    });
}

QTopologyDashboardViewModel.prototype.setTopologyEnabled = function (uuid) {
    var self = this;
    self.post("enable-topology", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.setTopologyDisabled = function (uuid) {
    var self = this;
    self.post("disable-topology", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.clearTopologyError = function (uuid) {
    var self = this;
    self.post("clear-topology-error", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.stopTopology = function (uuid) {
    var self = this;
    self.post("stop-topology", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.deleteWorker = function (name) {
    var self = this;
    self.post("delete-worker", { name: name }, function () {
        self.loadData(function () {
            self.showWorkerInfo(name);
        });
    });
}
QTopologyDashboardViewModel.prototype.shutDownWorker = function (name) {
    var self = this;
    self.post("shut-down-worker", { name: name }, function () {
        self.loadData(function () {
            self.showWorkerInfo(name);
        });
    });
}
<commit_msg>Added sorting to lists<commit_after>function QTopologyDashboardViewModel(divIdTarget) {
    this.target_div = divIdTarget;

    this.workers = ko.observableArray();
    this.topologies = ko.observableArray();
    this.storage_props = ko.observableArray();

    // blade worker
    this.selected_worker = ko.observable();
    // blade topology
    this.selected_topology = ko.observable();

    this.bladeWorker = "bladeWorker";
    this.bladeTopology = "bladeTopology";

    this.blades = [this.bladeWorker, this.bladeTopology];
    this.prepareBlades();
}
QTopologyDashboardViewModel.prototype.formatDateGui = function (d) {
    let dd = new Date(d.getTime());
    dd.setMinutes(dd.getMinutes() - dd.getTimezoneOffset());
    return dd.toISOString()
        .replace("T", " ")
        .substr(0,19);
}
QTopologyDashboardViewModel.prototype.post = function (cmd, data, callback) {
    $.ajax({
        url: "/" + cmd,
        type: "POST",
        dataType: "json",
        data: JSON.stringify(data),
        success: callback
    });
}
QTopologyDashboardViewModel.prototype.loadData = function (callback) {
    var self = this;
    self.post("topology-status", {}, function (data_topologies) {
        self.mergeTopologies(data_topologies);
        self.post("worker-status", {}, function (data_workers) {
            self.mergeWorkers(data_workers);
            if (callback) {
                callback();
            }
        });
    });
    self.post("storage-info", {}, function (props) {
        // here, it is OK to just overwrite stuff
        self.storage_props.removeAll();
        for (var prop of props.data) {
            self.storage_props.push(prop);
        }
    });
}
QTopologyDashboardViewModel.prototype.mergeTopologies = function (new_data) {
    var self = this;
    var existing_topologies = this.topologies.removeAll();
    for (var d of new_data) {
        var hits = existing_topologies.filter(x => x.uuid() == d.uuid);
        var obj = null;
        if (hits.length == 0) {
            var uuid = d.uuid;
            var rec = {
                uuid: ko.observable(uuid),
                enabled: ko.observable(d.enabled),
                status: ko.observable(d.status),
                config: ko.observable(""),
                error: ko.observable(d.error || "-"),
                worker: ko.observable(d.worker || "-"),
                history: ko.observableArray(),
                open: function () { self.showTopologyInfo(uuid); },
                set_enabled: function () { self.setTopologyEnabled(uuid); },
                set_disabled: function () { self.setTopologyDisabled(uuid); },
                clear_error: function () { self.clearTopologyError(uuid); },
                stop: function () { self.stopTopology(uuid); }
            };
            obj = rec;
        } else {
            var hit = hits[0];
            hit.enabled(d.enabled);
            hit.status(d.status || "-");
            hit.error(d.error || "-");
            hit.worker(d.worker || "-");
            obj = hit;
        }
        this.topologies.push(obj);
    }
    this.topologies.sort(function(a,b){
        return a.uuid().localeCompare(b.uuid());
    });
}
QTopologyDashboardViewModel.prototype.mergeWorkers = function (new_data) {
    var self = this;
    var existing_workers = self.workers.removeAll();
    for (var d of new_data) {
        var hits = existing_workers.filter(x => x.name() == d.name);
        var obj = null;
        var name = d.name;
        if (hits.length == 0) {
            var rec = {
                name: ko.observable(name),
                last_ping: ko.observable(new Date(d.last_ping)),
                status: ko.observable(d.status),
                lstatus: ko.observable(d.lstatus || "-"),
                lstatus_ts: ko.observable(new Date(d.lstatus_ts)),
                topologies_count: ko.observable(0),
                topologies: ko.observableArray(),
                history: ko.observableArray(),
                open: function () { self.showWorkerInfo(name); },
                shut_down: function () { self.shutDownWorker(name); },
                remove: function () { self.deleteWorker(name); }
            };
            rec.last_ping_s = ko.computed(function () {
                return self.formatDateGui(rec.last_ping());
            });
            obj = rec;
        } else {
            var hit = hits[0];
            hit.last_ping(new Date(d.last_ping));
            hit.status(d.status);
            hit.lstatus(d.lstatus || "-");
            hit.lstatus_ts(new Date(d.lstatus_ts));
            obj = hit;
        }
        // match with topologies
        obj.topologies.removeAll();
        self.topologies().forEach(function (x) {
            if (x.worker() == name) {
                obj.topologies.push(x);
            }
        });
        obj.topologies_count(obj.topologies().length);
        self.workers.push(obj);
    }
    self.workers.sort(function(a,b){
        return a.name().localeCompare(b.name());
    });
}
QTopologyDashboardViewModel.prototype.init = function (callback) {
    this.loadData(callback);
}
QTopologyDashboardViewModel.prototype.showBlade = function (name) {
    for (var blade_name of this.blades) {
        $("#" + blade_name).hide();
    }
    $("#" + name).show();
}
QTopologyDashboardViewModel.prototype.showWorkerInfo = function (name) {
    var self = this;
    var worker = this.workers().filter(function (x) { return x.name() == name; })[0];
    this.selected_worker(worker);
    this.showBlade(this.bladeWorker);
    self.post("worker-history", { name: name }, function (data) {
        worker.history.removeAll();
        data.forEach(function (x) {
            var d = new Date(x.ts);
            x.ts_d = d;
            x.ts_s = self.formatDateGui(d);
            worker.history.push(x);
        });
        // sort descending in time
        worker.history.sort(function (a, b) {
            return (a.ts_d < b.ts_d ? 1 : (a.ts_d > b.ts_d ? -1 : 0));
        });
    });
}
QTopologyDashboardViewModel.prototype.showTopologyInfo = function (uuid) {
    var self = this;
    var topology = self.topologies().filter(function (x) { return x.uuid() == uuid; })[0];
    self.selected_topology(topology);
    self.showBlade(self.bladeTopology);
    self.post("topology-info", { uuid: uuid }, function (data) {
        topology.config(data.config);
    });
    self.post("topology-history", { uuid: uuid }, function (data) {
        topology.history.removeAll();
        data.forEach(function (x) {
            var d = new Date(x.ts);
            x.ts_d = d;
            x.ts_s = self.formatDateGui(d);
            topology.history.push(x);
        });
        // sort descending in time
        topology.history.sort(function (a, b) {
            return (a.ts_d < b.ts_d ? 1 : (a.ts_d > b.ts_d ? -1 : 0));
        });
    });
}

QTopologyDashboardViewModel.prototype.prepareBlades = function () {
    var self = this;
    for (var ii = 0; ii < self.blades.length; ii++) (function (i) {
        var blade_name = self.blades[i];
        var blade_obj = $("#" + blade_name);
        blade_obj.hide();
        // prepend close buttons
        blade_obj.find(".blade-close").click(function () {
            blade_obj.hide();
        })
    })(ii);
    $(document).keyup(function (e) {
        if (e.keyCode === 27) {
            $(".blade").hide();
        }
    });
}

QTopologyDashboardViewModel.prototype.setTopologyEnabled = function (uuid) {
    var self = this;
    self.post("enable-topology", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.setTopologyDisabled = function (uuid) {
    var self = this;
    self.post("disable-topology", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.clearTopologyError = function (uuid) {
    var self = this;
    self.post("clear-topology-error", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.stopTopology = function (uuid) {
    var self = this;
    self.post("stop-topology", { uuid: uuid }, function () {
        self.loadData(function () {
            self.showTopologyInfo(uuid);
        });
    });
}
QTopologyDashboardViewModel.prototype.deleteWorker = function (name) {
    var self = this;
    self.post("delete-worker", { name: name }, function () {
        self.loadData(function () {
            self.showWorkerInfo(name);
        });
    });
}
QTopologyDashboardViewModel.prototype.shutDownWorker = function (name) {
    var self = this;
    self.post("shut-down-worker", { name: name }, function () {
        self.loadData(function () {
            self.showWorkerInfo(name);
        });
    });
}
<|endoftext|>


<commit_before>import { execFile } from 'child_process';
import Client from '../../client.js';
import configuredClients from "./clients.js";
import { enterJob } from '../../../utils/buildmessage.js';
import { getUrlWithResuming } from '../../../utils/http-helpers.js';
import { execFileSync } from '../../../utils/processes';
import { ensureDependencies } from '../../../cli/dev-bundle-helpers.js';
import {
  mkdtemp,
  pathJoin,
  chmod,
  statOrNull,
  readFile,
  createWriteStream,
  getDevBundle,
} from '../../../fs/files';

const NPM_DEPENDENCIES = {
  'browserstack-webdriver': '2.41.1',
  'browserstack-local': '1.3.0',
};

const USER = 'dev1141';

// A memoized key from BrowserStackClient._getBrowserStackKey.
let browserStackKey;

export default class BrowserStackClient extends Client {
  constructor(options) {
    super(options);

    enterJob({
      title: 'Installing BrowserStack WebDriver in Meteor tool',
    }, () => {
      ensureDependencies(NPM_DEPENDENCIES);
    });

    this.npmPackageExports = require('browserstack-webdriver');

    // Capabilities which are allowed by selenium.
    this.config.seleniumOptions =
      this.config.seleniumOptions || {};

    // Additional capabilities which are unique to BrowserStack.
    this.config.browserStackOptions =
      this.config.browserStackOptions || {};

    this._setName();
  }

  _setName() {
    const name = this.config.seleniumOptions.browserName || "default";
    const version = this.config.seleniumOptions.version || "";
    const device =
      this.config.browserStackOptions.realMobile &&
      this.config.browserStackOptions.device || "";

    this.name = "BrowserStack: " + name +
      (version && ` Version ${version}`) +
      (device && ` (Device: ${device})`);
  }

  connect() {
    const key = BrowserStackClient._getBrowserStackKey();
    if (! key) {
      throw new Error(
        "BrowserStack key not found. Ensure that s3cmd is setup with " +
        "S3 credentials, or set BROWSERSTACK_ACCESS_KEY in your environment.");
    }

    const capabilities = {
      // Authentication
      'browserstack.user': USER,
      'browserstack.key': key,

      // Use the BrowserStackLocal tunnel, to allow BrowserStack to
      // tunnel to the machine this server is runninng on.
      'browserstack.local': true,

      // Enabled the capturing of "Visual Logs" (i.e. Screenshots).
      'browserstack.debug': true,

      // On browsers that support it, capture the console
      'browserstack.console': 'errors',

      ...this.config.seleniumOptions,
      ...this.config.browserStackOptions,
    };

    const triggerRequest = () => {
      this.driver = new this.npmPackageExports.Builder()
        .usingServer('https://hub-cloud.browserstack.com/wd/hub')
        .withCapabilities(capabilities)
        .build();

      this.driver.get(this.url);
    }

    this._launchBrowserStackTunnel()
      .then(triggerRequest)
      .catch((e) => {
        // In the event of an error, shut down the daemon.
        this.stop();

        throw e;
      });
  }

  stop() {
    this.driver && this.driver.quit();
    this.driver = null;

    this.tunnelProcess && this.tunnelProcess.stop(() => {});
    this.tunnelProcess = null;
  }

  static _getBrowserStackKey() {
    // Use the memoized version, first and foremost.
    if (typeof browserStackKey !== "undefined") {
      return browserStackKey;
    }

    if (process.env.BROWSERSTACK_ACCESS_KEY) {
      return (browserStackKey = process.env.BROWSERSTACK_ACCESS_KEY);
    }

    // Try to get the credentials from S3 with the s3cmd tool.
    const outputDir = pathJoin(mkdtemp(), "key");
      const browserstackKey = "s3://meteor-browserstack-keys/browserstack-key";
    try {
      execFileSync("s3cmd", ["get",
        browserstackKey,
        outputDir
      ]);

      return (browserStackKey = readFile(outputDir, "utf8").trim());
    } catch (e) {
      // A failure is acceptable here; it was just a try.
      console.warn(`Failed to load browserstack key from
        ${browserstackKey}`, e);
    }

    return (browserStackKey = null);
  }

  _launchBrowserStackTunnel() {
    this.tunnelProcess = new (require('browserstack-local')).Local();

    const options = {
      key: this.constructor._getBrowserStackKey(),
      onlyAutomate: true,
      verbose: true,
      // The ",0" means "SSL off".  It's localhost, after all.
      only: `${this.host},${this.port},0`,
    }

    return new Promise((resolve, reject) => {
      this.tunnelProcess.start(options, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
  }

  static prerequisitesMet() {
    return !! this._getBrowserStackKey();
  }

  static pushClients(clients, appConfig) {
    configuredClients.forEach((client) => {
      clients.push(new BrowserStackClient(
        {
          ...appConfig,
          config: {
            seleniumOptions: client.selenium,
            browserStackOptions: client.browserstack,
          },
        },
      ));
    });
  }
}
<commit_msg>-Trying to run Browserstack inside Circle CI<commit_after>import { execFile } from 'child_process';
import Client from '../../client.js';
import configuredClients from "./clients.js";
import { enterJob } from '../../../utils/buildmessage.js';
import { getUrlWithResuming } from '../../../utils/http-helpers.js';
import { execFileSync } from '../../../utils/processes';
import { ensureDependencies } from '../../../cli/dev-bundle-helpers.js';
import {
  mkdtemp,
  pathJoin,
  chmod,
  statOrNull,
  readFile,
  createWriteStream,
  getDevBundle,
} from '../../../fs/files';

const NPM_DEPENDENCIES = {
  'browserstack-webdriver': '2.41.1',
  'browserstack-local': '1.3.0',
};

const USER = 'dev1141';

// A memoized key from BrowserStackClient._getBrowserStackKey.
let browserStackKey;

export default class BrowserStackClient extends Client {
  constructor(options) {
    super(options);

    enterJob({
      title: 'Installing BrowserStack WebDriver in Meteor tool',
    }, () => {
      ensureDependencies(NPM_DEPENDENCIES);
    });

    this.npmPackageExports = require('browserstack-webdriver');

    // Capabilities which are allowed by selenium.
    this.config.seleniumOptions =
      this.config.seleniumOptions || {};

    // Additional capabilities which are unique to BrowserStack.
    this.config.browserStackOptions =
      this.config.browserStackOptions || {};

    this._setName();
  }

  _setName() {
    const name = this.config.seleniumOptions.browserName || "default";
    const version = this.config.seleniumOptions.version || "";
    const device =
      this.config.browserStackOptions.realMobile &&
      this.config.browserStackOptions.device || "";

    this.name = "BrowserStack: " + name +
      (version && ` Version ${version}`) +
      (device && ` (Device: ${device})`);
  }

  connect() {
    const key = BrowserStackClient._getBrowserStackKey();
    console.log('connect KEY', key);
    if (! key) {
      throw new Error(
        "BrowserStack key not found. Ensure that s3cmd is setup with " +
        "S3 credentials, or set BROWSERSTACK_ACCESS_KEY in your environment.");
    }

    const capabilities = {
      // Authentication
      'browserstack.user': USER,
      'browserstack.key': key,

      // Use the BrowserStackLocal tunnel, to allow BrowserStack to
      // tunnel to the machine this server is runninng on.
      'browserstack.local': true,

      // Enabled the capturing of "Visual Logs" (i.e. Screenshots).
      'browserstack.debug': true,

      // On browsers that support it, capture the console
      'browserstack.console': 'errors',

      ...this.config.seleniumOptions,
      ...this.config.browserStackOptions,
    };

    const triggerRequest = () => {
      this.driver = new this.npmPackageExports.Builder()
        .usingServer('https://hub-cloud.browserstack.com/wd/hub')
        .withCapabilities(capabilities)
        .build();

      this.driver.get(this.url);
    }

    this._launchBrowserStackTunnel()
      .then(triggerRequest)
      .catch((e) => {
        // In the event of an error, shut down the daemon.
        this.stop();

        throw e;
      });
  }

  stop() {
    this.driver && this.driver.quit();
    this.driver = null;

    this.tunnelProcess && this.tunnelProcess.stop(() => {});
    this.tunnelProcess = null;
  }

  static _getBrowserStackKey() {
    // Use the memoized version, first and foremost.
    if (typeof browserStackKey !== "undefined") {
      return browserStackKey;
    }

    if (process.env.BROWSERSTACK_ACCESS_KEY) {
      return (browserStackKey = process.env.BROWSERSTACK_ACCESS_KEY);
    }

    // Try to get the credentials from S3 with the s3cmd tool.
    const outputDir = pathJoin(mkdtemp(), "key");
      const browserstackKey = "s3://meteor-browserstack-keys/browserstack-key";
    try {
      execFileSync("s3cmd", ["get",
        browserstackKey,
        outputDir
      ]);

      return (browserStackKey = readFile(outputDir, "utf8").trim());
    } catch (e) {
      // A failure is acceptable here; it was just a try.
      console.warn(`Failed to load browserstack key from
        ${browserstackKey}`, e);
    }

    return (browserStackKey = null);
  }

  _launchBrowserStackTunnel() {
    this.tunnelProcess = new (require('browserstack-local')).Local();

    const options = {
      key: this.constructor._getBrowserStackKey(),
      onlyAutomate: true,
      verbose: true,
      // The ",0" means "SSL off".  It's localhost, after all.
      only: `${this.host},${this.port},0`,
    }

    return new Promise((resolve, reject) => {
      this.tunnelProcess.start(options, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
  }

  static prerequisitesMet() {
    return !! this._getBrowserStackKey();
  }

  static pushClients(clients, appConfig) {
    configuredClients.forEach((client) => {
      clients.push(new BrowserStackClient(
        {
          ...appConfig,
          config: {
            seleniumOptions: client.selenium,
            browserStackOptions: client.browserstack,
          },
        },
      ));
    });
  }
}
<|endoftext|>


<commit_before>import _ from 'underscore';
import buildmessage from '../utils/buildmessage.js';
import runLog from '../runners/run-log.js';
import { Console } from '../console/console.js';
import main from '../cli/main.js';

import { displayNameForPlatform, prepareProjectForBuild } from './index.js';

export class CordovaRunner {
  constructor(cordovaProject, runTargets) {
    this.cordovaProject = cordovaProject;
    this.runTargets = runTargets;

    this.started = false;
  }

  get projectContext() {
    return this.cordovaProject.projectContext;
  }

  get platformsForRunTargets() {
    return _.uniq(this.runTargets.map((runTarget) => runTarget.platform));
  }

  checkPlatformsForRunTargets() {
    this.cordovaProject.ensurePlatformsAreSynchronized();

    let satisfied = true;
    const messages = buildmessage.capture(
      { title: `checking platform requirements` }, () => {
      for (const platform of this.platformsForRunTargets) {
        satisfied =
          this.cordovaProject.checkPlatformRequirements(platform) &&
          satisfied;
      }
    });

    if (messages.hasMessages()) {
      Console.printMessages(messages);
      throw new main.ExitWithCode(1);
    } else if (!satisfied) {
      throw new main.ExitWithCode(1);
    };
  }

  printWarningsIfNeeded() {
    // OAuth2 packages don't work so well with any mobile platform except the
    // iOS Simulator. Print a warning and direct users to the wiki page for help.
    if (this.projectContext.packageMap.getInfo('oauth2')) {
      Console.warn();
      Console.labelWarn(
        "It looks like you are using OAuth2 login in your app. " +
        "Meteor's OAuth2 implementation does not currently work with " +
        "mobile apps in local development mode, except in the iOS " +
        "simulator. You can run the iOS simulator with 'meteor run ios'. " +
        "For additional workarounds, see " +
        Console.url(
          "https://github.com/meteor/meteor/wiki/" +
          "OAuth-for-mobile-Meteor-clients."));
    }

    // If we are targeting remote devices, warn about ports and same network.
    if (_.findWhere(this.runTargets, { isDevice: true })) {
      Console.warn();
      Console.labelWarn(
        "You are testing your app on a remote device. " +
        "For the mobile app to be able to connect to the local server, make " +
        "sure your device is on the same network, and that the network " +
        "configuration allows clients to talk to each other " +
        "(no client isolation).");
    }
  }

  prepareProject(bundlePath, pluginVersions, options) {
    buildmessage.assertInCapture();

    buildmessage.enterJob({ title: "preparing Cordova project" }, () => {
      this.cordovaProject.prepareFromAppBundle(bundlePath,
        pluginVersions, options);

      if (buildmessage.jobHasMessages()) {
        return;
      }

      for (let platform of this.platformsForRunTargets) {
        this.cordovaProject.prepareForPlatform(platform);
      }
    });

    this.pluginVersions = pluginVersions;
  }

  startRunTargets() {
    this.started = false;

    for (runTarget of this.runTargets) {
      const messages = buildmessage.capture({ title: `starting ${runTarget.title}` }, () => {
        Promise.await(runTarget.start(this.cordovaProject));
      });
      if (messages.hasMessages()) {
        Console.printMessages(messages);
      } else {
        runLog.log(`Started ${runTarget.title}.`, { arrow: true });
      }
    }

    this.started = true;
  }

  havePlatformsChangedSinceLastRun() {
    const platformsForRunTargets = this.platformsForRunTargets;
    if (!platformsForRunTargets) {
      return false;
    }

    const cordovaPlatformsInApp = this.cordovaProject.cordovaPlatformsInApp;

    return !_.isEqual(platformsForRunTargets,
      _.intersection(platformsForRunTargets, cordovaPlatformsInApp));
  }

  havePluginsChangedSinceLastRun(pluginVersions) {
    return this.pluginVersions &&
      !_.isEqual(this.pluginVersions, pluginVersions);
  }
}
<commit_msg>Define `runTarget` before use.<commit_after>import _ from 'underscore';
import buildmessage from '../utils/buildmessage.js';
import runLog from '../runners/run-log.js';
import { Console } from '../console/console.js';
import main from '../cli/main.js';

import { displayNameForPlatform, prepareProjectForBuild } from './index.js';

export class CordovaRunner {
  constructor(cordovaProject, runTargets) {
    this.cordovaProject = cordovaProject;
    this.runTargets = runTargets;

    this.started = false;
  }

  get projectContext() {
    return this.cordovaProject.projectContext;
  }

  get platformsForRunTargets() {
    return _.uniq(this.runTargets.map((runTarget) => runTarget.platform));
  }

  checkPlatformsForRunTargets() {
    this.cordovaProject.ensurePlatformsAreSynchronized();

    let satisfied = true;
    const messages = buildmessage.capture(
      { title: `checking platform requirements` }, () => {
      for (const platform of this.platformsForRunTargets) {
        satisfied =
          this.cordovaProject.checkPlatformRequirements(platform) &&
          satisfied;
      }
    });

    if (messages.hasMessages()) {
      Console.printMessages(messages);
      throw new main.ExitWithCode(1);
    } else if (!satisfied) {
      throw new main.ExitWithCode(1);
    };
  }

  printWarningsIfNeeded() {
    // OAuth2 packages don't work so well with any mobile platform except the
    // iOS Simulator. Print a warning and direct users to the wiki page for help.
    if (this.projectContext.packageMap.getInfo('oauth2')) {
      Console.warn();
      Console.labelWarn(
        "It looks like you are using OAuth2 login in your app. " +
        "Meteor's OAuth2 implementation does not currently work with " +
        "mobile apps in local development mode, except in the iOS " +
        "simulator. You can run the iOS simulator with 'meteor run ios'. " +
        "For additional workarounds, see " +
        Console.url(
          "https://github.com/meteor/meteor/wiki/" +
          "OAuth-for-mobile-Meteor-clients."));
    }

    // If we are targeting remote devices, warn about ports and same network.
    if (_.findWhere(this.runTargets, { isDevice: true })) {
      Console.warn();
      Console.labelWarn(
        "You are testing your app on a remote device. " +
        "For the mobile app to be able to connect to the local server, make " +
        "sure your device is on the same network, and that the network " +
        "configuration allows clients to talk to each other " +
        "(no client isolation).");
    }
  }

  prepareProject(bundlePath, pluginVersions, options) {
    buildmessage.assertInCapture();

    buildmessage.enterJob({ title: "preparing Cordova project" }, () => {
      this.cordovaProject.prepareFromAppBundle(bundlePath,
        pluginVersions, options);

      if (buildmessage.jobHasMessages()) {
        return;
      }

      for (let platform of this.platformsForRunTargets) {
        this.cordovaProject.prepareForPlatform(platform);
      }
    });

    this.pluginVersions = pluginVersions;
  }

  startRunTargets() {
    this.started = false;

    for (let runTarget of this.runTargets) {
      const messages = buildmessage.capture({ title: `starting ${runTarget.title}` }, () => {
        Promise.await(runTarget.start(this.cordovaProject));
      });
      if (messages.hasMessages()) {
        Console.printMessages(messages);
      } else {
        runLog.log(`Started ${runTarget.title}.`, { arrow: true });
      }
    }

    this.started = true;
  }

  havePlatformsChangedSinceLastRun() {
    const platformsForRunTargets = this.platformsForRunTargets;
    if (!platformsForRunTargets) {
      return false;
    }

    const cordovaPlatformsInApp = this.cordovaProject.cordovaPlatformsInApp;

    return !_.isEqual(platformsForRunTargets,
      _.intersection(platformsForRunTargets, cordovaPlatformsInApp));
  }

  havePluginsChangedSinceLastRun(pluginVersions) {
    return this.pluginVersions &&
      !_.isEqual(this.pluginVersions, pluginVersions);
  }
}
<|endoftext|>


<commit_before>var config = {};

config.sensu = {};
config.redis = {};
config.puppetdb = {};
config.http = {};
config.cookie = {};
config.log = {};
config.development = {};
config.production = {};
config.test = {};
config.production.log = {};
config.development.log = {};
config.test.log = {};
config.metrics = {};
config.graphiteEvent = {};
config.credentials = {};
config.credentials.class = process.env.CREDS_CLASS || './config/system-dev-credentials';

config.crmModule = {};
config.crmModule.warmCache = false;
config.crmModule.ticketingHost = 'localhost';
config.crmModule.ticketingPath = '/ticketing/ticket_view.php?ticket=';
config.crmModule.class = process.env.CRM_CLASS || 'cloudy-ubersmith';

config.monModule = {};
config.monModule.class = process.env.MON_CLASS || './lib/monitoring';

config.mgmtDomain = process.env.MGMT_DOMAIN || '.example.org';

config.test.log.directory = process.env.LOG_DIR || process.cwd();
config.test.log.accessLog = process.env.ACCESS_LOG || config.test.log.directory + '/access.log';
config.test.log.level = 'hide';
config.test.log.screen = 'hide';

config.development.log.directory = process.env.LOG_DIR || process.cwd();
config.development.log.accessLog = process.env.ACCESS_LOG || config.development.log.directory + '/access.log';
config.development.log.level = 'hide';
config.development.log.screen = 'hide';

config.production.log.directory = process.env.LOG_DIR || '/var/log/cloudykangaroo';
config.production.log.accessLog = process.env.ACCESS_LOG || config.production.log.directory + '/access.log';
config.production.log.level = 'hide';
config.production.log.screen = 'debug';

config.metrics.interval = 15000;

config.sensu.host = process.env.SENSU_HOST || 'localhost';
config.sensu.port = process.env.SENSU_PORT || 4567;
config.sensu.uri = 'http://' + config.sensu.host + ':' + config.sensu.port;

config.puppetdb.host = process.env.PUPPETDB_HOST || 'localhost';
config.puppetdb.port = process.env.PUPPETDB_PORT || 8080;
config.puppetdb.uri =  'http://' + config.puppetdb.host + ':' + config.puppetdb.port + '/v3';

config.graphiteEvent.enabled = false;
config.graphiteEvent.urlPrefix = 'http://graphite.example.com/render/?';
config.graphiteEvent.targetTemplate = 'sensu.statsd.applications.counters.sensu.events..clientName.*.checkName';
config.graphiteEvent.severities = [ 'warning', 'critical', 'unknown' ];
config.graphiteEvent.timeRange = "-8h";
config.graphiteEvent.height = "450";

config.redis.uri = process.env.REDIS_URI;
config.redis.host = process.env.REDIS_HOST || 'localhost';
config.redis.port = process.env.REDIS_PORT || 6379;
config.redis.db = process.env.REDIS_DB || 1;
config.redis.cache = process.env.REDIS_CACHE || 6;
config.redis.ttl = process.env.REDIS_TTL || 300; /*seconds*/
config.redis.class = process.env.REDIS_CLASS || 'redis';
config.http.port = process.env.PORT || 3000;
config.cookie.secret = 'CHANGETHISPLEASE!!!';
config.USE_NOCK = process.env.USE_NOCK || 'false';
config.support = {};

config.roles = {
  users: {
    name: 'users',
    description: 'Minimum access, required to login',
    groups: ['users'],
    users: ['bob']
  },
  sales: {
    name: 'sales',
    description: 'Provides access to lead and account management functionality. Also provides read-only access to monitoring.',
    groups: ['sales'],
    users: ['bob']
  },
  executive: {
    name: 'executive',
    description: 'Provides access to executive reporting and dashboards.',
    groups: ['execs'],
    users: ['bob']
  },
  helpdesk: {
    name: 'helpdesk',
    description: 'Provides access to helpdesk functionality. Also provides read-only access to monitoring.',
    groups: ['engineers'],
    users: ['bob']
  },
  monitoring: {
    name: 'monitoring',
    description: 'Provides additional access to monitoring systems.',
    groups: ['engineers', 'execs'],
    users: ['bob']
  },
  admin: {
    name: 'admin',
    description: 'Provides full access to sales, monitoring and helpdesk functionality.',
    groups: ['admin'],
    users: ['bob']
  },
  super: {
    name: 'super',
    description: 'Provides access to administrative functions.',
    groups: ['ops'],
    users: ['bob']
  }
};

var signatureTemplate = "Ticket submitted via CloudyKangaroo - https://github.com/CloudyKangaroo/CloudyKangaroo";

config.support.signatureTemplate = signatureTemplate;

module.exports = config;
<commit_msg>default CRM is cloudy-localsmith<commit_after>var config = {};

config.sensu = {};
config.redis = {};
config.puppetdb = {};
config.http = {};
config.cookie = {};
config.log = {};
config.development = {};
config.production = {};
config.test = {};
config.production.log = {};
config.development.log = {};
config.test.log = {};
config.metrics = {};
config.graphiteEvent = {};
config.credentials = {};
config.credentials.class = process.env.CREDS_CLASS || './config/system-dev-credentials';

config.crmModule = {};
config.crmModule.warmCache = false;
config.crmModule.ticketingHost = 'localhost';
config.crmModule.ticketingPath = '/ticketing/ticket_view.php?ticket=';
config.crmModule.class = process.env.CRM_CLASS || 'cloudy-localsmith';

config.monModule = {};
config.monModule.class = process.env.MON_CLASS || './lib/monitoring';

config.mgmtDomain = process.env.MGMT_DOMAIN || '.example.org';

config.test.log.directory = process.env.LOG_DIR || process.cwd();
config.test.log.accessLog = process.env.ACCESS_LOG || config.test.log.directory + '/access.log';
config.test.log.level = 'hide';
config.test.log.screen = 'hide';

config.development.log.directory = process.env.LOG_DIR || process.cwd();
config.development.log.accessLog = process.env.ACCESS_LOG || config.development.log.directory + '/access.log';
config.development.log.level = 'hide';
config.development.log.screen = 'hide';

config.production.log.directory = process.env.LOG_DIR || '/var/log/cloudykangaroo';
config.production.log.accessLog = process.env.ACCESS_LOG || config.production.log.directory + '/access.log';
config.production.log.level = 'hide';
config.production.log.screen = 'debug';

config.metrics.interval = 15000;

config.sensu.host = process.env.SENSU_HOST || 'localhost';
config.sensu.port = process.env.SENSU_PORT || 4567;
config.sensu.uri = 'http://' + config.sensu.host + ':' + config.sensu.port;

config.puppetdb.host = process.env.PUPPETDB_HOST || 'localhost';
config.puppetdb.port = process.env.PUPPETDB_PORT || 8080;
config.puppetdb.uri =  'http://' + config.puppetdb.host + ':' + config.puppetdb.port + '/v3';

config.graphiteEvent.enabled = false;
config.graphiteEvent.urlPrefix = 'http://graphite.example.com/render/?';
config.graphiteEvent.targetTemplate = 'sensu.statsd.applications.counters.sensu.events..clientName.*.checkName';
config.graphiteEvent.severities = [ 'warning', 'critical', 'unknown' ];
config.graphiteEvent.timeRange = "-8h";
config.graphiteEvent.height = "450";

config.redis.uri = process.env.REDIS_URI;
config.redis.host = process.env.REDIS_HOST || 'localhost';
config.redis.port = process.env.REDIS_PORT || 6379;
config.redis.db = process.env.REDIS_DB || 1;
config.redis.cache = process.env.REDIS_CACHE || 6;
config.redis.ttl = process.env.REDIS_TTL || 300; /*seconds*/
config.redis.class = process.env.REDIS_CLASS || 'redis';
config.http.port = process.env.PORT || 3000;
config.cookie.secret = 'CHANGETHISPLEASE!!!';
config.USE_NOCK = process.env.USE_NOCK || 'false';
config.support = {};

config.roles = {
  users: {
    name: 'users',
    description: 'Minimum access, required to login',
    groups: ['users'],
    users: ['bob']
  },
  sales: {
    name: 'sales',
    description: 'Provides access to lead and account management functionality. Also provides read-only access to monitoring.',
    groups: ['sales'],
    users: ['bob']
  },
  executive: {
    name: 'executive',
    description: 'Provides access to executive reporting and dashboards.',
    groups: ['execs'],
    users: ['bob']
  },
  helpdesk: {
    name: 'helpdesk',
    description: 'Provides access to helpdesk functionality. Also provides read-only access to monitoring.',
    groups: ['engineers'],
    users: ['bob']
  },
  monitoring: {
    name: 'monitoring',
    description: 'Provides additional access to monitoring systems.',
    groups: ['engineers', 'execs'],
    users: ['bob']
  },
  admin: {
    name: 'admin',
    description: 'Provides full access to sales, monitoring and helpdesk functionality.',
    groups: ['admin'],
    users: ['bob']
  },
  super: {
    name: 'super',
    description: 'Provides access to administrative functions.',
    groups: ['ops'],
    users: ['bob']
  }
};

var signatureTemplate = "Ticket submitted via CloudyKangaroo - https://github.com/CloudyKangaroo/CloudyKangaroo";

config.support.signatureTemplate = signatureTemplate;

module.exports = config;
<|endoftext|>


<commit_before><commit_msg>cancel order<commit_after><|endoftext|>