'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (
      <div is="app">
        <Header />
      </div>
    );
  }
}

export default ReactCSS(Felony);

'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';
import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (
      <div is="app">
        <Header />
        <FloatingButtonToggle />
      </div>
    );
  }
}

export default ReactCSS(Felony);

Add floating button toggle to main

Add floating button toggle to main

--- src/components/Felony.js
+++ src/components/Felony.js
@@ -9,6 +9,7 @@
 import '../styles/felony.css!';

 import Header from './header/Header';
+import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

 export class Felony extends Component {
   classes() {
@@ -26,6 +27,7 @@
     return (
       <div is="app">
         <Header />
+        <FloatingButtonToggle />
       </div>
     );
   }

'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';
import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (
      <div is="app">
        <Header />
      </div>
    );
  }
}

export default ReactCSS(Felony);

<|original_code|>
'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (

    );
  }
}

export default ReactCSS(Felony);

<|edits_diff|>
--- src/components/Felony.js
+++ src/components/Felony.js
@@ -9,6 +9,7 @@
 import '../styles/felony.css!';

 import Header from './header/Header';
+import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

 export class Felony extends Component {
   classes() {
<|current_version|>
'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';
import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (

    );
  }
}

export default ReactCSS(Felony);

<|next_version|>
'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';
import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (

        <FloatingButtonToggle />

    );
  }
}

export default ReactCSS(Felony);


Add comments to JS functions

Add comments to JS functions

--- project/src/main/webapp/script.js
+++ project/src/main/webapp/script.js
@@ -1,3 +1,4 @@
+/** Updates trend in carousel. */
 function switchTrend(val) {
   var trends = document.getElementsByClassName('trends');
   var i = 0;
@@ -13,6 +14,7 @@
   }
 }

+/** Returns next trend in carousel. */
 function getNextTrend(trend, val) {
   var nextSlide = -1;
   var currentTrendVal = parseInt(trend.getAttribute('value'));

<|original_code|>
function switchTrend(val) {
  var trends = document.getElementsByClassName('trends');
  var i = 0;
  var updatedCurrentSlide = false;
  while(i < trends.length && !updatedCurrentSlide) {
    if(trends[i].style.display === 'block') {
      var nextTrend = getNextTrend(trends[i],val);
      trends[i].style.display = 'none';
      nextTrend.style.display = 'block';
      updatedCurrentSlide = true;
    }
    i+=1;
  }
}

function getNextTrend(trend, val) {
  var nextSlide = -1;
  var currentTrendVal = parseInt(trend.getAttribute('value'));
  // Clicking left on the first slide returns to last slide
  if (currentTrendVal + val === 0) {
    nextSlide = 4;
  // Clicking right on the last slide returns to first slide
  } else if (currentTrendVal + val === 5) {
    nextSlide = 1;
  } else {
    nextSlide = currentTrendVal + val;
  }
  return document.getElementById('trend-' + nextSlide);
}

<|edits_diff|>
--- project/src/main/webapp/script.js
+++ project/src/main/webapp/script.js
@@ -1,3 +1,4 @@
+/** Updates trend in carousel. */
 function switchTrend(val) {
   var trends = document.getElementsByClassName('trends');
   var i = 0;
<|current_version|>
/** Updates trend in carousel. */
function switchTrend(val) {
  var trends = document.getElementsByClassName('trends');
  var i = 0;
  var updatedCurrentSlide = false;
  while(i < trends.length && !updatedCurrentSlide) {
    if(trends[i].style.display === 'block') {
      var nextTrend = getNextTrend(trends[i],val);
      trends[i].style.display = 'none';
      nextTrend.style.display = 'block';
      updatedCurrentSlide = true;
    }
    i+=1;
  }
}

function getNextTrend(trend, val) {
  var nextSlide = -1;
  var currentTrendVal = parseInt(trend.getAttribute('value'));
  // Clicking left on the first slide returns to last slide
  if (currentTrendVal + val === 0) {
    nextSlide = 4;
  // Clicking right on the last slide returns to first slide
  } else if (currentTrendVal + val === 5) {
    nextSlide = 1;
  } else {
    nextSlide = currentTrendVal + val;
  }
  return document.getElementById('trend-' + nextSlide);
}

<|next_version|>
/** Updates trend in carousel. */
function switchTrend(val) {
  var trends = document.getElementsByClassName('trends');
  var i = 0;
  var updatedCurrentSlide = false;
  while(i < trends.length && !updatedCurrentSlide) {
    if(trends[i].style.display === 'block') {
      var nextTrend = getNextTrend(trends[i],val);
      trends[i].style.display = 'none';
      nextTrend.style.display = 'block';
      updatedCurrentSlide = true;
    }
    i+=1;
  }
}

/** Returns next trend in carousel. */
function getNextTrend(trend, val) {
  var nextSlide = -1;
  var currentTrendVal = parseInt(trend.getAttribute('value'));
  // Clicking left on the first slide returns to last slide
  if (currentTrendVal + val === 0) {
    nextSlide = 4;
  // Clicking right on the last slide returns to first slide
  } else if (currentTrendVal + val === 5) {
    nextSlide = 1;
  } else {
    nextSlide = currentTrendVal + val;
  }
  return document.getElementById('trend-' + nextSlide);
}


Add comments to every method.

Add comments to every method.

--- js/inputmanager.js
+++ js/inputmanager.js
@@ -8,10 +8,12 @@

 }

+/* Store the game-related keycodes to listen for */
 InputManager.prototype.setKeyMap = function(keyMap) {
     this.km = keyMap;
 }

+/* Defines the comm pipeline to take when a relavent event is captured */
 InputManager.prototype.register = function(event, callback) {
     switch(event) {
         case 'action':      this.notify = callback;     break;
@@ -22,10 +24,12 @@
     }
 }

+/* Register the event filter with the browser */
 InputManager.prototype.listen = function() {
     document.addEventListener('keydown', this.keyHandler.bind(this));
 }

+/* The filter to use to get only game-related events */
 InputManager.prototype.keyHandler = function(e) {
     switch(e.keyCode) {
         case this.km.LEFT:

<|original_code|>
function InputManager() {
    this.km;

    this.notify;
    this.newGame;
    this.quitGame;
    this.pauseGame;

}

InputManager.prototype.setKeyMap = function(keyMap) {
    this.km = keyMap;
}

InputManager.prototype.register = function(event, callback) {
    switch(event) {
        case 'action':      this.notify = callback;     break;
        case 'newgame':     this.newGame = callback;    break;
        case 'quitgame':    this.quitGame = callback;   break;
        case 'pausegame':   this.pauseGame = callback;  break;

    }
}

InputManager.prototype.listen = function() {
    document.addEventListener('keydown', this.keyHandler.bind(this));
}

InputManager.prototype.keyHandler = function(e) {
    switch(e.keyCode) {
        case this.km.LEFT:
        case this.km.RIGHT:
        case this.km.DOWN:
        case this.km.DROP:
        case this.km.RTURN:
        case this.km.LTURN:
            this.notify(e.keyCode);
            break;
        case this.km.NEW:
            this.newGame();
            break;
        case this.km.QUIT:
            this.quitGame();
            break;
        case this.km.PAUSE:
            this.pauseGame();
            break;
    }
}

<|edits_diff|>
--- js/inputmanager.js
+++ js/inputmanager.js
@@ -8,10 +8,12 @@

 }

+/* Store the game-related keycodes to listen for */
 InputManager.prototype.setKeyMap = function(keyMap) {
     this.km = keyMap;
 }

+/* Defines the comm pipeline to take when a relavent event is captured */
 InputManager.prototype.register = function(event, callback) {
     switch(event) {
         case 'action':      this.notify = callback;     break;
@@ -22,6 +24,7 @@
     }
 }

+/* Register the event filter with the browser */
 InputManager.prototype.listen = function() {
     document.addEventListener('keydown', this.keyHandler.bind(this));
 }
<|current_version|>
function InputManager() {
    this.km;

    this.notify;
    this.newGame;
    this.quitGame;
    this.pauseGame;

}

/* Store the game-related keycodes to listen for */
InputManager.prototype.setKeyMap = function(keyMap) {
    this.km = keyMap;
}

/* Defines the comm pipeline to take when a relavent event is captured */
InputManager.prototype.register = function(event, callback) {
    switch(event) {
        case 'action':      this.notify = callback;     break;
        case 'newgame':     this.newGame = callback;    break;
        case 'quitgame':    this.quitGame = callback;   break;
        case 'pausegame':   this.pauseGame = callback;  break;

    }
}

/* Register the event filter with the browser */
InputManager.prototype.listen = function() {
    document.addEventListener('keydown', this.keyHandler.bind(this));
}

InputManager.prototype.keyHandler = function(e) {
    switch(e.keyCode) {
        case this.km.LEFT:
        case this.km.RIGHT:
        case this.km.DOWN:
        case this.km.DROP:
        case this.km.RTURN:
        case this.km.LTURN:
            this.notify(e.keyCode);
            break;
        case this.km.NEW:
            this.newGame();
            break;
        case this.km.QUIT:
            this.quitGame();
            break;
        case this.km.PAUSE:
            this.pauseGame();
            break;
    }
}

<|next_version|>
function InputManager() {
    this.km;

    this.notify;
    this.newGame;
    this.quitGame;
    this.pauseGame;

}

/* Store the game-related keycodes to listen for */
InputManager.prototype.setKeyMap = function(keyMap) {
    this.km = keyMap;
}

/* Defines the comm pipeline to take when a relavent event is captured */
InputManager.prototype.register = function(event, callback) {
    switch(event) {
        case 'action':      this.notify = callback;     break;
        case 'newgame':     this.newGame = callback;    break;
        case 'quitgame':    this.quitGame = callback;   break;
        case 'pausegame':   this.pauseGame = callback;  break;

    }
}

/* Register the event filter with the browser */
InputManager.prototype.listen = function() {
    document.addEventListener('keydown', this.keyHandler.bind(this));
}

/* The filter to use to get only game-related events */
InputManager.prototype.keyHandler = function(e) {
    switch(e.keyCode) {
        case this.km.LEFT:
        case this.km.RIGHT:
        case this.km.DOWN:
        case this.km.DROP:
        case this.km.RTURN:
        case this.km.LTURN:
            this.notify(e.keyCode);
            break;
        case this.km.NEW:
            this.newGame();
            break;
        case this.km.QUIT:
            this.quitGame();
            break;
        case this.km.PAUSE:
            this.pauseGame();
            break;
    }
}


Add exit validation of message receipt.

Add exit validation of message receipt.

--- test/test-simple.js
+++ test/test-simple.js
@@ -6,6 +6,8 @@
 var sys = require('sys');
 var Worker = require('webworker').Worker;

+var receivedMsg = false;
+
 var w = new Worker(path.join(__dirname, 'workers', 'simple.js'));

 w.onmessage = function(e) {
@@ -13,7 +15,13 @@
     assert.equal(e.data.bar, 'foo');
     assert.equal(e.data.bunkle, 'baz');

+    receivedMsg = true;
+
     w.terminate();
 };

 w.postMessage({'foo' : 'bar', 'baz' : 'bunkle'});
+
+process.addListener('exit', function() {
+    assert.equal(receivedMsg, true);
+});

<|original_code|>
// Verify that we can spawn a worker, send and receive a simple message, and
// kill it.

var assert = require('assert');
var path = require('path');
var sys = require('sys');
var Worker = require('webworker').Worker;

var w = new Worker(path.join(__dirname, 'workers', 'simple.js'));

w.onmessage = function(e) {
    assert.ok('data' in e);
    assert.equal(e.data.bar, 'foo');
    assert.equal(e.data.bunkle, 'baz');

    w.terminate();
};

w.postMessage({'foo' : 'bar', 'baz' : 'bunkle'});

<|edits_diff|>
--- test/test-simple.js
+++ test/test-simple.js
@@ -6,6 +6,8 @@
 var sys = require('sys');
 var Worker = require('webworker').Worker;

+var receivedMsg = false;
+
 var w = new Worker(path.join(__dirname, 'workers', 'simple.js'));

 w.onmessage = function(e) {
@@ -13,6 +15,8 @@
     assert.equal(e.data.bar, 'foo');
     assert.equal(e.data.bunkle, 'baz');

+    receivedMsg = true;
+
     w.terminate();
 };

<|current_version|>
// Verify that we can spawn a worker, send and receive a simple message, and
// kill it.

var assert = require('assert');
var path = require('path');
var sys = require('sys');
var Worker = require('webworker').Worker;

var receivedMsg = false;

var w = new Worker(path.join(__dirname, 'workers', 'simple.js'));

w.onmessage = function(e) {
    assert.ok('data' in e);
    assert.equal(e.data.bar, 'foo');
    assert.equal(e.data.bunkle, 'baz');

    receivedMsg = true;

    w.terminate();
};

w.postMessage({'foo' : 'bar', 'baz' : 'bunkle'});

<|next_version|>
// Verify that we can spawn a worker, send and receive a simple message, and
// kill it.

var assert = require('assert');
var path = require('path');
var sys = require('sys');
var Worker = require('webworker').Worker;

var receivedMsg = false;

var w = new Worker(path.join(__dirname, 'workers', 'simple.js'));

w.onmessage = function(e) {
    assert.ok('data' in e);
    assert.equal(e.data.bar, 'foo');
    assert.equal(e.data.bunkle, 'baz');

    receivedMsg = true;

    w.terminate();
};

w.postMessage({'foo' : 'bar', 'baz' : 'bunkle'});

process.addListener('exit', function() {
    assert.equal(receivedMsg, true);
});


Add Fieldset Text Factory For DSL

Add Fieldset Text Factory For DSL

--- src/factories.js
+++ src/factories.js
@@ -4,9 +4,11 @@
 import Submit from "./components/submit.js"
 import FormErrorList from "./components/form_error_list.js"
 import Fieldset from "./components/fieldset.js"
+import FieldsetText from "./components/fieldset_text.js"

 export const form = React.createFactory(Form)
 export const input = React.createFactory(Input)
 export const submit = React.createFactory(Submit)
 export const formErrorList = React.createFactory(FormErrorList)
 export const fieldset = React.createFactory(Fieldset)
+export const fieldsetText = React.createFactory(FieldsetText)

<|original_code|>
import React from "react"
import Form from "./components/form.js"
import Input from "./components/input.js"
import Submit from "./components/submit.js"
import FormErrorList from "./components/form_error_list.js"
import Fieldset from "./components/fieldset.js"

export const form = React.createFactory(Form)
export const input = React.createFactory(Input)
export const submit = React.createFactory(Submit)
export const formErrorList = React.createFactory(FormErrorList)
export const fieldset = React.createFactory(Fieldset)

<|edits_diff|>
--- src/factories.js
+++ src/factories.js
@@ -4,6 +4,7 @@
 import Submit from "./components/submit.js"
 import FormErrorList from "./components/form_error_list.js"
 import Fieldset from "./components/fieldset.js"
+import FieldsetText from "./components/fieldset_text.js"

 export const form = React.createFactory(Form)
 export const input = React.createFactory(Input)
<|current_version|>
import React from "react"
import Form from "./components/form.js"
import Input from "./components/input.js"
import Submit from "./components/submit.js"
import FormErrorList from "./components/form_error_list.js"
import Fieldset from "./components/fieldset.js"
import FieldsetText from "./components/fieldset_text.js"

export const form = React.createFactory(Form)
export const input = React.createFactory(Input)
export const submit = React.createFactory(Submit)
export const formErrorList = React.createFactory(FormErrorList)
export const fieldset = React.createFactory(Fieldset)

<|next_version|>
import React from "react"
import Form from "./components/form.js"
import Input from "./components/input.js"
import Submit from "./components/submit.js"
import FormErrorList from "./components/form_error_list.js"
import Fieldset from "./components/fieldset.js"
import FieldsetText from "./components/fieldset_text.js"

export const form = React.createFactory(Form)
export const input = React.createFactory(Input)
export const submit = React.createFactory(Submit)
export const formErrorList = React.createFactory(FormErrorList)
export const fieldset = React.createFactory(Fieldset)
export const fieldsetText = React.createFactory(FieldsetText)


Add css processing to `gulp build`

Add css processing to `gulp build`

--- gulpfile.js
+++ gulpfile.js
@@ -1,5 +1,7 @@
 const babel = require('gulp-babel');
+const cssnano = require('cssnano');
 const gulp = require('gulp');
+const postcss = require('gulp-postcss');
 const pug = require('gulp-pug');
 const uglify = require('gulp-uglify');

@@ -8,6 +10,10 @@
 		.pipe(pug())
 		.pipe(gulp.dest('app/dist'));

+	gulp.src('app/src/css/*')
+		.pipe(postcss([cssnano]))
+		.pipe(gulp.dest('app/dist'));
+
 	gulp.src('app/src/js/*')
 		.pipe(babel({presets: ['es2015']}))
 		.pipe(uglify())

<|original_code|>
const babel = require('gulp-babel');
const gulp = require('gulp');
const pug = require('gulp-pug');
const uglify = require('gulp-uglify');

gulp.task('build', () => {
	gulp.src('app/src/pug/*')
		.pipe(pug())
		.pipe(gulp.dest('app/dist'));

	gulp.src('app/src/js/*')
		.pipe(babel({presets: ['es2015']}))
		.pipe(uglify())
		.pipe(gulp.dest('app/dist'));
});

<|edits_diff|>
--- gulpfile.js
+++ gulpfile.js
@@ -1,5 +1,7 @@
 const babel = require('gulp-babel');
+const cssnano = require('cssnano');
 const gulp = require('gulp');
+const postcss = require('gulp-postcss');
 const pug = require('gulp-pug');
 const uglify = require('gulp-uglify');

<|current_version|>
const babel = require('gulp-babel');
const cssnano = require('cssnano');
const gulp = require('gulp');
const postcss = require('gulp-postcss');
const pug = require('gulp-pug');
const uglify = require('gulp-uglify');

gulp.task('build', () => {
	gulp.src('app/src/pug/*')
		.pipe(pug())
		.pipe(gulp.dest('app/dist'));

	gulp.src('app/src/js/*')
		.pipe(babel({presets: ['es2015']}))
		.pipe(uglify())
		.pipe(gulp.dest('app/dist'));
});

<|next_version|>
const babel = require('gulp-babel');
const cssnano = require('cssnano');
const gulp = require('gulp');
const postcss = require('gulp-postcss');
const pug = require('gulp-pug');
const uglify = require('gulp-uglify');

gulp.task('build', () => {
	gulp.src('app/src/pug/*')
		.pipe(pug())
		.pipe(gulp.dest('app/dist'));

	gulp.src('app/src/css/*')
		.pipe(postcss([cssnano]))
		.pipe(gulp.dest('app/dist'));

	gulp.src('app/src/js/*')
		.pipe(babel({presets: ['es2015']}))
		.pipe(uglify())
		.pipe(gulp.dest('app/dist'));
});


Add test task to gulp

Add test task to gulp

--- gulpfile.js
+++ gulpfile.js
@@ -6,6 +6,10 @@
 var concat = require('gulp-concat');
 var sourcemaps = require('gulp-sourcemaps');
 var babel = require('gulp-babel');
+require('babel-core/register');
+// testing
+var mocha = require('gulp-mocha');
+

 gulp.task('babel', function() {
     return gulp.src('app/Resources/client/jsx/project/details/*.jsx')
@@ -14,6 +18,11 @@
         }))
         .pipe(concat('details.js'))
         .pipe(gulp.dest('web/assets/js/project'));
+});
+
+gulp.task('test', function() {
+    return gulp.src('tests/jsx/**/*.js', {read: false})
+        .pipe(mocha({reporter: 'spec', useColors: true}))
 });

 gulp.task('sass', function () {

<|original_code|>
'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');
var sassLint = require('gulp-sass-lint');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');
var babel = require('gulp-babel');

gulp.task('babel', function() {
    return gulp.src('app/Resources/client/jsx/project/details/*.jsx')
        .pipe(babel({
            presets: ['es2015', 'react']
        }))
        .pipe(concat('details.js'))
        .pipe(gulp.dest('web/assets/js/project'));
});

gulp.task('sass', function () {
  return gulp.src('web/assets/scss/*.scss')
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(sourcemaps.write('.', {includeContent: false}))
    .pipe(gulp.dest('web/assets/css'));
});

gulp.task('sassLint', function() {
  gulp.src('web/assets/scss/*.s+(a|c)ss')
    .pipe(sassLint())
    .pipe(sassLint.format())
    .pipe(sassLint.failOnError());
});

gulp.task('css', ['sassLint','sass'], function () {
});

gulp.task('default', ['css'], function() {
  // place code for your default task here
});

<|edits_diff|>
--- gulpfile.js
+++ gulpfile.js
@@ -6,6 +6,10 @@
 var concat = require('gulp-concat');
 var sourcemaps = require('gulp-sourcemaps');
 var babel = require('gulp-babel');
+require('babel-core/register');
+// testing
+var mocha = require('gulp-mocha');
+

 gulp.task('babel', function() {
     return gulp.src('app/Resources/client/jsx/project/details/*.jsx')
<|current_version|>
'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');
var sassLint = require('gulp-sass-lint');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');
var babel = require('gulp-babel');
require('babel-core/register');
// testing
var mocha = require('gulp-mocha');

gulp.task('babel', function() {
    return gulp.src('app/Resources/client/jsx/project/details/*.jsx')
        .pipe(babel({
            presets: ['es2015', 'react']
        }))
        .pipe(concat('details.js'))
        .pipe(gulp.dest('web/assets/js/project'));
});

gulp.task('sass', function () {
  return gulp.src('web/assets/scss/*.scss')
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(sourcemaps.write('.', {includeContent: false}))
    .pipe(gulp.dest('web/assets/css'));
});

gulp.task('sassLint', function() {
  gulp.src('web/assets/scss/*.s+(a|c)ss')
    .pipe(sassLint())
    .pipe(sassLint.format())
    .pipe(sassLint.failOnError());
});

gulp.task('css', ['sassLint','sass'], function () {
});

gulp.task('default', ['css'], function() {
  // place code for your default task here
});

<|next_version|>
'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');
var sassLint = require('gulp-sass-lint');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');
var babel = require('gulp-babel');
require('babel-core/register');
// testing
var mocha = require('gulp-mocha');

gulp.task('babel', function() {
    return gulp.src('app/Resources/client/jsx/project/details/*.jsx')
        .pipe(babel({
            presets: ['es2015', 'react']
        }))
        .pipe(concat('details.js'))
        .pipe(gulp.dest('web/assets/js/project'));
});

gulp.task('test', function() {
    return gulp.src('tests/jsx/**/*.js', {read: false})
        .pipe(mocha({reporter: 'spec', useColors: true}))
});

gulp.task('sass', function () {
  return gulp.src('web/assets/scss/*.scss')
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(sourcemaps.write('.', {includeContent: false}))
    .pipe(gulp.dest('web/assets/css'));
});

gulp.task('sassLint', function() {
  gulp.src('web/assets/scss/*.s+(a|c)ss')
    .pipe(sassLint())
    .pipe(sassLint.format())
    .pipe(sassLint.failOnError());
});

gulp.task('css', ['sassLint','sass'], function () {
});

gulp.task('default', ['css'], function() {
  // place code for your default task here
});


Add Event Listener to window.resize

Add Event Listener to window.resize

--- content.js
+++ content.js
@@ -17,7 +17,13 @@
     return {success: success, x1: x1, y1: y1, x2: x2, y2: y2};
 }

+// A side note: use event listener, not inline event handlers (e.g., "onclick")
+// new inline events could overwrite any existing inline event handlers

 document.addEventListener("mouseup", function(event) {
     chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
 });
+
+window.addEventListener("resize", function(event) {
+    chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
+});

<|original_code|>
//Get the begin and end coordinates of selction
function getSelectionEnds() {
    var success = false, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    var sel = window.getSelection()
    if (sel.rangeCount > 0){
        var range_rects = sel.getRangeAt(0).getClientRects();
        if (range_rects.length > 0){ //fail if zero
            success = true;
            var rect_first = range_rects[0];
            x1 = rect_first.left;
            y1 = rect_first.top;
            var rect_last = range_rects[range_rects.length - 1];
            x2 = rect_last.right;
            y2 = rect_last.bottom;
        }
    }
    return {success: success, x1: x1, y1: y1, x2: x2, y2: y2};
}

document.addEventListener("mouseup", function(event) {
    chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
});

<|edits_diff|>
--- content.js
+++ content.js
@@ -17,6 +17,8 @@
     return {success: success, x1: x1, y1: y1, x2: x2, y2: y2};
 }

+// A side note: use event listener, not inline event handlers (e.g., "onclick")
+// new inline events could overwrite any existing inline event handlers

 document.addEventListener("mouseup", function(event) {
     chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
<|current_version|>
//Get the begin and end coordinates of selction
function getSelectionEnds() {
    var success = false, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    var sel = window.getSelection()
    if (sel.rangeCount > 0){
        var range_rects = sel.getRangeAt(0).getClientRects();
        if (range_rects.length > 0){ //fail if zero
            success = true;
            var rect_first = range_rects[0];
            x1 = rect_first.left;
            y1 = rect_first.top;
            var rect_last = range_rects[range_rects.length - 1];
            x2 = rect_last.right;
            y2 = rect_last.bottom;
        }
    }
    return {success: success, x1: x1, y1: y1, x2: x2, y2: y2};
}

// A side note: use event listener, not inline event handlers (e.g., "onclick")
// new inline events could overwrite any existing inline event handlers

document.addEventListener("mouseup", function(event) {
    chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
});

<|next_version|>
//Get the begin and end coordinates of selction
function getSelectionEnds() {
    var success = false, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    var sel = window.getSelection()
    if (sel.rangeCount > 0){
        var range_rects = sel.getRangeAt(0).getClientRects();
        if (range_rects.length > 0){ //fail if zero
            success = true;
            var rect_first = range_rects[0];
            x1 = rect_first.left;
            y1 = rect_first.top;
            var rect_last = range_rects[range_rects.length - 1];
            x2 = rect_last.right;
            y2 = rect_last.bottom;
        }
    }
    return {success: success, x1: x1, y1: y1, x2: x2, y2: y2};
}

// A side note: use event listener, not inline event handlers (e.g., "onclick")
// new inline events could overwrite any existing inline event handlers

document.addEventListener("mouseup", function(event) {
    chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
});

window.addEventListener("resize", function(event) {
    chrome.runtime.sendMessage(getSelectionEnds(), function(response) {});
});


Reset search state on reset action

Reset search state on reset action

--- src/ui/reducers/Search.js
+++ src/ui/reducers/Search.js
@@ -1,4 +1,5 @@
 import { SET_COMPLETION, SET_BODY, SET_PAGE, SET_RESULTS_PER_PAGE } from '../actions/Search'
+import { SEARCH_REQUEST_RESET } from '../../api/actions/query'

 const initialState = {
   completion: '',
@@ -21,6 +22,9 @@
   case SET_RESULTS_PER_PAGE:
     return { ...state, resultsPerPage: action.resultsPerPage }

+  case SEARCH_REQUEST_RESET:
+    return { ...initialState }
+
   default:
     return state
   }

<|original_code|>
import { SET_COMPLETION, SET_BODY, SET_PAGE, SET_RESULTS_PER_PAGE } from '../actions/Search'

const initialState = {
  completion: '',
  body: '',
  page: 1,
  resultsPerPage: 10
}

function search(state = initialState, action) {
  switch (action.type) {
  case SET_COMPLETION:
    return { ...state, completion: action.completion }

  case SET_BODY:
    return { ...state, body: action.body }

  case SET_PAGE:
    return { ...state, page: action.page }

  case SET_RESULTS_PER_PAGE:
    return { ...state, resultsPerPage: action.resultsPerPage }

  default:
    return state
  }
}

export default search

<|edits_diff|>
--- src/ui/reducers/Search.js
+++ src/ui/reducers/Search.js
@@ -1,4 +1,5 @@
 import { SET_COMPLETION, SET_BODY, SET_PAGE, SET_RESULTS_PER_PAGE } from '../actions/Search'
+import { SEARCH_REQUEST_RESET } from '../../api/actions/query'

 const initialState = {
   completion: '',
<|current_version|>
import { SET_COMPLETION, SET_BODY, SET_PAGE, SET_RESULTS_PER_PAGE } from '../actions/Search'
import { SEARCH_REQUEST_RESET } from '../../api/actions/query'

const initialState = {
  completion: '',
  body: '',
  page: 1,
  resultsPerPage: 10
}

function search(state = initialState, action) {
  switch (action.type) {
  case SET_COMPLETION:
    return { ...state, completion: action.completion }

  case SET_BODY:
    return { ...state, body: action.body }

  case SET_PAGE:
    return { ...state, page: action.page }

  case SET_RESULTS_PER_PAGE:
    return { ...state, resultsPerPage: action.resultsPerPage }

  default:
    return state
  }
}

export default search

<|next_version|>
import { SET_COMPLETION, SET_BODY, SET_PAGE, SET_RESULTS_PER_PAGE } from '../actions/Search'
import { SEARCH_REQUEST_RESET } from '../../api/actions/query'

const initialState = {
  completion: '',
  body: '',
  page: 1,
  resultsPerPage: 10
}

function search(state = initialState, action) {
  switch (action.type) {
  case SET_COMPLETION:
    return { ...state, completion: action.completion }

  case SET_BODY:
    return { ...state, body: action.body }

  case SET_PAGE:
    return { ...state, page: action.page }

  case SET_RESULTS_PER_PAGE:
    return { ...state, resultsPerPage: action.resultsPerPage }

  case SEARCH_REQUEST_RESET:
    return { ...initialState }

  default:
    return state
  }
}

export default search


Add proper exporting of programStrings

Add proper exporting of programStrings

--- src/localization/utilities.js
+++ src/localization/utilities.js
@@ -11,6 +11,7 @@
 import { pageInfoStrings } from './pageInfoStrings';
 import { syncStrings } from './syncStrings';
 import { tableStrings } from './tableStrings';
+import { programStrings } from './programStrings';

 export function setCurrentLanguage(language) {
   authStrings.setLanguage(language);
@@ -21,6 +22,7 @@
   pageInfoStrings.setLanguage(language);
   tableStrings.setLanguage(language);
   syncStrings.setLanguage(language);
+  programStrings.setLanguage(language);
 }

 export default setCurrentLanguage;

<|original_code|>
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { authStrings } from './authStrings';
import { buttonStrings } from './buttonStrings';
import { generalStrings } from './generalStrings';
import { modalStrings } from './modalStrings';
import { navStrings } from './navStrings';
import { pageInfoStrings } from './pageInfoStrings';
import { syncStrings } from './syncStrings';
import { tableStrings } from './tableStrings';

export function setCurrentLanguage(language) {
  authStrings.setLanguage(language);
  buttonStrings.setLanguage(language);
  generalStrings.setLanguage(language);
  modalStrings.setLanguage(language);
  navStrings.setLanguage(language);
  pageInfoStrings.setLanguage(language);
  tableStrings.setLanguage(language);
  syncStrings.setLanguage(language);
}

export default setCurrentLanguage;

<|edits_diff|>
--- src/localization/utilities.js
+++ src/localization/utilities.js
@@ -11,6 +11,7 @@
 import { pageInfoStrings } from './pageInfoStrings';
 import { syncStrings } from './syncStrings';
 import { tableStrings } from './tableStrings';
+import { programStrings } from './programStrings';

 export function setCurrentLanguage(language) {
   authStrings.setLanguage(language);
<|current_version|>
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { authStrings } from './authStrings';
import { buttonStrings } from './buttonStrings';
import { generalStrings } from './generalStrings';
import { modalStrings } from './modalStrings';
import { navStrings } from './navStrings';
import { pageInfoStrings } from './pageInfoStrings';
import { syncStrings } from './syncStrings';
import { tableStrings } from './tableStrings';
import { programStrings } from './programStrings';

export function setCurrentLanguage(language) {
  authStrings.setLanguage(language);
  buttonStrings.setLanguage(language);
  generalStrings.setLanguage(language);
  modalStrings.setLanguage(language);
  navStrings.setLanguage(language);
  pageInfoStrings.setLanguage(language);
  tableStrings.setLanguage(language);
  syncStrings.setLanguage(language);
}

export default setCurrentLanguage;

<|next_version|>
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { authStrings } from './authStrings';
import { buttonStrings } from './buttonStrings';
import { generalStrings } from './generalStrings';
import { modalStrings } from './modalStrings';
import { navStrings } from './navStrings';
import { pageInfoStrings } from './pageInfoStrings';
import { syncStrings } from './syncStrings';
import { tableStrings } from './tableStrings';
import { programStrings } from './programStrings';

export function setCurrentLanguage(language) {
  authStrings.setLanguage(language);
  buttonStrings.setLanguage(language);
  generalStrings.setLanguage(language);
  modalStrings.setLanguage(language);
  navStrings.setLanguage(language);
  pageInfoStrings.setLanguage(language);
  tableStrings.setLanguage(language);
  syncStrings.setLanguage(language);
  programStrings.setLanguage(language);
}

export default setCurrentLanguage;


Add ensure_logged_in to onboarding middleware stack

--- apps/onboarding/index.js
+++ apps/onboarding/index.js
@@ -2,6 +2,7 @@
 import SearchBlocks from '../../collections/search_blocks';
 import { extend } from 'underscore';
 import apolloMiddleware from 'react/apollo/middleware';
+import ensureLoggedInMiddleware from 'lib/middleware/ensure_logged_in.coffee';
 import setOnboardingComponentMiddleware from 'apps/onboarding/middleware/setOnboardingComponent';

 const app = express();
@@ -14,6 +15,7 @@
 };

 const middlewareStack = [
+  ensureLoggedInMiddleware,
   apolloMiddleware,
   setOnboardingComponentMiddleware
 ];

<|original_code|>
import express from 'express';
import SearchBlocks from '../../collections/search_blocks';
import { extend } from 'underscore';
import apolloMiddleware from 'react/apollo/middleware';
import setOnboardingComponentMiddleware from 'apps/onboarding/middleware/setOnboardingComponent';

const app = express();

app.set('views', `${__dirname}/templates`);
app.set('view engine', 'jade');

const renderOnboarding = (req, res, next) => {
  res.render('index');
};

const middlewareStack = [
  apolloMiddleware,
  setOnboardingComponentMiddleware
];

app.get('/welcome', ...middlewareStack, renderOnboarding);

module.exports = app;

<|edits_diff|>
--- apps/onboarding/index.js
+++ apps/onboarding/index.js
@@ -2,6 +2,7 @@
 import SearchBlocks from '../../collections/search_blocks';
 import { extend } from 'underscore';
 import apolloMiddleware from 'react/apollo/middleware';
+import ensureLoggedInMiddleware from 'lib/middleware/ensure_logged_in.coffee';
 import setOnboardingComponentMiddleware from 'apps/onboarding/middleware/setOnboardingComponent';

 const app = express();
<|current_version|>
import express from 'express';
import SearchBlocks from '../../collections/search_blocks';
import { extend } from 'underscore';
import apolloMiddleware from 'react/apollo/middleware';
import ensureLoggedInMiddleware from 'lib/middleware/ensure_logged_in.coffee';
import setOnboardingComponentMiddleware from 'apps/onboarding/middleware/setOnboardingComponent';

const app = express();

app.set('views', `${__dirname}/templates`);
app.set('view engine', 'jade');

const renderOnboarding = (req, res, next) => {
  res.render('index');
};

const middlewareStack = [
  apolloMiddleware,
  setOnboardingComponentMiddleware
];

app.get('/welcome', ...middlewareStack, renderOnboarding);

module.exports = app;

<|next_version|>
import express from 'express';
import SearchBlocks from '../../collections/search_blocks';
import { extend } from 'underscore';
import apolloMiddleware from 'react/apollo/middleware';
import ensureLoggedInMiddleware from 'lib/middleware/ensure_logged_in.coffee';
import setOnboardingComponentMiddleware from 'apps/onboarding/middleware/setOnboardingComponent';

const app = express();

app.set('views', `${__dirname}/templates`);
app.set('view engine', 'jade');

const renderOnboarding = (req, res, next) => {
  res.render('index');
};

const middlewareStack = [
  ensureLoggedInMiddleware,
  apolloMiddleware,
  setOnboardingComponentMiddleware
];

app.get('/welcome', ...middlewareStack, renderOnboarding);

module.exports = app;


Add additional polyfills required to make this work on original iPad

--- client/src/js/index.js
+++ client/src/js/index.js
@@ -1,5 +1,8 @@
+import 'core-js/es5';
 import 'core-js/es6/promise';
 import 'core-js/es6/symbol';
+import 'core-js/es6/array';
+
 import 'moment-timezone/moment-timezone';
 import 'moment/locale/ru';

<|original_code|>
import 'core-js/es6/promise';
import 'core-js/es6/symbol';
import 'moment-timezone/moment-timezone';
import 'moment/locale/ru';

import moment from 'moment';

import timezones from '../data/timezones.json';
import App from './core/app';

moment.tz.load(timezones);

document.addEventListener('DOMContentLoaded', (event) => {
  const app = new App();
  app.run();
});

<|edits_diff|>
--- client/src/js/index.js
+++ client/src/js/index.js
@@ -1,3 +1,4 @@
+import 'core-js/es5';
 import 'core-js/es6/promise';
 import 'core-js/es6/symbol';
 import 'moment-timezone/moment-timezone';
<|current_version|>
import 'core-js/es5';
import 'core-js/es6/promise';
import 'core-js/es6/symbol';
import 'moment-timezone/moment-timezone';
import 'moment/locale/ru';

import moment from 'moment';

import timezones from '../data/timezones.json';
import App from './core/app';

moment.tz.load(timezones);

document.addEventListener('DOMContentLoaded', (event) => {
  const app = new App();
  app.run();
});

<|next_version|>
import 'core-js/es5';
import 'core-js/es6/promise';
import 'core-js/es6/symbol';
import 'core-js/es6/array';

import 'moment-timezone/moment-timezone';
import 'moment/locale/ru';

import moment from 'moment';

import timezones from '../data/timezones.json';
import App from './core/app';

moment.tz.load(timezones);

document.addEventListener('DOMContentLoaded', (event) => {
  const app = new App();
  app.run();
});


Index con todas las rutinas

Index con todas las rutinas

--- routes/index.js
+++ routes/index.js
@@ -23,8 +23,12 @@

 //rutina de pistolas
 api.get('/getGuns', GunsController.getGuns)
+api.get('/getGun', GunsController.getGun)
+api.post('/createGun', GunsController.createGun)

 //rutina de disparos
 api.get('/getDisparo', DisparoController.getDisparo)
+api.get('/getOneDisparo', DisparoController.getOneDisparo)
+api.post('/createDisparo', DisparoController.createDisparo)

 module.exports = api

<|original_code|>
'use strict'

const express = require ('express')
const api = express.Router()

const UserController = require ('../Controllers/UserController')
const MatchController = require ('../Controllers/MatchController')
const GunsController = require ('../Controllers/GunController')
const DisparoController = require ('../Controllers/DisparoController')

//DEFINED ROUTES TO API METHODS

//rutina de usuarios
api.get('/getUsers', UserController.getUsers)
api.get('/getUser', UserController.getUser)
api.post('/createUser', UserController.createUser)

//rutina de partida
api.get('/getMatchs', MatchController.getMatchs)
api.get('/getMatch', MatchController.getMatch)
api.post('/createMatch', MatchController.createMatch)

//rutina de pistolas
api.get('/getGuns', GunsController.getGuns)

//rutina de disparos
api.get('/getDisparo', DisparoController.getDisparo)

module.exports = api

<|edits_diff|>
--- routes/index.js
+++ routes/index.js
@@ -23,6 +23,8 @@

 //rutina de pistolas
 api.get('/getGuns', GunsController.getGuns)
+api.get('/getGun', GunsController.getGun)
+api.post('/createGun', GunsController.createGun)

 //rutina de disparos
 api.get('/getDisparo', DisparoController.getDisparo)
<|current_version|>
'use strict'

const express = require ('express')
const api = express.Router()

const UserController = require ('../Controllers/UserController')
const MatchController = require ('../Controllers/MatchController')
const GunsController = require ('../Controllers/GunController')
const DisparoController = require ('../Controllers/DisparoController')

//DEFINED ROUTES TO API METHODS

//rutina de usuarios
api.get('/getUsers', UserController.getUsers)
api.get('/getUser', UserController.getUser)
api.post('/createUser', UserController.createUser)

//rutina de partida
api.get('/getMatchs', MatchController.getMatchs)
api.get('/getMatch', MatchController.getMatch)
api.post('/createMatch', MatchController.createMatch)

//rutina de pistolas
api.get('/getGuns', GunsController.getGuns)
api.get('/getGun', GunsController.getGun)
api.post('/createGun', GunsController.createGun)

//rutina de disparos
api.get('/getDisparo', DisparoController.getDisparo)

module.exports = api

<|next_version|>
'use strict'

const express = require ('express')
const api = express.Router()

const UserController = require ('../Controllers/UserController')
const MatchController = require ('../Controllers/MatchController')
const GunsController = require ('../Controllers/GunController')
const DisparoController = require ('../Controllers/DisparoController')

//DEFINED ROUTES TO API METHODS

//rutina de usuarios
api.get('/getUsers', UserController.getUsers)
api.get('/getUser', UserController.getUser)
api.post('/createUser', UserController.createUser)

//rutina de partida
api.get('/getMatchs', MatchController.getMatchs)
api.get('/getMatch', MatchController.getMatch)
api.post('/createMatch', MatchController.createMatch)

//rutina de pistolas
api.get('/getGuns', GunsController.getGuns)
api.get('/getGun', GunsController.getGun)
api.post('/createGun', GunsController.createGun)

//rutina de disparos
api.get('/getDisparo', DisparoController.getDisparo)
api.get('/getOneDisparo', DisparoController.getOneDisparo)
api.post('/createDisparo', DisparoController.createDisparo)

module.exports = api


Check - don't insert script tags twice.

Check - don't insert script tags twice.

--- Js/Core/Lib/Core/Page.js
+++ Js/Core/Lib/Core/Page.js
@@ -3,6 +3,10 @@
 class Page {
     loadScript(url) {
         return new Promise(resolve => {
+            // Is it already inserted, possibly with server-side rendering?
+            if (document.querySelectorAll(`script[src="${url}"]`).length) {
+                return;
+            }
             const s = document.createElement('script');
             s.type = 'text/javascript';
             s.src = url;
@@ -14,6 +18,10 @@

     loadStylesheet(url) {
         return new Promise(resolve => {
+            // Is it already inserted, possibly with server-side rendering?
+            if (document.querySelectorAll(`link[href="${url}"]`).length) {
+                return;
+            }
             const s = document.createElement('link');
             s.rel = 'stylesheet';
             s.href = url;

<|original_code|>
import _ from 'lodash';

class Page {
    loadScript(url) {
        return new Promise(resolve => {
            const s = document.createElement('script');
            s.type = 'text/javascript';
            s.src = url;
            s.async = true;
            s.onload = resolve;
            document.body.appendChild(s);
        });
    }

    loadStylesheet(url) {
        return new Promise(resolve => {
            const s = document.createElement('link');
            s.rel = 'stylesheet';
            s.href = url;
            s.onload = resolve;
            document.head.appendChild(s);
        });
    }

    setMeta(attributes) {
        let updatedExisting = false;
        _.each(['name', 'property'], name => {
            if (_.has(attributes, name)) {
                // Fetch existing element
                const element = document.querySelector(`meta[${name}="${attributes[name]}"]`);
                if (element) {
                    // If exists, update with new attributes
                    _.each(attributes, (value, key) => element.setAttribute(key, value));
                    updatedExisting = true;
                    return false;
                }
            }
        });

        if (updatedExisting) {
            return;
        }

        // Create new element
        const element = document.createElement('meta');
        _.each(attributes, (value, key) => element.setAttribute(key, value));
        document.head.appendChild(element);
    }

    setTitle(title) {
        document.title = title;
    }
}

export default Page;
<|edits_diff|>
--- Js/Core/Lib/Core/Page.js
+++ Js/Core/Lib/Core/Page.js
@@ -3,6 +3,10 @@
 class Page {
     loadScript(url) {
         return new Promise(resolve => {
+            // Is it already inserted, possibly with server-side rendering?
+            if (document.querySelectorAll(`script[src="${url}"]`).length) {
+                return;
+            }
             const s = document.createElement('script');
             s.type = 'text/javascript';
             s.src = url;
<|current_version|>
import _ from 'lodash';

class Page {
    loadScript(url) {
        return new Promise(resolve => {
            // Is it already inserted, possibly with server-side rendering?
            if (document.querySelectorAll(`script[src="${url}"]`).length) {
                return;
            }
            const s = document.createElement('script');
            s.type = 'text/javascript';
            s.src = url;
            s.async = true;
            s.onload = resolve;
            document.body.appendChild(s);
        });
    }

    loadStylesheet(url) {
        return new Promise(resolve => {
            const s = document.createElement('link');
            s.rel = 'stylesheet';
            s.href = url;
            s.onload = resolve;
            document.head.appendChild(s);
        });
    }

    setMeta(attributes) {
        let updatedExisting = false;
        _.each(['name', 'property'], name => {
            if (_.has(attributes, name)) {
                // Fetch existing element
                const element = document.querySelector(`meta[${name}="${attributes[name]}"]`);
                if (element) {
                    // If exists, update with new attributes
                    _.each(attributes, (value, key) => element.setAttribute(key, value));
                    updatedExisting = true;
                    return false;
                }
            }
        });

        if (updatedExisting) {
            return;
        }

        // Create new element
        const element = document.createElement('meta');
        _.each(attributes, (value, key) => element.setAttribute(key, value));
        document.head.appendChild(element);
    }

    setTitle(title) {
        document.title = title;
    }
}

export default Page;
<|next_version|>
import _ from 'lodash';

class Page {
    loadScript(url) {
        return new Promise(resolve => {
            // Is it already inserted, possibly with server-side rendering?
            if (document.querySelectorAll(`script[src="${url}"]`).length) {
                return;
            }
            const s = document.createElement('script');
            s.type = 'text/javascript';
            s.src = url;
            s.async = true;
            s.onload = resolve;
            document.body.appendChild(s);
        });
    }

    loadStylesheet(url) {
        return new Promise(resolve => {
            // Is it already inserted, possibly with server-side rendering?
            if (document.querySelectorAll(`link[href="${url}"]`).length) {
                return;
            }
            const s = document.createElement('link');
            s.rel = 'stylesheet';
            s.href = url;
            s.onload = resolve;
            document.head.appendChild(s);
        });
    }

    setMeta(attributes) {
        let updatedExisting = false;
        _.each(['name', 'property'], name => {
            if (_.has(attributes, name)) {
                // Fetch existing element
                const element = document.querySelector(`meta[${name}="${attributes[name]}"]`);
                if (element) {
                    // If exists, update with new attributes
                    _.each(attributes, (value, key) => element.setAttribute(key, value));
                    updatedExisting = true;
                    return false;
                }
            }
        });

        if (updatedExisting) {
            return;
        }

        // Create new element
        const element = document.createElement('meta');
        _.each(attributes, (value, key) => element.setAttribute(key, value));
        document.head.appendChild(element);
    }

    setTitle(title) {
        document.title = title;
    }
}

export default Page;


Fix switch removing regex and adding alias for serve and build

--- src/commands/commands.js
+++ src/commands/commands.js
@@ -10,9 +10,11 @@
   var command = argv._[0] || options.parent.rawArgs[2];
   switch( command ) {
     case 'serve':
+    case 's':
       runner(cb, 'serve');
       break;
     case 'build':
+    case 'b':
       runner(cb, 'release');
       break;
     default:

<|original_code|>
'use strict';

// This is a very simple interface
// Used to fire up gulp task in your local project
var runner = require('../utils/runner'),
    cb = require('../utils/callback'),
    argv = require('minimist')(process.argv.slice(2));

var commands = function(options) {
  var command = argv._[0] || options.parent.rawArgs[2];
  switch( command ) {
    case 'serve':
      runner(cb, 'serve');
      break;
    case 'build':
      runner(cb, 'release');
      break;
    default:
      runner(cb, 'default');
  }
};

module.exports = commands;

<|edits_diff|>
--- src/commands/commands.js
+++ src/commands/commands.js
@@ -10,6 +10,7 @@
   var command = argv._[0] || options.parent.rawArgs[2];
   switch( command ) {
     case 'serve':
+    case 's':
       runner(cb, 'serve');
       break;
     case 'build':
<|current_version|>
'use strict';

// This is a very simple interface
// Used to fire up gulp task in your local project
var runner = require('../utils/runner'),
    cb = require('../utils/callback'),
    argv = require('minimist')(process.argv.slice(2));

var commands = function(options) {
  var command = argv._[0] || options.parent.rawArgs[2];
  switch( command ) {
    case 'serve':
    case 's':
      runner(cb, 'serve');
      break;
    case 'build':
      runner(cb, 'release');
      break;
    default:
      runner(cb, 'default');
  }
};

module.exports = commands;

<|next_version|>
'use strict';

// This is a very simple interface
// Used to fire up gulp task in your local project
var runner = require('../utils/runner'),
    cb = require('../utils/callback'),
    argv = require('minimist')(process.argv.slice(2));

var commands = function(options) {
  var command = argv._[0] || options.parent.rawArgs[2];
  switch( command ) {
    case 'serve':
    case 's':
      runner(cb, 'serve');
      break;
    case 'build':
    case 'b':
      runner(cb, 'release');
      break;
    default:
      runner(cb, 'default');
  }
};

module.exports = commands;


Add gulp electron and gulp clean

Add gulp electron and gulp clean

--- gulpfile.js
+++ gulpfile.js
@@ -2,9 +2,16 @@

 let gulp = require('gulp');
 let server = require('gulp-express');
+let shell = require('gulp-shell');
+let del = require('del');
+
 let paths = {
 	scripts: ['app.js', 'routes/**/*.js', 'public/**/*.js', 'gulpfile.js']
 };
+
+gulp.task('clean', () => {
+	return del(['build']);
+});

 gulp.task('run', () => {
 	server.run(['bin/www']);
@@ -15,3 +22,8 @@
 });

 gulp.task('default', ['watch', 'run']);
+
+gulp.task('electron', ['clean'], () => {
+	return gulp.src(['main.js', './views/**/**', './public/**/**'])
+		.pipe(gulp.dest('build/electron'));
+});

<|original_code|>
'use strict';

let gulp = require('gulp');
let server = require('gulp-express');
let paths = {
	scripts: ['app.js', 'routes/**/*.js', 'public/**/*.js', 'gulpfile.js']
};

gulp.task('run', () => {
	server.run(['bin/www']);
});

gulp.task('watch', () => {
    gulp.watch([paths.scripts, ['run']]);
});

gulp.task('default', ['watch', 'run']);
<|edits_diff|>
--- gulpfile.js
+++ gulpfile.js
@@ -2,6 +2,9 @@

 let gulp = require('gulp');
 let server = require('gulp-express');
+let shell = require('gulp-shell');
+let del = require('del');
+
 let paths = {
 	scripts: ['app.js', 'routes/**/*.js', 'public/**/*.js', 'gulpfile.js']
 };
@@ -15,3 +18,8 @@
 });

 gulp.task('default', ['watch', 'run']);
+
+gulp.task('electron', ['clean'], () => {
+	return gulp.src(['main.js', './views/**/**', './public/**/**'])
+		.pipe(gulp.dest('build/electron'));
+});
<|current_version|>
'use strict';

let gulp = require('gulp');
let server = require('gulp-express');
let shell = require('gulp-shell');
let del = require('del');

let paths = {
	scripts: ['app.js', 'routes/**/*.js', 'public/**/*.js', 'gulpfile.js']
};

gulp.task('run', () => {
	server.run(['bin/www']);
});

gulp.task('watch', () => {
    gulp.watch([paths.scripts, ['run']]);
});

gulp.task('default', ['watch', 'run']);

gulp.task('electron', ['clean'], () => {
	return gulp.src(['main.js', './views/**/**', './public/**/**'])
		.pipe(gulp.dest('build/electron'));
});

<|next_version|>
'use strict';

let gulp = require('gulp');
let server = require('gulp-express');
let shell = require('gulp-shell');
let del = require('del');

let paths = {
	scripts: ['app.js', 'routes/**/*.js', 'public/**/*.js', 'gulpfile.js']
};

gulp.task('clean', () => {
	return del(['build']);
});

gulp.task('run', () => {
	server.run(['bin/www']);
});

gulp.task('watch', () => {
    gulp.watch([paths.scripts, ['run']]);
});

gulp.task('default', ['watch', 'run']);

gulp.task('electron', ['clean'], () => {
	return gulp.src(['main.js', './views/**/**', './public/**/**'])
		.pipe(gulp.dest('build/electron'));
});


Set debuggee in HelloWorld example

Set debuggee in HelloWorld example

--- HelloWorld/lib/myPanel.js
+++ HelloWorld/lib/myPanel.js
@@ -42,8 +42,16 @@
   * `debuggee` object
   */
   setup: function(options) {
+    console.log("MyPanel.setup" + options.debuggee);
+
+    this.debuggee = options.debuggee;
+
     // TODO: connect to backend using options.debuggee
   },
+
+  onReady: function() {
+    console.log("MyPanel.onReady " + this.debuggee);
+  }
 });

 const myTool = new Tool({

<|original_code|>
/* See license.txt for terms of usage */

"use strict";

const self = require("sdk/self");

const { Cu, Ci } = require("chrome");
const { Panel } = require("dev/panel.js");
const { Class } = require("sdk/core/heritage");
const { Tool } = require("dev/toolbox");

/**
 * This object represents a new {@Toolbox} panel
 */
const MyPanel = Class(
/** @lends MyPanel */
{
  extends: Panel,

  label: "My Panel",
  tooltip: "My panel tooltip",
  icon: "./icon-16.png",
  url: "./myPanel.html",

  /**
   * Executed by the framework when an instance of this panel is created.
   * There is one instance of this panel per {@Toolbox}. The panel is
   * instantiated when selected in the toolbox for the first time.
   */
  initialize: function(options) {
  },

  /**
   * Executed by the framework when the panel is destroyed.
   */
  dispose: function() {
  },

 /**
  * Executed by the framework when the panel content iframe is
  * constructed. Allows e.g to connect the backend through
  * `debuggee` object
  */
  setup: function(options) {
    // TODO: connect to backend using options.debuggee
  },
});

const myTool = new Tool({
  name: "MyTool",
  panels: {
    myPanel: MyPanel
  }
});

<|edits_diff|>
--- HelloWorld/lib/myPanel.js
+++ HelloWorld/lib/myPanel.js
@@ -42,6 +42,10 @@
   * `debuggee` object
   */
   setup: function(options) {
+    console.log("MyPanel.setup" + options.debuggee);
+
+    this.debuggee = options.debuggee;
+
     // TODO: connect to backend using options.debuggee
   },
 });
<|current_version|>
/* See license.txt for terms of usage */

"use strict";

const self = require("sdk/self");

const { Cu, Ci } = require("chrome");
const { Panel } = require("dev/panel.js");
const { Class } = require("sdk/core/heritage");
const { Tool } = require("dev/toolbox");

/**
 * This object represents a new {@Toolbox} panel
 */
const MyPanel = Class(
/** @lends MyPanel */
{
  extends: Panel,

  label: "My Panel",
  tooltip: "My panel tooltip",
  icon: "./icon-16.png",
  url: "./myPanel.html",

  /**
   * Executed by the framework when an instance of this panel is created.
   * There is one instance of this panel per {@Toolbox}. The panel is
   * instantiated when selected in the toolbox for the first time.
   */
  initialize: function(options) {
  },

  /**
   * Executed by the framework when the panel is destroyed.
   */
  dispose: function() {
  },

 /**
  * Executed by the framework when the panel content iframe is
  * constructed. Allows e.g to connect the backend through
  * `debuggee` object
  */
  setup: function(options) {
    console.log("MyPanel.setup" + options.debuggee);

    this.debuggee = options.debuggee;

    // TODO: connect to backend using options.debuggee
  },
});

const myTool = new Tool({
  name: "MyTool",
  panels: {
    myPanel: MyPanel
  }
});

<|next_version|>
/* See license.txt for terms of usage */

"use strict";

const self = require("sdk/self");

const { Cu, Ci } = require("chrome");
const { Panel } = require("dev/panel.js");
const { Class } = require("sdk/core/heritage");
const { Tool } = require("dev/toolbox");

/**
 * This object represents a new {@Toolbox} panel
 */
const MyPanel = Class(
/** @lends MyPanel */
{
  extends: Panel,

  label: "My Panel",
  tooltip: "My panel tooltip",
  icon: "./icon-16.png",
  url: "./myPanel.html",

  /**
   * Executed by the framework when an instance of this panel is created.
   * There is one instance of this panel per {@Toolbox}. The panel is
   * instantiated when selected in the toolbox for the first time.
   */
  initialize: function(options) {
  },

  /**
   * Executed by the framework when the panel is destroyed.
   */
  dispose: function() {
  },

 /**
  * Executed by the framework when the panel content iframe is
  * constructed. Allows e.g to connect the backend through
  * `debuggee` object
  */
  setup: function(options) {
    console.log("MyPanel.setup" + options.debuggee);

    this.debuggee = options.debuggee;

    // TODO: connect to backend using options.debuggee
  },

  onReady: function() {
    console.log("MyPanel.onReady " + this.debuggee);
  }
});

const myTool = new Tool({
  name: "MyTool",
  panels: {
    myPanel: MyPanel
  }
});


Add progress bar to / for consistency.

Add progress bar to / for consistency.

--- client/js/controllers/index-controller.js
+++ client/js/controllers/index-controller.js
@@ -2,6 +2,7 @@
 var IndexController = function($scope, analytics, navigation, progressbar, search) {
 	$scope.searchQuery = "";

+	progressbar.start();
 	$scope.search = function() {
 		if ($scope.searchQuery.trim().length === 0) {
 			navigation.toEntry("the-narrows");
@@ -10,6 +11,7 @@
 		}
 	};

+	progressbar.complete();
 	$scope.htmlReady();
 };

<|original_code|>
"use strict";
var IndexController = function($scope, analytics, navigation, progressbar, search) {
	$scope.searchQuery = "";

	$scope.search = function() {
		if ($scope.searchQuery.trim().length === 0) {
			navigation.toEntry("the-narrows");
		} else {
			search.search($scope.searchQuery);
		}
	};

	$scope.htmlReady();
};

IndexController.$inject = ["$scope", "analytics", "navigation", "progressbar", "search"];
<|edits_diff|>
--- client/js/controllers/index-controller.js
+++ client/js/controllers/index-controller.js
@@ -2,6 +2,7 @@
 var IndexController = function($scope, analytics, navigation, progressbar, search) {
 	$scope.searchQuery = "";

+	progressbar.start();
 	$scope.search = function() {
 		if ($scope.searchQuery.trim().length === 0) {
 			navigation.toEntry("the-narrows");
<|current_version|>
"use strict";
var IndexController = function($scope, analytics, navigation, progressbar, search) {
	$scope.searchQuery = "";

	progressbar.start();
	$scope.search = function() {
		if ($scope.searchQuery.trim().length === 0) {
			navigation.toEntry("the-narrows");
		} else {
			search.search($scope.searchQuery);
		}
	};

	$scope.htmlReady();
};

IndexController.$inject = ["$scope", "analytics", "navigation", "progressbar", "search"];
<|next_version|>
"use strict";
var IndexController = function($scope, analytics, navigation, progressbar, search) {
	$scope.searchQuery = "";

	progressbar.start();
	$scope.search = function() {
		if ($scope.searchQuery.trim().length === 0) {
			navigation.toEntry("the-narrows");
		} else {
			search.search($scope.searchQuery);
		}
	};

	progressbar.complete();
	$scope.htmlReady();
};

IndexController.$inject = ["$scope", "analytics", "navigation", "progressbar", "search"];


Reposition tooltips when window is resized

--- public/tutorial/index.js
+++ public/tutorial/index.js
@@ -16,12 +16,17 @@
           resizable: false,
           position: step.position
         });
+        step.resize = function resize() {
+          step.$content.dialog("option", "position", step.position);
+        };
+        $(window).on('resize', step.resize);
       }

       function hide(idx) {
         var step = steps[idx];
         if (step.destroy) step.destroy.apply(_this);
         step.$content.dialog('destroy');
+        $(window).off('resize', step.resize);
       }

       this.start = function() {

<|original_code|>
define(
  ["jquery"],
  function($) {
    function Tutorial(steps, content) {
      var _this = this;
      var currentIdx;

      function show(idx) {
        var step = steps[idx];
        if (step.init) step.init.apply(_this);
        step.$content = $('[data-step="' + step.name + '"]', content);
        step.$content.dialog({
          dialogClass: [].concat("tutorial-dialog", step.dialogClass || []).join(' '),
          maxWidth: 300,
          modal: false,
          resizable: false,
          position: step.position
        });
      }

      function hide(idx) {
        var step = steps[idx];
        if (step.destroy) step.destroy.apply(_this);
        step.$content.dialog('destroy');
      }

      this.start = function() {
        currentIdx = 0;
        show(currentIdx);
      };

      this.next = function() {
        if (currentIdx >= steps.length) return;
        hide(currentIdx);
        currentIdx++;
        if (currentIdx < steps.length) show(currentIdx);
      }

      this.end = function() {
        hide(currentIdx);
        currentIdx = steps.length;
      };

      $('.tutorial-next', content).click(function () {
        _this.next();
        return false;
      });
      $('.tutorial-end', content).click(function () {
        _this.end();
        return false;
      });

      return this;
    };

    return Tutorial;
  }
);

<|edits_diff|>
--- public/tutorial/index.js
+++ public/tutorial/index.js
@@ -16,6 +16,10 @@
           resizable: false,
           position: step.position
         });
+        step.resize = function resize() {
+          step.$content.dialog("option", "position", step.position);
+        };
+        $(window).on('resize', step.resize);
       }

       function hide(idx) {
<|current_version|>
define(
  ["jquery"],
  function($) {
    function Tutorial(steps, content) {
      var _this = this;
      var currentIdx;

      function show(idx) {
        var step = steps[idx];
        if (step.init) step.init.apply(_this);
        step.$content = $('[data-step="' + step.name + '"]', content);
        step.$content.dialog({
          dialogClass: [].concat("tutorial-dialog", step.dialogClass || []).join(' '),
          maxWidth: 300,
          modal: false,
          resizable: false,
          position: step.position
        });
        step.resize = function resize() {
          step.$content.dialog("option", "position", step.position);
        };
        $(window).on('resize', step.resize);
      }

      function hide(idx) {
        var step = steps[idx];
        if (step.destroy) step.destroy.apply(_this);
        step.$content.dialog('destroy');
      }

      this.start = function() {
        currentIdx = 0;
        show(currentIdx);
      };

      this.next = function() {
        if (currentIdx >= steps.length) return;
        hide(currentIdx);
        currentIdx++;
        if (currentIdx < steps.length) show(currentIdx);
      }

      this.end = function() {
        hide(currentIdx);
        currentIdx = steps.length;
      };

      $('.tutorial-next', content).click(function () {
        _this.next();
        return false;
      });
      $('.tutorial-end', content).click(function () {
        _this.end();
        return false;
      });

      return this;
    };

    return Tutorial;
  }
);

<|next_version|>
define(
  ["jquery"],
  function($) {
    function Tutorial(steps, content) {
      var _this = this;
      var currentIdx;

      function show(idx) {
        var step = steps[idx];
        if (step.init) step.init.apply(_this);
        step.$content = $('[data-step="' + step.name + '"]', content);
        step.$content.dialog({
          dialogClass: [].concat("tutorial-dialog", step.dialogClass || []).join(' '),
          maxWidth: 300,
          modal: false,
          resizable: false,
          position: step.position
        });
        step.resize = function resize() {
          step.$content.dialog("option", "position", step.position);
        };
        $(window).on('resize', step.resize);
      }

      function hide(idx) {
        var step = steps[idx];
        if (step.destroy) step.destroy.apply(_this);
        step.$content.dialog('destroy');
        $(window).off('resize', step.resize);
      }

      this.start = function() {
        currentIdx = 0;
        show(currentIdx);
      };

      this.next = function() {
        if (currentIdx >= steps.length) return;
        hide(currentIdx);
        currentIdx++;
        if (currentIdx < steps.length) show(currentIdx);
      }

      this.end = function() {
        hide(currentIdx);
        currentIdx = steps.length;
      };

      $('.tutorial-next', content).click(function () {
        _this.next();
        return false;
      });
      $('.tutorial-end', content).click(function () {
        _this.end();
        return false;
      });

      return this;
    };

    return Tutorial;
  }
);


Check for fn in .on(), bail early in .off()

--- src/emitter.js
+++ src/emitter.js
@@ -1,3 +1,5 @@
+import { EmitterError } from './error'
+
 export default class Emitter {
   constructor() {
     this._events = {}
@@ -8,10 +10,12 @@
   }

   on(name, fn) {
+    if (typeof fn !== 'function') throw new EmitterError('requires function')
     this._event(name).add(fn)
   }

   off(name, fn) {
+    if (!this._events[name]) return
     if (fn) this._event(name).delete(fn)
     else this._event(name).clear()
   }

<|original_code|>
export default class Emitter {
  constructor() {
    this._events = {}
  }

  _event(name) {
    return (this._events[name] = this._events[name] || new Set())
  }

  on(name, fn) {
    this._event(name).add(fn)
  }

  off(name, fn) {
    if (fn) this._event(name).delete(fn)
    else this._event(name).clear()
  }

  once(name, fn) {
    const self = this
    this.on(name, function(input) {
      self.off(name, this)
      fn(input)
    })
  }

  emit(name, input) {
    if (!this._events[name]) return
    this._event(name).forEach(fn => fn(input))
  }
}

<|edits_diff|>
--- src/emitter.js
+++ src/emitter.js
@@ -1,3 +1,5 @@
+import { EmitterError } from './error'
+
 export default class Emitter {
   constructor() {
     this._events = {}
@@ -8,6 +10,7 @@
   }

   on(name, fn) {
+    if (typeof fn !== 'function') throw new EmitterError('requires function')
     this._event(name).add(fn)
   }

<|current_version|>
import { EmitterError } from './error'

export default class Emitter {
  constructor() {
    this._events = {}
  }

  _event(name) {
    return (this._events[name] = this._events[name] || new Set())
  }

  on(name, fn) {
    if (typeof fn !== 'function') throw new EmitterError('requires function')
    this._event(name).add(fn)
  }

  off(name, fn) {
    if (fn) this._event(name).delete(fn)
    else this._event(name).clear()
  }

  once(name, fn) {
    const self = this
    this.on(name, function(input) {
      self.off(name, this)
      fn(input)
    })
  }

  emit(name, input) {
    if (!this._events[name]) return
    this._event(name).forEach(fn => fn(input))
  }
}

<|next_version|>
import { EmitterError } from './error'

export default class Emitter {
  constructor() {
    this._events = {}
  }

  _event(name) {
    return (this._events[name] = this._events[name] || new Set())
  }

  on(name, fn) {
    if (typeof fn !== 'function') throw new EmitterError('requires function')
    this._event(name).add(fn)
  }

  off(name, fn) {
    if (!this._events[name]) return
    if (fn) this._event(name).delete(fn)
    else this._event(name).clear()
  }

  once(name, fn) {
    const self = this
    this.on(name, function(input) {
      self.off(name, this)
      fn(input)
    })
  }

  emit(name, input) {
    if (!this._events[name]) return
    this._event(name).forEach(fn => fn(input))
  }
}


Add 'present' url query/search param to presentation mode middleware.

--- ui/src/shared/middleware/resizeLayout.js
+++ ui/src/shared/middleware/resizeLayout.js
@@ -1,4 +1,5 @@
 // Trigger resize event to relayout the React Layout plugin
+import {enablePresentationMode} from '../actions/app'

 export default function resizeLayout() {
   return next => action => {
@@ -12,5 +13,9 @@
       evt.initEvent('resize', false, true)
       window.dispatchEvent(evt)
     }
+    if (window.location.search.includes('present')) {
+      next(enablePresentationMode())
+      next(action)
+    }
   }
 }

<|original_code|>
// Trigger resize event to relayout the React Layout plugin

export default function resizeLayout() {
  return next => action => {
    next(action)
    if (
      action.type === 'ENABLE_PRESENTATION_MODE' ||
      action.type === 'DISABLE_PRESENTATION_MODE'
    ) {
      // Uses longer event object creation method due to IE compatibility.
      const evt = document.createEvent('HTMLEvents')
      evt.initEvent('resize', false, true)
      window.dispatchEvent(evt)
    }
  }
}

<|edits_diff|>
--- ui/src/shared/middleware/resizeLayout.js
+++ ui/src/shared/middleware/resizeLayout.js
@@ -1,4 +1,5 @@
 // Trigger resize event to relayout the React Layout plugin
+import {enablePresentationMode} from '../actions/app'

 export default function resizeLayout() {
   return next => action => {
<|current_version|>
// Trigger resize event to relayout the React Layout plugin
import {enablePresentationMode} from '../actions/app'

export default function resizeLayout() {
  return next => action => {
    next(action)
    if (
      action.type === 'ENABLE_PRESENTATION_MODE' ||
      action.type === 'DISABLE_PRESENTATION_MODE'
    ) {
      // Uses longer event object creation method due to IE compatibility.
      const evt = document.createEvent('HTMLEvents')
      evt.initEvent('resize', false, true)
      window.dispatchEvent(evt)
    }
  }
}

<|next_version|>
// Trigger resize event to relayout the React Layout plugin
import {enablePresentationMode} from '../actions/app'

export default function resizeLayout() {
  return next => action => {
    next(action)
    if (
      action.type === 'ENABLE_PRESENTATION_MODE' ||
      action.type === 'DISABLE_PRESENTATION_MODE'
    ) {
      // Uses longer event object creation method due to IE compatibility.
      const evt = document.createEvent('HTMLEvents')
      evt.initEvent('resize', false, true)
      window.dispatchEvent(evt)
    }
    if (window.location.search.includes('present')) {
      next(enablePresentationMode())
      next(action)
    }
  }
}


Add a missing index (votes by document)

Add a missing index (votes by document)

--- packages/lesswrong/lib/modules/indexes.js
+++ packages/lesswrong/lib/modules/indexes.js
@@ -1,4 +1,5 @@
 import { Comments, Posts } from 'meteor/example-forum';
+import { Votes } from "meteor/vulcan:voting";

 // Recent Comments query index\
@@ -6,3 +7,6 @@

 // Top Posts query index
 Posts._ensureIndex({'status': -1, 'draft': -1, 'isFuture': -1, 'sticky': -1, 'score': -1, '_id': -1});
+
+// Votes by document (comment) ID
+Votes._ensureIndex({ "documentId": 1 });

<|original_code|>
import { Comments, Posts } from 'meteor/example-forum';

// Recent Comments query index\
Comments._ensureIndex({'postedAt': -1, '_id': -1});

// Top Posts query index
Posts._ensureIndex({'status': -1, 'draft': -1, 'isFuture': -1, 'sticky': -1, 'score': -1, '_id': -1});

<|edits_diff|>
--- packages/lesswrong/lib/modules/indexes.js
+++ packages/lesswrong/lib/modules/indexes.js
@@ -1,4 +1,5 @@
 import { Comments, Posts } from 'meteor/example-forum';
+import { Votes } from "meteor/vulcan:voting";

 // Recent Comments query index\
<|current_version|>
import { Comments, Posts } from 'meteor/example-forum';
import { Votes } from "meteor/vulcan:voting";

// Recent Comments query index\
Comments._ensureIndex({'postedAt': -1, '_id': -1});

// Top Posts query index
Posts._ensureIndex({'status': -1, 'draft': -1, 'isFuture': -1, 'sticky': -1, 'score': -1, '_id': -1});

<|next_version|>
import { Comments, Posts } from 'meteor/example-forum';
import { Votes } from "meteor/vulcan:voting";

// Recent Comments query index\
Comments._ensureIndex({'postedAt': -1, '_id': -1});

// Top Posts query index
Posts._ensureIndex({'status': -1, 'draft': -1, 'isFuture': -1, 'sticky': -1, 'score': -1, '_id': -1});

// Votes by document (comment) ID
Votes._ensureIndex({ "documentId": 1 });


Update page titles on Lessons.

Update page titles on Lessons.

--- app/routers/Play/routes/ClassroomLessons/index.js
+++ app/routers/Play/routes/ClassroomLessons/index.js
@@ -4,6 +4,9 @@

 const playRoute = {
   path: ':lessonID',
+  onEnter: (nextState, replaceWith) => {
+    document.title = 'Quill Lessons';
+  },
   getComponent: (nextState, cb) => {
     System.import(/* webpackChunkName: "teach-classroom-lesson" */'components/classroomLessons/play/container.tsx')
     .then((component) => {
@@ -17,6 +20,7 @@
   onEnter: (nextState, replaceWith) => {
     const classroom_activity_id = getParameterByName('classroom_activity_id');
     const lessonID = getParameterByName('uid');
+    document.title = 'Quill Lessons';
     const student = getParameterByName('student');
     if (lessonID) {
       document.location.href = `${document.location.origin + document.location.pathname}#/play/class-lessons/${lessonID}?student=${student}&classroom_activity_id=${classroom_activity_id}`;

<|original_code|>
import Passthrough from 'components/shared/passthrough.jsx';

import { getParameterByName } from 'libs/getParameterByName';

const playRoute = {
  path: ':lessonID',
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "teach-classroom-lesson" */'components/classroomLessons/play/container.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const indexRoute = {
  component: Passthrough,
  onEnter: (nextState, replaceWith) => {
    const classroom_activity_id = getParameterByName('classroom_activity_id');
    const lessonID = getParameterByName('uid');
    const student = getParameterByName('student');
    if (lessonID) {
      document.location.href = `${document.location.origin + document.location.pathname}#/play/class-lessons/${lessonID}?student=${student}&classroom_activity_id=${classroom_activity_id}`;
    }
  },
};

const route = {
  path: 'class-lessons',
  indexRoute,
  childRoutes: [
    playRoute
  ],
  component: Passthrough,
};

export default route;

<|edits_diff|>
--- app/routers/Play/routes/ClassroomLessons/index.js
+++ app/routers/Play/routes/ClassroomLessons/index.js
@@ -4,6 +4,9 @@

 const playRoute = {
   path: ':lessonID',
+  onEnter: (nextState, replaceWith) => {
+    document.title = 'Quill Lessons';
+  },
   getComponent: (nextState, cb) => {
     System.import(/* webpackChunkName: "teach-classroom-lesson" */'components/classroomLessons/play/container.tsx')
     .then((component) => {
<|current_version|>
import Passthrough from 'components/shared/passthrough.jsx';

import { getParameterByName } from 'libs/getParameterByName';

const playRoute = {
  path: ':lessonID',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Quill Lessons';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "teach-classroom-lesson" */'components/classroomLessons/play/container.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const indexRoute = {
  component: Passthrough,
  onEnter: (nextState, replaceWith) => {
    const classroom_activity_id = getParameterByName('classroom_activity_id');
    const lessonID = getParameterByName('uid');
    const student = getParameterByName('student');
    if (lessonID) {
      document.location.href = `${document.location.origin + document.location.pathname}#/play/class-lessons/${lessonID}?student=${student}&classroom_activity_id=${classroom_activity_id}`;
    }
  },
};

const route = {
  path: 'class-lessons',
  indexRoute,
  childRoutes: [
    playRoute
  ],
  component: Passthrough,
};

export default route;

<|next_version|>
import Passthrough from 'components/shared/passthrough.jsx';

import { getParameterByName } from 'libs/getParameterByName';

const playRoute = {
  path: ':lessonID',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Quill Lessons';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "teach-classroom-lesson" */'components/classroomLessons/play/container.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const indexRoute = {
  component: Passthrough,
  onEnter: (nextState, replaceWith) => {
    const classroom_activity_id = getParameterByName('classroom_activity_id');
    const lessonID = getParameterByName('uid');
    document.title = 'Quill Lessons';
    const student = getParameterByName('student');
    if (lessonID) {
      document.location.href = `${document.location.origin + document.location.pathname}#/play/class-lessons/${lessonID}?student=${student}&classroom_activity_id=${classroom_activity_id}`;
    }
  },
};

const route = {
  path: 'class-lessons',
  indexRoute,
  childRoutes: [
    playRoute
  ],
  component: Passthrough,
};

export default route;


Add preload to js api

Add preload to js api

--- src/index.js
+++ src/index.js
@@ -1,5 +1,10 @@
+import { NativeModules } from 'react-native';
+
+const { BBBCardIO: { preload, } } = NativeModules;
+
 import CardIOView from './CardIO.ios';
 import * as constants from './constants';

 export default CardIOView;
 export const CardIOConstants = constants;
+export { preload, };

<|original_code|>
import CardIOView from './CardIO.ios';
import * as constants from './constants';

export default CardIOView;
export const CardIOConstants = constants;

<|edits_diff|>
--- src/index.js
+++ src/index.js
@@ -1,3 +1,7 @@
+import { NativeModules } from 'react-native';
+
+const { BBBCardIO: { preload, } } = NativeModules;
+
 import CardIOView from './CardIO.ios';
 import * as constants from './constants';

<|current_version|>
import { NativeModules } from 'react-native';

const { BBBCardIO: { preload, } } = NativeModules;

import CardIOView from './CardIO.ios';
import * as constants from './constants';

export default CardIOView;
export const CardIOConstants = constants;

<|next_version|>
import { NativeModules } from 'react-native';

const { BBBCardIO: { preload, } } = NativeModules;

import CardIOView from './CardIO.ios';
import * as constants from './constants';

export default CardIOView;
export const CardIOConstants = constants;
export { preload, };


Destroy Sticky elements before leaving the page

When Foundation initializes a page that has any sticky element, it
loads a window scroll listener into window object to handle the sticky
element positioning when scrolling. This works great until user moves
to a page without sticky elements and the window listeners remain
attached to the window object on this new page too when there is no
need to run the scrollListener and there is no sticky elements so the
window scroll listener cannot find the sticky object on that page a lot
of errors are thrown when user scrolls.

With this approach we are destroying sticky elements before leaving
the page which also remove the Sticky scrollListener from the window
object.

I do not know how to write a test to demonstrate this fix, but at least
there is some steps to reproduce this behavior:

0. Undo this commit
1. Go to any proposal page
2. Click on any link (with Turbolinks enabled)
3. Scroll the page
4. Check the console log. Yo will find as error occurrences as pixels you scrolled.

--- app/assets/javascripts/foundation_extras.js
+++ app/assets/javascripts/foundation_extras.js
@@ -3,6 +3,13 @@
   App.FoundationExtras = {
     initialize: function() {
       $(document).foundation();
+    },
+    destroy: function() {
+      if ($(".sticky").length > 0) {
+        $(".sticky").foundation("_destroy");
+      }
     }
   };
+
+  $(document).on("turbolinks:before-visit", App.FoundationExtras.destroy);
 }).call(this);

<|original_code|>
(function() {
  "use strict";
  App.FoundationExtras = {
    initialize: function() {
      $(document).foundation();
    }
  };
}).call(this);

<|edits_diff|>
--- app/assets/javascripts/foundation_extras.js
+++ app/assets/javascripts/foundation_extras.js
@@ -3,6 +3,11 @@
   App.FoundationExtras = {
     initialize: function() {
       $(document).foundation();
+    },
+    destroy: function() {
+      if ($(".sticky").length > 0) {
+        $(".sticky").foundation("_destroy");
+      }
     }
   };
 }).call(this);
<|current_version|>
(function() {
  "use strict";
  App.FoundationExtras = {
    initialize: function() {
      $(document).foundation();
    },
    destroy: function() {
      if ($(".sticky").length > 0) {
        $(".sticky").foundation("_destroy");
      }
    }
  };
}).call(this);

<|next_version|>
(function() {
  "use strict";
  App.FoundationExtras = {
    initialize: function() {
      $(document).foundation();
    },
    destroy: function() {
      if ($(".sticky").length > 0) {
        $(".sticky").foundation("_destroy");
      }
    }
  };

  $(document).on("turbolinks:before-visit", App.FoundationExtras.destroy);
}).call(this);


Add support for ZStandard compression.

Add support for ZStandard compression.

This is landing in Kafka 2.1.0, due for release 29th October, 2018.

References -

1. https://cwiki.apache.org/confluence/display/KAFKA/KIP-110%3A+Add+Codec+for+ZStandard+Compression
2. https://issues.apache.org/jira/browse/KAFKA-4514
3. https://github.com/apache/kafka/pull/2267
4. https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=91554044

--- src/protocol/message/compression/index.js
+++ src/protocol/message/compression/index.js
@@ -8,6 +8,7 @@
   GZIP: 1,
   Snappy: 2,
   LZ4: 3,
+  ZSTD: 4,
 }

 const Codecs = {
@@ -17,6 +18,9 @@
   },
   [Types.LZ4]: () => {
     throw new KafkaJSNotImplemented('LZ4 compression not implemented')
+  },
+  [Types.ZSTD]: () => {
+    throw new KafkaJSNotImplemented('ZSTD compression not implemented')
   },
 }

<|original_code|>
const { KafkaJSNotImplemented } = require('../../../errors')

const MESSAGE_CODEC_MASK = 0x3
const RECORD_BATCH_CODEC_MASK = 0x07

const Types = {
  None: 0,
  GZIP: 1,
  Snappy: 2,
  LZ4: 3,
}

const Codecs = {
  [Types.GZIP]: () => require('./gzip'),
  [Types.Snappy]: () => {
    throw new KafkaJSNotImplemented('Snappy compression not implemented')
  },
  [Types.LZ4]: () => {
    throw new KafkaJSNotImplemented('LZ4 compression not implemented')
  },
}

const lookupCodec = type => (Codecs[type] ? Codecs[type]() : null)
const lookupCodecByAttributes = attributes => {
  const codec = Codecs[attributes & MESSAGE_CODEC_MASK]
  return codec ? codec() : null
}
const lookupCodecByRecordBatchAttributes = attributes => {
  const codec = Codecs[attributes & RECORD_BATCH_CODEC_MASK]
  return codec ? codec() : null
}

module.exports = {
  Types,
  Codecs,
  lookupCodec,
  lookupCodecByAttributes,
  lookupCodecByRecordBatchAttributes,
}

<|edits_diff|>
--- src/protocol/message/compression/index.js
+++ src/protocol/message/compression/index.js
@@ -8,6 +8,7 @@
   GZIP: 1,
   Snappy: 2,
   LZ4: 3,
+  ZSTD: 4,
 }

 const Codecs = {
<|current_version|>
const { KafkaJSNotImplemented } = require('../../../errors')

const MESSAGE_CODEC_MASK = 0x3
const RECORD_BATCH_CODEC_MASK = 0x07

const Types = {
  None: 0,
  GZIP: 1,
  Snappy: 2,
  LZ4: 3,
  ZSTD: 4,
}

const Codecs = {
  [Types.GZIP]: () => require('./gzip'),
  [Types.Snappy]: () => {
    throw new KafkaJSNotImplemented('Snappy compression not implemented')
  },
  [Types.LZ4]: () => {
    throw new KafkaJSNotImplemented('LZ4 compression not implemented')
  },
}

const lookupCodec = type => (Codecs[type] ? Codecs[type]() : null)
const lookupCodecByAttributes = attributes => {
  const codec = Codecs[attributes & MESSAGE_CODEC_MASK]
  return codec ? codec() : null
}
const lookupCodecByRecordBatchAttributes = attributes => {
  const codec = Codecs[attributes & RECORD_BATCH_CODEC_MASK]
  return codec ? codec() : null
}

module.exports = {
  Types,
  Codecs,
  lookupCodec,
  lookupCodecByAttributes,
  lookupCodecByRecordBatchAttributes,
}

<|next_version|>
const { KafkaJSNotImplemented } = require('../../../errors')

const MESSAGE_CODEC_MASK = 0x3
const RECORD_BATCH_CODEC_MASK = 0x07

const Types = {
  None: 0,
  GZIP: 1,
  Snappy: 2,
  LZ4: 3,
  ZSTD: 4,
}

const Codecs = {
  [Types.GZIP]: () => require('./gzip'),
  [Types.Snappy]: () => {
    throw new KafkaJSNotImplemented('Snappy compression not implemented')
  },
  [Types.LZ4]: () => {
    throw new KafkaJSNotImplemented('LZ4 compression not implemented')
  },
  [Types.ZSTD]: () => {
    throw new KafkaJSNotImplemented('ZSTD compression not implemented')
  },
}

const lookupCodec = type => (Codecs[type] ? Codecs[type]() : null)
const lookupCodecByAttributes = attributes => {
  const codec = Codecs[attributes & MESSAGE_CODEC_MASK]
  return codec ? codec() : null
}
const lookupCodecByRecordBatchAttributes = attributes => {
  const codec = Codecs[attributes & RECORD_BATCH_CODEC_MASK]
  return codec ? codec() : null
}

module.exports = {
  Types,
  Codecs,
  lookupCodec,
  lookupCodecByAttributes,
  lookupCodecByRecordBatchAttributes,
}


core.directive("validatedinput", function() {
	return {
		template: '<span ng-include src="view"></span>',
		restrict: 'E',
		scope: {
			"type": "@",
			"model": "=",
			"property": "@",
			"label": "@",
			"placeholder": "@",
			"truevalue": "@",
			"falsevalue": "@",
			"blur": "&",
			"results": "="
		},
		link: function ($scope, element, attr) {
			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

			$scope.keydown = function($event) {
				if($event.which == 13) {
					$event.target.blur();
				}
			};

		}
	};
});

core.directive("validatedinput", function() {
	return {
		template: '<span ng-include src="view"></span>',
		restrict: 'E',
		scope: {
			"type": "@",
			"model": "=",
			"property": "@",
			"label": "@",
			"placeholder": "@",
			"truevalue": "@",
			"falsevalue": "@",
			"blur": "&",
			"results": "="
		},
		link: function ($scope, element, attr) {
			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

			$scope.keydown = function($event) {
				// enter(13): submit value to be persisted
				if($event.which == 13) {
					$event.target.blur();
				}
				// escape(27): reset value using shadow
				if($event.which == 27) {
					$scope.model.refresh();
				}
			};

		}
	};
});

Refresh model when pressing escape within validated input.

--- app/directives/validatedInputDirective.js
+++ app/directives/validatedInputDirective.js
@@ -17,8 +17,13 @@
 			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

 			$scope.keydown = function($event) {
+				// enter(13): submit value to be persisted
 				if($event.which == 13) {
 					$event.target.blur();
+				}
+				// escape(27): reset value using shadow
+				if($event.which == 27) {
+					$scope.model.refresh();
 				}
 			};

core.directive("validatedinput", function() {
	return {
		template: '<span ng-include src="view"></span>',
		restrict: 'E',
		scope: {
			"type": "@",
			"model": "=",
			"property": "@",
			"label": "@",
			"placeholder": "@",
			"truevalue": "@",
			"falsevalue": "@",
			"blur": "&",
			"results": "="
		},
		link: function ($scope, element, attr) {
			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

			$scope.keydown = function($event) {
				// enter(13): submit value to be persisted
				if($event.which == 13) {
					$event.target.blur();
				}
			};

		}
	};
});

<|original_code|>
core.directive("validatedinput", function() {
	return {
		template: '',
		restrict: 'E',
		scope: {
			"type": "@",
			"model": "=",
			"property": "@",
			"label": "@",
			"placeholder": "@",
			"truevalue": "@",
			"falsevalue": "@",
			"blur": "&",
			"results": "="
		},
		link: function ($scope, element, attr) {
			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

			$scope.keydown = function($event) {
				if($event.which == 13) {
					$event.target.blur();
				}
			};

		}
	};
});
<|edits_diff|>
--- app/directives/validatedInputDirective.js
+++ app/directives/validatedInputDirective.js
@@ -17,6 +17,7 @@
 			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

 			$scope.keydown = function($event) {
+				// enter(13): submit value to be persisted
 				if($event.which == 13) {
 					$event.target.blur();
 				}
<|current_version|>
core.directive("validatedinput", function() {
	return {
		template: '',
		restrict: 'E',
		scope: {
			"type": "@",
			"model": "=",
			"property": "@",
			"label": "@",
			"placeholder": "@",
			"truevalue": "@",
			"falsevalue": "@",
			"blur": "&",
			"results": "="
		},
		link: function ($scope, element, attr) {
			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

			$scope.keydown = function($event) {
				// enter(13): submit value to be persisted
				if($event.which == 13) {
					$event.target.blur();
				}
			};

		}
	};
});
<|next_version|>
core.directive("validatedinput", function() {
	return {
		template: '',
		restrict: 'E',
		scope: {
			"type": "@",
			"model": "=",
			"property": "@",
			"label": "@",
			"placeholder": "@",
			"truevalue": "@",
			"falsevalue": "@",
			"blur": "&",
			"results": "="
		},
		link: function ($scope, element, attr) {
			$scope.view = attr.view ? attr.view : "bower_components/core/app/views/directives/validatedInput.html";

			$scope.keydown = function($event) {
				// enter(13): submit value to be persisted
				if($event.which == 13) {
					$event.target.blur();
				}
				// escape(27): reset value using shadow
				if($event.which == 27) {
					$scope.model.refresh();
				}
			};

		}
	};
});


Add pseudocode to quick sort function

Add pseudocode to quick sort function

--- quick-sort.js
+++ quick-sort.js
@@ -1,16 +1,20 @@
 // Program to sort an array using recursion
+
 function quickSort(arr) {
 	if(arr.length == 0) {
 		return [];
 	}
 	var left = [], right = [], pivot = arr[0];
+	// compare first element in array to the rest
 	for(var i = 1; i < arr.length; i++) {
+		// if element being looked at is less than first element, put it in left array--else put it in right array
 		if(arr[i] < pivot) {
 			left.push(arr[i]);
 		} else {
 			right.push(arr[i]);
 		}
 	}
+	// apply same loop to left and right arrays (broken down from original array) and merge them with pivot element, where left array lies to the left of pivot element and right array lies to the right of pivot element
 	return quickSort(left).concat(pivot, quickSort(right));
 }

<|original_code|>
// Program to sort an array using recursion
function quickSort(arr) {
	if(arr.length == 0) {
		return [];
	}
	var left = [], right = [], pivot = arr[0];
	for(var i = 1; i < arr.length; i++) {
		if(arr[i] < pivot) {
			left.push(arr[i]);
		} else {
			right.push(arr[i]);
		}
	}
	return quickSort(left).concat(pivot, quickSort(right));
}

// test case
// expect output to be [1, 2, 3, 4, 5]
console.log(quickSort([5, 4, 3, 2, 1]));
<|edits_diff|>
--- quick-sort.js
+++ quick-sort.js
@@ -1,10 +1,13 @@
 // Program to sort an array using recursion
+
 function quickSort(arr) {
 	if(arr.length == 0) {
 		return [];
 	}
 	var left = [], right = [], pivot = arr[0];
+	// compare first element in array to the rest
 	for(var i = 1; i < arr.length; i++) {
+		// if element being looked at is less than first element, put it in left array--else put it in right array
 		if(arr[i] < pivot) {
 			left.push(arr[i]);
 		} else {
<|current_version|>
// Program to sort an array using recursion

function quickSort(arr) {
	if(arr.length == 0) {
		return [];
	}
	var left = [], right = [], pivot = arr[0];
	// compare first element in array to the rest
	for(var i = 1; i < arr.length; i++) {
		// if element being looked at is less than first element, put it in left array--else put it in right array
		if(arr[i] < pivot) {
			left.push(arr[i]);
		} else {
			right.push(arr[i]);
		}
	}
	return quickSort(left).concat(pivot, quickSort(right));
}

// test case
// expect output to be [1, 2, 3, 4, 5]
console.log(quickSort([5, 4, 3, 2, 1]));

<|next_version|>
// Program to sort an array using recursion

function quickSort(arr) {
	if(arr.length == 0) {
		return [];
	}
	var left = [], right = [], pivot = arr[0];
	// compare first element in array to the rest
	for(var i = 1; i < arr.length; i++) {
		// if element being looked at is less than first element, put it in left array--else put it in right array
		if(arr[i] < pivot) {
			left.push(arr[i]);
		} else {
			right.push(arr[i]);
		}
	}
	// apply same loop to left and right arrays (broken down from original array) and merge them with pivot element, where left array lies to the left of pivot element and right array lies to the right of pivot element
	return quickSort(left).concat(pivot, quickSort(right));
}

// test case
// expect output to be [1, 2, 3, 4, 5]
console.log(quickSort([5, 4, 3, 2, 1]));