Stop validation error notification stack

closes #3383
- Calls closePassive() if a new validation error is thrown to display
only the latest validation error

--- core/client/controllers/forgotten.js
+++ core/client/controllers/forgotten.js
@@ -30,10 +30,12 @@
                     self.transitionToRoute('signin');
                 }).catch(function (resp) {
                     self.toggleProperty('submitting');
+                    self.notifications.closePassive();
                     self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
                 });
             }).catch(function (errors) {
                 self.toggleProperty('submitting');
+                self.notifications.closePassive();
                 self.notifications.showErrors(errors);
             });
         }

<|original_code|>
/* jshint unused: false */
import ajax from 'ghost/utils/ajax';
import ValidationEngine from 'ghost/mixins/validation-engine';

var ForgottenController = Ember.Controller.extend(ValidationEngine, {
    email: '',
    submitting: false,

    // ValidationEngine settings
    validationType: 'forgotten',

    actions: {
        submit: function () {
            var self = this,
                data = self.getProperties('email');

            this.toggleProperty('submitting');
            this.validate({ format: false }).then(function () {
                ajax({
                    url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
                    type: 'POST',
                    data: {
                        passwordreset: [{
                            email: data.email
                        }]
                    }
                }).then(function (resp) {
                    self.toggleProperty('submitting');
                    self.notifications.showSuccess('Please check your email for instructions.');
                    self.transitionToRoute('signin');
                }).catch(function (resp) {
                    self.toggleProperty('submitting');
                    self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
                });
            }).catch(function (errors) {
                self.toggleProperty('submitting');
                self.notifications.showErrors(errors);
            });
        }
    }
});

export default ForgottenController;

<|edits_diff|>
--- core/client/controllers/forgotten.js
+++ core/client/controllers/forgotten.js
@@ -30,6 +30,7 @@
                     self.transitionToRoute('signin');
                 }).catch(function (resp) {
                     self.toggleProperty('submitting');
+                    self.notifications.closePassive();
                     self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
                 });
             }).catch(function (errors) {
<|current_version|>
/* jshint unused: false */
import ajax from 'ghost/utils/ajax';
import ValidationEngine from 'ghost/mixins/validation-engine';

var ForgottenController = Ember.Controller.extend(ValidationEngine, {
    email: '',
    submitting: false,

    // ValidationEngine settings
    validationType: 'forgotten',

    actions: {
        submit: function () {
            var self = this,
                data = self.getProperties('email');

            this.toggleProperty('submitting');
            this.validate({ format: false }).then(function () {
                ajax({
                    url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
                    type: 'POST',
                    data: {
                        passwordreset: [{
                            email: data.email
                        }]
                    }
                }).then(function (resp) {
                    self.toggleProperty('submitting');
                    self.notifications.showSuccess('Please check your email for instructions.');
                    self.transitionToRoute('signin');
                }).catch(function (resp) {
                    self.toggleProperty('submitting');
                    self.notifications.closePassive();
                    self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
                });
            }).catch(function (errors) {
                self.toggleProperty('submitting');
                self.notifications.showErrors(errors);
            });
        }
    }
});

export default ForgottenController;

<|next_version|>
/* jshint unused: false */
import ajax from 'ghost/utils/ajax';
import ValidationEngine from 'ghost/mixins/validation-engine';

var ForgottenController = Ember.Controller.extend(ValidationEngine, {
    email: '',
    submitting: false,

    // ValidationEngine settings
    validationType: 'forgotten',

    actions: {
        submit: function () {
            var self = this,
                data = self.getProperties('email');

            this.toggleProperty('submitting');
            this.validate({ format: false }).then(function () {
                ajax({
                    url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
                    type: 'POST',
                    data: {
                        passwordreset: [{
                            email: data.email
                        }]
                    }
                }).then(function (resp) {
                    self.toggleProperty('submitting');
                    self.notifications.showSuccess('Please check your email for instructions.');
                    self.transitionToRoute('signin');
                }).catch(function (resp) {
                    self.toggleProperty('submitting');
                    self.notifications.closePassive();
                    self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
                });
            }).catch(function (errors) {
                self.toggleProperty('submitting');
                self.notifications.closePassive();
                self.notifications.showErrors(errors);
            });
        }
    }
});

export default ForgottenController;


import React, { Component } from 'react';
import SetPage from '../components/SetPage';

export default class Pollard extends Component {
  render() {
    return (
      <div className="container">
				{ this.props.children }
      </div>
    );
  }
}

Add routing link on /

Add routing link on /

--- containers/Pollard.js
+++ containers/Pollard.js
@@ -1,4 +1,6 @@
 import React, { Component } from 'react';
+import { Link } from 'react-router';
+
 import SetPage from '../components/SetPage';

@@ -6,6 +8,9 @@
   render() {
     return (

+

+
<Link to="/setlist" activeClassName="active">Setlist</Link>

+

 				{ this.props.children }

     );

import React, { Component } from 'react';
import { Link } from 'react-router';

import SetPage from '../components/SetPage';

export default class Pollard extends Component {
  render() {
    return (
      <div className="container">
				{ this.props.children }
      </div>
    );
  }
}

<|original_code|>
import React, { Component } from 'react';
import SetPage from '../components/SetPage';

export default class Pollard extends Component {
  render() {
    return (

				{ this.props.children }

    );
  }
}

<|edits_diff|>
--- containers/Pollard.js
+++ containers/Pollard.js
@@ -1,4 +1,6 @@
 import React, { Component } from 'react';
+import { Link } from 'react-router';
+
 import SetPage from '../components/SetPage';

<|current_version|>
import React, { Component } from 'react';
import { Link } from 'react-router';

import SetPage from '../components/SetPage';

export default class Pollard extends Component {
  render() {
    return (

				{ this.props.children }

    );
  }
}

<|next_version|>
import React, { Component } from 'react';
import { Link } from 'react-router';

import SetPage from '../components/SetPage';

export default class Pollard extends Component {
  render() {
    return (

<Link to="/setlist" activeClassName="active">Setlist</Link>

				{ this.props.children }

    );
  }
}


Add routes to handle login GET and POST

Add routes to handle login GET and POST

--- app.js
+++ app.js
@@ -4,6 +4,7 @@
 const path = require('path')
 const bodyParser = require('body-parser')
 const register = require('./routes/register')
+const login = require('./routes/login')
 // view engine setup
 app.set('views', path.join(__dirname, 'views'))
 app.set('view engine', 'ejs')
@@ -20,6 +21,9 @@
 app.get('/register', register.form)
 app.post('/register', register.submit)

+app.get('/login', login.form)
+app.post('/login', login.submit)
+
 http.listen(3000, () => {
   console.log('Server is listening at * 3000')
 })

<|original_code|>
const express = require('express')
const app = express()
const http = require('http').Server(app)
const path = require('path')
const bodyParser = require('body-parser')
const register = require('./routes/register')
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')

// Looks for external JS file holding front-end logic
app.use(express.static(path.join(__dirname, '/public')))

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

app.get('/', (req, res) => {
  res.render('chat_ui')
})
app.get('/register', register.form)
app.post('/register', register.submit)

http.listen(3000, () => {
  console.log('Server is listening at * 3000')
})

const socket = require('./lib/chat_server')
socket.listen(http)

<|edits_diff|>
--- app.js
+++ app.js
@@ -4,6 +4,7 @@
 const path = require('path')
 const bodyParser = require('body-parser')
 const register = require('./routes/register')
+const login = require('./routes/login')
 // view engine setup
 app.set('views', path.join(__dirname, 'views'))
 app.set('view engine', 'ejs')
<|current_version|>
const express = require('express')
const app = express()
const http = require('http').Server(app)
const path = require('path')
const bodyParser = require('body-parser')
const register = require('./routes/register')
const login = require('./routes/login')
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')

// Looks for external JS file holding front-end logic
app.use(express.static(path.join(__dirname, '/public')))

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

app.get('/', (req, res) => {
  res.render('chat_ui')
})
app.get('/register', register.form)
app.post('/register', register.submit)

http.listen(3000, () => {
  console.log('Server is listening at * 3000')
})

const socket = require('./lib/chat_server')
socket.listen(http)

<|next_version|>
const express = require('express')
const app = express()
const http = require('http').Server(app)
const path = require('path')
const bodyParser = require('body-parser')
const register = require('./routes/register')
const login = require('./routes/login')
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')

// Looks for external JS file holding front-end logic
app.use(express.static(path.join(__dirname, '/public')))

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

app.get('/', (req, res) => {
  res.render('chat_ui')
})
app.get('/register', register.form)
app.post('/register', register.submit)

app.get('/login', login.form)
app.post('/login', login.submit)

http.listen(3000, () => {
  console.log('Server is listening at * 3000')
})

const socket = require('./lib/chat_server')
socket.listen(http)


Fix Gulp task not closing

Fix Gulp task not closing

--- gulp/utils/watch.js
+++ gulp/utils/watch.js
@@ -1,5 +1,6 @@
 'use strict';

+const process = require('process');
 const { promisify } = require('util');

 const { watch, series, parallel } = require('gulp');
@@ -30,6 +31,10 @@
 const watchByType = async function ({ type, task }) {
   const taskA = Array.isArray(task) ? parallel(task) : task;
   const watcher = watch(FILES[type], taskA);
+
+  // Otherwise the task will hang when fired through npm scripts
+  process.on('SIGINT', watcher.close.bind(watcher));
+
   // Wait for watching to be setup to mark the `watch` task as complete
   await promisify(watcher.on.bind(watcher))('ready');
 };

<|original_code|>
'use strict';

const { promisify } = require('util');

const { watch, series, parallel } = require('gulp');

const FILES = require('../files');

// Returns a watch task
// E.g. with `tasks` `{ FORMAT: format }`, the `format` task will be fired
// everytime `FILES.FORMAT` is changed.
// If specified, `initialTask` is fired first
const getWatchTask = function (tasks, initialTask) {
  const watchTask = getWatchTasks(tasks);

  if (initialTask === undefined) { return watchTask; }

  // Runs the task before watching
  // Using `ignoreInitial` chokidar option does not work because the task would
  // be marked as complete before the initial run.
  return series(initialTask, watchTask);
};

const getWatchTasks = tasks => function watchTasks () {
  const promises = Object.entries(tasks)
    .map(([type, task]) => watchByType({ type, task }));
  return Promise.all(promises);
};

const watchByType = async function ({ type, task }) {
  const taskA = Array.isArray(task) ? parallel(task) : task;
  const watcher = watch(FILES[type], taskA);
  // Wait for watching to be setup to mark the `watch` task as complete
  await promisify(watcher.on.bind(watcher))('ready');
};

module.exports = {
  getWatchTask,
};

<|edits_diff|>
--- gulp/utils/watch.js
+++ gulp/utils/watch.js
@@ -1,5 +1,6 @@
 'use strict';

+const process = require('process');
 const { promisify } = require('util');

 const { watch, series, parallel } = require('gulp');
<|current_version|>
'use strict';

const process = require('process');
const { promisify } = require('util');

const { watch, series, parallel } = require('gulp');

const FILES = require('../files');

// Returns a watch task
// E.g. with `tasks` `{ FORMAT: format }`, the `format` task will be fired
// everytime `FILES.FORMAT` is changed.
// If specified, `initialTask` is fired first
const getWatchTask = function (tasks, initialTask) {
  const watchTask = getWatchTasks(tasks);

  if (initialTask === undefined) { return watchTask; }

  // Runs the task before watching
  // Using `ignoreInitial` chokidar option does not work because the task would
  // be marked as complete before the initial run.
  return series(initialTask, watchTask);
};

const getWatchTasks = tasks => function watchTasks () {
  const promises = Object.entries(tasks)
    .map(([type, task]) => watchByType({ type, task }));
  return Promise.all(promises);
};

const watchByType = async function ({ type, task }) {
  const taskA = Array.isArray(task) ? parallel(task) : task;
  const watcher = watch(FILES[type], taskA);
  // Wait for watching to be setup to mark the `watch` task as complete
  await promisify(watcher.on.bind(watcher))('ready');
};

module.exports = {
  getWatchTask,
};

<|next_version|>
'use strict';

const process = require('process');
const { promisify } = require('util');

const { watch, series, parallel } = require('gulp');

const FILES = require('../files');

// Returns a watch task
// E.g. with `tasks` `{ FORMAT: format }`, the `format` task will be fired
// everytime `FILES.FORMAT` is changed.
// If specified, `initialTask` is fired first
const getWatchTask = function (tasks, initialTask) {
  const watchTask = getWatchTasks(tasks);

  if (initialTask === undefined) { return watchTask; }

  // Runs the task before watching
  // Using `ignoreInitial` chokidar option does not work because the task would
  // be marked as complete before the initial run.
  return series(initialTask, watchTask);
};

const getWatchTasks = tasks => function watchTasks () {
  const promises = Object.entries(tasks)
    .map(([type, task]) => watchByType({ type, task }));
  return Promise.all(promises);
};

const watchByType = async function ({ type, task }) {
  const taskA = Array.isArray(task) ? parallel(task) : task;
  const watcher = watch(FILES[type], taskA);

  // Otherwise the task will hang when fired through npm scripts
  process.on('SIGINT', watcher.close.bind(watcher));

  // Wait for watching to be setup to mark the `watch` task as complete
  await promisify(watcher.on.bind(watcher))('ready');
};

module.exports = {
  getWatchTask,
};


Add sinon to global vars

Add sinon to global vars

--- config/mocha.js
+++ config/mocha.js
@@ -1,4 +1,6 @@
 import chai from 'chai';
+import sinon from 'sinon';

 global.chai = chai;
 global.expect = chai.expect;
+global.sinon = sinon;

<|original_code|>
import chai from 'chai';

global.chai = chai;
global.expect = chai.expect;

<|edits_diff|>
--- config/mocha.js
+++ config/mocha.js
@@ -1,4 +1,5 @@
 import chai from 'chai';
+import sinon from 'sinon';

 global.chai = chai;
 global.expect = chai.expect;
<|current_version|>
import chai from 'chai';
import sinon from 'sinon';

global.chai = chai;
global.expect = chai.expect;

<|next_version|>
import chai from 'chai';
import sinon from 'sinon';

global.chai = chai;
global.expect = chai.expect;
global.sinon = sinon;


Add Emittery back into the event mangager

--- packages/truffle-event-manager/index.js
+++ packages/truffle-event-manager/index.js
@@ -1,4 +1,5 @@
 const { ReporterAggregator } = require("truffle-reporters");
+const Emittery = require("emittery");

 class EventManager {
   constructor(eventManagerOptions) {
@@ -8,7 +9,11 @@
     // if necessary in truffle-config
     this.initializationOptions = eventManagerOptions;

+    const emitter = new Emittery();
+    this.emitter = emitter;
+
     const initializationOptions = {
+      emitter,
       globalConfig,
       logger,
       muteReporters

<|original_code|>
const { ReporterAggregator } = require("truffle-reporters");

class EventManager {
  constructor(eventManagerOptions) {
    const { logger, muteReporters, globalConfig } = eventManagerOptions;

    // Keep a reference to these so it can be cloned
    // if necessary in truffle-config
    this.initializationOptions = eventManagerOptions;

    const initializationOptions = {
      globalConfig,
      logger,
      muteReporters
    };
    this.initializeSubscribers(initializationOptions);
  }

  emit(event, data) {
    if (this.reporters) this.reporters.emit(event, data);
  }

  initializeReporters(initializationOptions) {
    this.reporters = new ReporterAggregator(initializationOptions);
  }

  initializeSubscribers(initializationOptions) {
    const { muteReporters } = initializationOptions;
    if (!muteReporters) this.initializeReporters(initializationOptions);
  }
}

module.exports = EventManager;

<|edits_diff|>
--- packages/truffle-event-manager/index.js
+++ packages/truffle-event-manager/index.js
@@ -1,4 +1,5 @@
 const { ReporterAggregator } = require("truffle-reporters");
+const Emittery = require("emittery");

 class EventManager {
   constructor(eventManagerOptions) {
@@ -7,6 +8,9 @@
     // Keep a reference to these so it can be cloned
     // if necessary in truffle-config
     this.initializationOptions = eventManagerOptions;
+
+    const emitter = new Emittery();
+    this.emitter = emitter;

     const initializationOptions = {
       globalConfig,
<|current_version|>
const { ReporterAggregator } = require("truffle-reporters");
const Emittery = require("emittery");

class EventManager {
  constructor(eventManagerOptions) {
    const { logger, muteReporters, globalConfig } = eventManagerOptions;

    // Keep a reference to these so it can be cloned
    // if necessary in truffle-config
    this.initializationOptions = eventManagerOptions;

    const emitter = new Emittery();
    this.emitter = emitter;

    const initializationOptions = {
      globalConfig,
      logger,
      muteReporters
    };
    this.initializeSubscribers(initializationOptions);
  }

  emit(event, data) {
    if (this.reporters) this.reporters.emit(event, data);
  }

  initializeReporters(initializationOptions) {
    this.reporters = new ReporterAggregator(initializationOptions);
  }

  initializeSubscribers(initializationOptions) {
    const { muteReporters } = initializationOptions;
    if (!muteReporters) this.initializeReporters(initializationOptions);
  }
}

module.exports = EventManager;

<|next_version|>
const { ReporterAggregator } = require("truffle-reporters");
const Emittery = require("emittery");

class EventManager {
  constructor(eventManagerOptions) {
    const { logger, muteReporters, globalConfig } = eventManagerOptions;

    // Keep a reference to these so it can be cloned
    // if necessary in truffle-config
    this.initializationOptions = eventManagerOptions;

    const emitter = new Emittery();
    this.emitter = emitter;

    const initializationOptions = {
      emitter,
      globalConfig,
      logger,
      muteReporters
    };
    this.initializeSubscribers(initializationOptions);
  }

  emit(event, data) {
    if (this.reporters) this.reporters.emit(event, data);
  }

  initializeReporters(initializationOptions) {
    this.reporters = new ReporterAggregator(initializationOptions);
  }

  initializeSubscribers(initializationOptions) {
    const { muteReporters } = initializationOptions;
    if (!muteReporters) this.initializeReporters(initializationOptions);
  }
}

module.exports = EventManager;


Check if a track is playing

Check if a track is playing

--- src/components/RecentTracks.js
+++ src/components/RecentTracks.js
@@ -2,14 +2,20 @@
 import './RecentTracks.css';
 import RecentTrack from './RecentTrack.js';
 import _map from 'lodash/map';
+import _isEqual from 'lodash/isEqual';
 import {
   fetchRecentTracks
 } from '../actions/action-creators';

 let RecentTracks = React.createClass ({

+  shouldComponentUpdate(nextProps){
+    return !_isEqual(nextProps.recentTracks,this.props.recentTracks);
+  },
+
   componentWillMount() {
     fetchRecentTracks();
+    // this.updateInterval = setInterval(() => fetchRecentTracks(2), 3000);
   },

   render() {

<|original_code|>
import React from 'react';
import './RecentTracks.css';
import RecentTrack from './RecentTrack.js';
import _map from 'lodash/map';
import {
  fetchRecentTracks
} from '../actions/action-creators';

let RecentTracks = React.createClass ({

  componentWillMount() {
    fetchRecentTracks();
  },

  render() {

    const {
      recentTracks
    } = this.props;

    let RecentTrackElement;
    if (recentTracks) {
      RecentTrackElement = _map(recentTracks, (recentTrack, i) => (
        <RecentTrack
          key={i}
          recentTrack={recentTrack} />
      ));
    }

    return (
    <section
      className="RecentTracks">
      {RecentTrackElement}
    </section>
    );
  }
});

export default RecentTracks;

<|edits_diff|>
--- src/components/RecentTracks.js
+++ src/components/RecentTracks.js
@@ -2,11 +2,16 @@
 import './RecentTracks.css';
 import RecentTrack from './RecentTrack.js';
 import _map from 'lodash/map';
+import _isEqual from 'lodash/isEqual';
 import {
   fetchRecentTracks
 } from '../actions/action-creators';

 let RecentTracks = React.createClass ({
+
+  shouldComponentUpdate(nextProps){
+    return !_isEqual(nextProps.recentTracks,this.props.recentTracks);
+  },

   componentWillMount() {
     fetchRecentTracks();
<|current_version|>
import React from 'react';
import './RecentTracks.css';
import RecentTrack from './RecentTrack.js';
import _map from 'lodash/map';
import _isEqual from 'lodash/isEqual';
import {
  fetchRecentTracks
} from '../actions/action-creators';

let RecentTracks = React.createClass ({

  shouldComponentUpdate(nextProps){
    return !_isEqual(nextProps.recentTracks,this.props.recentTracks);
  },

  componentWillMount() {
    fetchRecentTracks();
  },

  render() {

    const {
      recentTracks
    } = this.props;

    let RecentTrackElement;
    if (recentTracks) {
      RecentTrackElement = _map(recentTracks, (recentTrack, i) => (
        <RecentTrack
          key={i}
          recentTrack={recentTrack} />
      ));
    }

    return (
    <section
      className="RecentTracks">
      {RecentTrackElement}
    </section>
    );
  }
});

export default RecentTracks;

<|next_version|>
import React from 'react';
import './RecentTracks.css';
import RecentTrack from './RecentTrack.js';
import _map from 'lodash/map';
import _isEqual from 'lodash/isEqual';
import {
  fetchRecentTracks
} from '../actions/action-creators';

let RecentTracks = React.createClass ({

  shouldComponentUpdate(nextProps){
    return !_isEqual(nextProps.recentTracks,this.props.recentTracks);
  },

  componentWillMount() {
    fetchRecentTracks();
    // this.updateInterval = setInterval(() => fetchRecentTracks(2), 3000);
  },

  render() {

    const {
      recentTracks
    } = this.props;

    let RecentTrackElement;
    if (recentTracks) {
      RecentTrackElement = _map(recentTracks, (recentTrack, i) => (
        <RecentTrack
          key={i}
          recentTrack={recentTrack} />
      ));
    }

    return (
    <section
      className="RecentTracks">
      {RecentTrackElement}
    </section>
    );
  }
});

export default RecentTracks;


Edit sentence list to show a detail

Edit sentence list to show a detail

--- src/components/SentenceList.js
+++ src/components/SentenceList.js
@@ -10,6 +10,7 @@

             Sentence
+            Detail
             CreatedAt
             Source

@@ -21,6 +22,7 @@
                 key={index}
               >
                 {sentence.sentence}
+                {sentence.detail}
                 {sentence.createdAt.toLocaleString()}
                 {sentence.source.title}

<|original_code|>
import React from 'react'
import PropTypes from 'prop-types'

const SentenceList = ({sentences, isLoading}) => (

    {isLoading ? (

    ) : (

            Sentence
            CreatedAt
            Source

          {
            sentences.map((sentence, index) => (

                {sentence.sentence}
                {sentence.createdAt.toLocaleString()}
                {sentence.source.title}

            ))
          }

    )}

)

SentenceList.propTypes = {
  sentences: PropTypes.array.isRequired,
  isLoading: PropTypes.bool.isRequired,
}

export default SentenceList

<|edits_diff|>
--- src/components/SentenceList.js
+++ src/components/SentenceList.js
@@ -10,6 +10,7 @@

             Sentence
+            Detail
             CreatedAt
             Source

<|current_version|>
import React from 'react'
import PropTypes from 'prop-types'

const SentenceList = ({sentences, isLoading}) => (

    {isLoading ? (

    ) : (

            Sentence
            Detail
            CreatedAt
            Source

          {
            sentences.map((sentence, index) => (

                {sentence.sentence}
                {sentence.createdAt.toLocaleString()}
                {sentence.source.title}

            ))
          }

    )}

)

SentenceList.propTypes = {
  sentences: PropTypes.array.isRequired,
  isLoading: PropTypes.bool.isRequired,
}

export default SentenceList

<|next_version|>
import React from 'react'
import PropTypes from 'prop-types'

const SentenceList = ({sentences, isLoading}) => (

    {isLoading ? (

    ) : (

            Sentence
            Detail
            CreatedAt
            Source

          {
            sentences.map((sentence, index) => (

                {sentence.sentence}
                {sentence.detail}
                {sentence.createdAt.toLocaleString()}
                {sentence.source.title}

            ))
          }

    )}

)

SentenceList.propTypes = {
  sentences: PropTypes.array.isRequired,
  isLoading: PropTypes.bool.isRequired,
}

export default SentenceList


Support configuring the host and port of devserver

The HOST and PORT env variables may now be used to explicitly set the
host and port.

Signed-off-by: Byron Ruth <e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98@devel.io>

--- webpack.config.babel.js
+++ webpack.config.babel.js
@@ -1,3 +1,7 @@
+// Host and port
+const HOST = process.env.HOST || '127.0.0.1'
+const PORT = process.env.PORT || 3000
+
 export default {
   // Entrypoint of the application. It is named main since that
   // is most common in other programming environments.
@@ -11,6 +15,11 @@
   output: {
     path: __dirname + "/dist",
     filename: "bundle.js"
+  },
+
+  devServer: {
+    host: HOST,
+    port: PORT
   },

   // Each file that is processed can be optionally handled by a 'loader'

<|original_code|>
export default {
  // Entrypoint of the application. It is named main since that
  // is most common in other programming environments.
  entry: [
    // Entry point files.
    "./src/main.js",
    "./src/index.html"
  ],

  // Output of the built files to the specified path and filename.
  output: {
    path: __dirname + "/dist",
    filename: "bundle.js"
  },

  // Each file that is processed can be optionally handled by a 'loader'
  // which acts as a preprocessor.
  module: {
    loaders: [
      // The babel-loader handles all the transpilation work with
      // ES 2015 and JSX. See .babelrc for specifics about the configuration.
      {
        text: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      },

      // The file loader allows for webpack to copy other static assets.
      {
        test: /\.html$/,
        loader: "file?name=[name].[ext]"
      }
    ]
  }
}

<|edits_diff|>
--- webpack.config.babel.js
+++ webpack.config.babel.js
@@ -1,3 +1,7 @@
+// Host and port
+const HOST = process.env.HOST || '127.0.0.1'
+const PORT = process.env.PORT || 3000
+
 export default {
   // Entrypoint of the application. It is named main since that
   // is most common in other programming environments.
<|current_version|>
// Host and port
const HOST = process.env.HOST || '127.0.0.1'
const PORT = process.env.PORT || 3000

export default {
  // Entrypoint of the application. It is named main since that
  // is most common in other programming environments.
  entry: [
    // Entry point files.
    "./src/main.js",
    "./src/index.html"
  ],

  // Output of the built files to the specified path and filename.
  output: {
    path: __dirname + "/dist",
    filename: "bundle.js"
  },

  // Each file that is processed can be optionally handled by a 'loader'
  // which acts as a preprocessor.
  module: {
    loaders: [
      // The babel-loader handles all the transpilation work with
      // ES 2015 and JSX. See .babelrc for specifics about the configuration.
      {
        text: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      },

      // The file loader allows for webpack to copy other static assets.
      {
        test: /\.html$/,
        loader: "file?name=[name].[ext]"
      }
    ]
  }
}

<|next_version|>
// Host and port
const HOST = process.env.HOST || '127.0.0.1'
const PORT = process.env.PORT || 3000

export default {
  // Entrypoint of the application. It is named main since that
  // is most common in other programming environments.
  entry: [
    // Entry point files.
    "./src/main.js",
    "./src/index.html"
  ],

  // Output of the built files to the specified path and filename.
  output: {
    path: __dirname + "/dist",
    filename: "bundle.js"
  },

  devServer: {
    host: HOST,
    port: PORT
  },

  // Each file that is processed can be optionally handled by a 'loader'
  // which acts as a preprocessor.
  module: {
    loaders: [
      // The babel-loader handles all the transpilation work with
      // ES 2015 and JSX. See .babelrc for specifics about the configuration.
      {
        text: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      },

      // The file loader allows for webpack to copy other static assets.
      {
        test: /\.html$/,
        loader: "file?name=[name].[ext]"
      }
    ]
  }
}


Add a constructor for a component of the load-button

--- js/components/content-header.js
+++ js/components/content-header.js
@@ -4,7 +4,12 @@
   var jCore = require('jcore');
   var helper = app.helper || require('../helper.js');
   var dom = app.dom || require('../dom.js');
+  var Button = app.Button || require('./button.js');
   var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');
+
+  var LoadButton = helper.inherits(function(props) {
+    LoadButton.super_.call(this, props);
+  }, Button);

   var ContentHeader = helper.inherits(function(props) {
     ContentHeader.super_.call(this);

<|original_code|>
(function(app) {
  'use strict';

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');

  var ContentHeader = helper.inherits(function(props) {
    ContentHeader.super_.call(this);

    this.element = this.prop(props.element);

    this.sidebarToggleButton = this.prop(new SidebarToggleButton({
      element: this.sidebarToggleButtonElement(),
      collapser: props.sidebarCollapser,
      expander: props.sidebarExpander
    }));

    this.sidebarToggleButton().registerTapListener();
  }, jCore.Component);

  ContentHeader.prototype.sidebarToggleButtonElement = function() {
    return dom.child(this.element(), 0);
  };

  ContentHeader.prototype.loadButtonElement = function() {
    return dom.child(this.element(), 1);
  };

  ContentHeader.prototype.saveButtonElement = function() {
    return dom.child(this.element(), 2);
  };

  ContentHeader.prototype.redraw = function() {
    this.sidebarToggleButton().redraw();
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = ContentHeader;
  else
    app.ContentHeader = ContentHeader;
})(this.app || (this.app = {}));

<|edits_diff|>
--- js/components/content-header.js
+++ js/components/content-header.js
@@ -4,6 +4,7 @@
   var jCore = require('jcore');
   var helper = app.helper || require('../helper.js');
   var dom = app.dom || require('../dom.js');
+  var Button = app.Button || require('./button.js');
   var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');

   var ContentHeader = helper.inherits(function(props) {
<|current_version|>
(function(app) {
  'use strict';

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var Button = app.Button || require('./button.js');
  var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');

  var ContentHeader = helper.inherits(function(props) {
    ContentHeader.super_.call(this);

    this.element = this.prop(props.element);

    this.sidebarToggleButton = this.prop(new SidebarToggleButton({
      element: this.sidebarToggleButtonElement(),
      collapser: props.sidebarCollapser,
      expander: props.sidebarExpander
    }));

    this.sidebarToggleButton().registerTapListener();
  }, jCore.Component);

  ContentHeader.prototype.sidebarToggleButtonElement = function() {
    return dom.child(this.element(), 0);
  };

  ContentHeader.prototype.loadButtonElement = function() {
    return dom.child(this.element(), 1);
  };

  ContentHeader.prototype.saveButtonElement = function() {
    return dom.child(this.element(), 2);
  };

  ContentHeader.prototype.redraw = function() {
    this.sidebarToggleButton().redraw();
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = ContentHeader;
  else
    app.ContentHeader = ContentHeader;
})(this.app || (this.app = {}));

<|next_version|>
(function(app) {
  'use strict';

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var Button = app.Button || require('./button.js');
  var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');

  var LoadButton = helper.inherits(function(props) {
    LoadButton.super_.call(this, props);
  }, Button);

  var ContentHeader = helper.inherits(function(props) {
    ContentHeader.super_.call(this);

    this.element = this.prop(props.element);

    this.sidebarToggleButton = this.prop(new SidebarToggleButton({
      element: this.sidebarToggleButtonElement(),
      collapser: props.sidebarCollapser,
      expander: props.sidebarExpander
    }));

    this.sidebarToggleButton().registerTapListener();
  }, jCore.Component);

  ContentHeader.prototype.sidebarToggleButtonElement = function() {
    return dom.child(this.element(), 0);
  };

  ContentHeader.prototype.loadButtonElement = function() {
    return dom.child(this.element(), 1);
  };

  ContentHeader.prototype.saveButtonElement = function() {
    return dom.child(this.element(), 2);
  };

  ContentHeader.prototype.redraw = function() {
    this.sidebarToggleButton().redraw();
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = ContentHeader;
  else
    app.ContentHeader = ContentHeader;
})(this.app || (this.app = {}));


import React, { Component } from 'react';
import './App.css';
import Nav from './components/Nav'
import Home from './components/Home'
import HouseholdsContainer from './components/HouseholdsContainer'
import Signup from './components/Signup'
import Login from './components/Login'
import { authenticate, authenticationFailure, logout } from './redux/modules/Auth/actions'
import { connect } from 'react-redux'
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom'
import { Container } from 'semantic-ui-react'
import NewHousehold from './components/NewHousehold'

class App extends Component {

  componentDidMount() {
    const token = localStorage.getItem('token')

    if (token) {
      this.props.authenticate()
    } else {
      this.props.authenticationFailure()
    }
  }

  render() {
    return (

        <Router>
          <div>
            <Container text>
            <Nav logout={this.props.logout} />
            </Container>
            <Container>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/households/new" component={NewHousehold} />
                <Route path="/households" component={HouseholdsContainer} />
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} />
              </Switch>
            </Container>
          </div>
        </Router>
    );
  }
}

export default connect(null, { authenticate, authenticationFailure, logout })(App);

import React, { Component } from 'react';
import './App.css';
import Nav from './components/Nav'
import Home from './components/Home'
import HouseholdsContainer from './components/HouseholdsContainer'
import Signup from './components/Signup'
import Login from './components/Login'
import { authenticate, authenticationFailure, logout } from './redux/modules/Auth/actions'
import { connect } from 'react-redux'
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom'
import { Container } from 'semantic-ui-react'
import NewHousehold from './components/NewHousehold'
import NewMeal from './components/NewMeal'

class App extends Component {

  componentDidMount() {
    const token = localStorage.getItem('token')

    if (token) {
      this.props.authenticate()
    } else {
      this.props.authenticationFailure()
    }
  }

  render() {
    return (

        <Router>
          <div>
            <Container text>
            <Nav logout={this.props.logout} />
            </Container>
            <Container>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/households/new" component={NewHousehold} />
                <Route path="/households" component={HouseholdsContainer} />
                <Route path="/meals/new" component={NewMeal} />
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} />
              </Switch>
            </Container>
          </div>
        </Router>
    );
  }
}

export default connect(null, { authenticate, authenticationFailure, logout })(App);

Create route for new meal form

Create route for new meal form

--- src/App.js
+++ src/App.js
@@ -14,6 +14,7 @@
 } from 'react-router-dom'
 import { Container } from 'semantic-ui-react'
 import NewHousehold from './components/NewHousehold'
+import NewMeal from './components/NewMeal'

 class App extends Component {

@@ -40,6 +41,7 @@
                 <Route exact path="/" component={Home} />
                 <Route path="/households/new" component={NewHousehold} />
                 <Route path="/households" component={HouseholdsContainer} />
+                <Route path="/meals/new" component={NewMeal} />
                 <Route path="/signup" component={Signup} />
                 <Route path="/login" component={Login} />
               </Switch>

import React, { Component } from 'react';
import './App.css';
import Nav from './components/Nav'
import Home from './components/Home'
import HouseholdsContainer from './components/HouseholdsContainer'
import Signup from './components/Signup'
import Login from './components/Login'
import { authenticate, authenticationFailure, logout } from './redux/modules/Auth/actions'
import { connect } from 'react-redux'
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom'
import { Container } from 'semantic-ui-react'
import NewHousehold from './components/NewHousehold'
import NewMeal from './components/NewMeal'

class App extends Component {

  componentDidMount() {
    const token = localStorage.getItem('token')

    if (token) {
      this.props.authenticate()
    } else {
      this.props.authenticationFailure()
    }
  }

  render() {
    return (

        <Router>
          <div>
            <Container text>
            <Nav logout={this.props.logout} />
            </Container>
            <Container>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/households/new" component={NewHousehold} />
                <Route path="/households" component={HouseholdsContainer} />
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} />
              </Switch>
            </Container>
          </div>
        </Router>
    );
  }
}

export default connect(null, { authenticate, authenticationFailure, logout })(App);

<|original_code|>
import React, { Component } from 'react';
import './App.css';
import Nav from './components/Nav'
import Home from './components/Home'
import HouseholdsContainer from './components/HouseholdsContainer'
import Signup from './components/Signup'
import Login from './components/Login'
import { authenticate, authenticationFailure, logout } from './redux/modules/Auth/actions'
import { connect } from 'react-redux'
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom'
import { Container } from 'semantic-ui-react'
import NewHousehold from './components/NewHousehold'

class App extends Component {

  componentDidMount() {
    const token = localStorage.getItem('token')

    if (token) {
      this.props.authenticate()
    } else {
      this.props.authenticationFailure()
    }
  }

  render() {
    return (

        <Router>

            <Container text>

            </Container>
            <Container>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/households/new" component={NewHousehold} />
                <Route path="/households" component={HouseholdsContainer} />
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} />
              </Switch>
            </Container>

        </Router>
    );
  }
}

export default connect(null, { authenticate, authenticationFailure, logout })(App);

<|edits_diff|>
--- src/App.js
+++ src/App.js
@@ -14,6 +14,7 @@
 } from 'react-router-dom'
 import { Container } from 'semantic-ui-react'
 import NewHousehold from './components/NewHousehold'
+import NewMeal from './components/NewMeal'

 class App extends Component {

<|current_version|>
import React, { Component } from 'react';
import './App.css';
import Nav from './components/Nav'
import Home from './components/Home'
import HouseholdsContainer from './components/HouseholdsContainer'
import Signup from './components/Signup'
import Login from './components/Login'
import { authenticate, authenticationFailure, logout } from './redux/modules/Auth/actions'
import { connect } from 'react-redux'
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom'
import { Container } from 'semantic-ui-react'
import NewHousehold from './components/NewHousehold'
import NewMeal from './components/NewMeal'

class App extends Component {

  componentDidMount() {
    const token = localStorage.getItem('token')

    if (token) {
      this.props.authenticate()
    } else {
      this.props.authenticationFailure()
    }
  }

  render() {
    return (

        <Router>

            <Container text>

            </Container>
            <Container>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/households/new" component={NewHousehold} />
                <Route path="/households" component={HouseholdsContainer} />
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} />
              </Switch>
            </Container>

        </Router>
    );
  }
}

export default connect(null, { authenticate, authenticationFailure, logout })(App);

<|next_version|>
import React, { Component } from 'react';
import './App.css';
import Nav from './components/Nav'
import Home from './components/Home'
import HouseholdsContainer from './components/HouseholdsContainer'
import Signup from './components/Signup'
import Login from './components/Login'
import { authenticate, authenticationFailure, logout } from './redux/modules/Auth/actions'
import { connect } from 'react-redux'
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom'
import { Container } from 'semantic-ui-react'
import NewHousehold from './components/NewHousehold'
import NewMeal from './components/NewMeal'

class App extends Component {

  componentDidMount() {
    const token = localStorage.getItem('token')

    if (token) {
      this.props.authenticate()
    } else {
      this.props.authenticationFailure()
    }
  }

  render() {
    return (

        <Router>

            <Container text>

            </Container>
            <Container>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/households/new" component={NewHousehold} />
                <Route path="/households" component={HouseholdsContainer} />
                <Route path="/meals/new" component={NewMeal} />
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} />
              </Switch>
            </Container>

        </Router>
    );
  }
}

export default connect(null, { authenticate, authenticationFailure, logout })(App);


Update gulp to watch scripts and html

Update gulp to watch scripts and html

--- gulpfile.js
+++ gulpfile.js
@@ -1,5 +1,6 @@
 var gulp = require('gulp');
 var bs = require('browser-sync').create();
+var reload = bs.reload;

 gulp.task('default', function() {
   bs.init({
@@ -10,5 +11,8 @@
       }
     }
   });
+
+  gulp.watch("app/**/*.html").on('change', reload);
+  gulp.watch("app/scripts/**/*.js").on('change', reload);
 });

<|original_code|>
var gulp = require('gulp');
var bs = require('browser-sync').create();

gulp.task('default', function() {
  bs.init({
    server: {
      baseDir: "./app",
      routes: {
        "/lib": "bower_components"
      }
    }
  });
});

<|edits_diff|>
--- gulpfile.js
+++ gulpfile.js
@@ -1,5 +1,6 @@
 var gulp = require('gulp');
 var bs = require('browser-sync').create();
+var reload = bs.reload;

 gulp.task('default', function() {
   bs.init({
<|current_version|>
var gulp = require('gulp');
var bs = require('browser-sync').create();
var reload = bs.reload;

gulp.task('default', function() {
  bs.init({
    server: {
      baseDir: "./app",
      routes: {
        "/lib": "bower_components"
      }
    }
  });
});

<|next_version|>
var gulp = require('gulp');
var bs = require('browser-sync').create();
var reload = bs.reload;

gulp.task('default', function() {
  bs.init({
    server: {
      baseDir: "./app",
      routes: {
        "/lib": "bower_components"
      }
    }
  });

  gulp.watch("app/**/*.html").on('change', reload);
  gulp.watch("app/scripts/**/*.js").on('change', reload);
});


Add AwsS3 to the dist bundle.

Add AwsS3 to the dist bundle.

--- src/index.js
+++ src/index.js
@@ -26,6 +26,7 @@
 const Tus10 = require('./plugins/Tus10')
 const XHRUpload = require('./plugins/XHRUpload')
 const Transloadit = require('./plugins/Transloadit')
+const AwsS3 = require('./plugins/AwsS3')

 module.exports = {
   Core,
@@ -41,6 +42,7 @@
   Tus10,
   XHRUpload,
   Transloadit,
+  AwsS3,
   Dashboard,
   MetaData,
   Webcam

<|original_code|>
const Core = require('./core/index.js')

// Parent
const Plugin = require('./plugins/Plugin')

// Orchestrators
const Dashboard = require('./plugins/Dashboard/index.js')

// Acquirers
const Dummy = require('./plugins/Dummy')
const DragDrop = require('./plugins/DragDrop/index.js')
const FileInput = require('./plugins/FileInput.js')
const GoogleDrive = require('./plugins/GoogleDrive/index.js')
const Dropbox = require('./plugins/Dropbox/index.js')
const Instagram = require('./plugins/Instagram/index.js')
const Webcam = require('./plugins/Webcam/index.js')

// Progressindicators
const ProgressBar = require('./plugins/ProgressBar.js')
const Informer = require('./plugins/Informer.js')

// Modifiers
const MetaData = require('./plugins/MetaData.js')

// Uploaders
const Tus10 = require('./plugins/Tus10')
const XHRUpload = require('./plugins/XHRUpload')
const Transloadit = require('./plugins/Transloadit')

module.exports = {
  Core,
  Plugin,
  Dummy,
  ProgressBar,
  Informer,
  DragDrop,
  GoogleDrive,
  Dropbox,
  Instagram,
  FileInput,
  Tus10,
  XHRUpload,
  Transloadit,
  Dashboard,
  MetaData,
  Webcam
}

<|edits_diff|>
--- src/index.js
+++ src/index.js
@@ -26,6 +26,7 @@
 const Tus10 = require('./plugins/Tus10')
 const XHRUpload = require('./plugins/XHRUpload')
 const Transloadit = require('./plugins/Transloadit')
+const AwsS3 = require('./plugins/AwsS3')

 module.exports = {
   Core,
<|current_version|>
const Core = require('./core/index.js')

// Parent
const Plugin = require('./plugins/Plugin')

// Orchestrators
const Dashboard = require('./plugins/Dashboard/index.js')

// Acquirers
const Dummy = require('./plugins/Dummy')
const DragDrop = require('./plugins/DragDrop/index.js')
const FileInput = require('./plugins/FileInput.js')
const GoogleDrive = require('./plugins/GoogleDrive/index.js')
const Dropbox = require('./plugins/Dropbox/index.js')
const Instagram = require('./plugins/Instagram/index.js')
const Webcam = require('./plugins/Webcam/index.js')

// Progressindicators
const ProgressBar = require('./plugins/ProgressBar.js')
const Informer = require('./plugins/Informer.js')

// Modifiers
const MetaData = require('./plugins/MetaData.js')

// Uploaders
const Tus10 = require('./plugins/Tus10')
const XHRUpload = require('./plugins/XHRUpload')
const Transloadit = require('./plugins/Transloadit')
const AwsS3 = require('./plugins/AwsS3')

module.exports = {
  Core,
  Plugin,
  Dummy,
  ProgressBar,
  Informer,
  DragDrop,
  GoogleDrive,
  Dropbox,
  Instagram,
  FileInput,
  Tus10,
  XHRUpload,
  Transloadit,
  Dashboard,
  MetaData,
  Webcam
}

<|next_version|>
const Core = require('./core/index.js')

// Parent
const Plugin = require('./plugins/Plugin')

// Orchestrators
const Dashboard = require('./plugins/Dashboard/index.js')

// Acquirers
const Dummy = require('./plugins/Dummy')
const DragDrop = require('./plugins/DragDrop/index.js')
const FileInput = require('./plugins/FileInput.js')
const GoogleDrive = require('./plugins/GoogleDrive/index.js')
const Dropbox = require('./plugins/Dropbox/index.js')
const Instagram = require('./plugins/Instagram/index.js')
const Webcam = require('./plugins/Webcam/index.js')

// Progressindicators
const ProgressBar = require('./plugins/ProgressBar.js')
const Informer = require('./plugins/Informer.js')

// Modifiers
const MetaData = require('./plugins/MetaData.js')

// Uploaders
const Tus10 = require('./plugins/Tus10')
const XHRUpload = require('./plugins/XHRUpload')
const Transloadit = require('./plugins/Transloadit')
const AwsS3 = require('./plugins/AwsS3')

module.exports = {
  Core,
  Plugin,
  Dummy,
  ProgressBar,
  Informer,
  DragDrop,
  GoogleDrive,
  Dropbox,
  Instagram,
  FileInput,
  Tus10,
  XHRUpload,
  Transloadit,
  AwsS3,
  Dashboard,
  MetaData,
  Webcam
}


Fix package.json parsing when project is not initialized

--- lib/OptionsParser.js
+++ lib/OptionsParser.js
@@ -9,7 +9,11 @@

     static parse() {
         var smildFile = null,
+            packageJson = {};
+        try {
             packageJson = require(path.join(process.cwd(), 'package.json'));
+        } catch (error) {
+        }
         try {
             smildFile = require(path.join(process.cwd(), 'smildfile.js'));
         } catch (error) {

<|original_code|>
"use strict";

const DefaultOptions = require('./DefaultOptions'),
    path = require('path'),
    _ = require('lodash'),
    fs = require('fs');

class OptionsParser {

    static parse() {
        var smildFile = null,
            packageJson = require(path.join(process.cwd(), 'package.json'));
        try {
            smildFile = require(path.join(process.cwd(), 'smildfile.js'));
        } catch (error) {
            smildFile = {};
        }
        return _.assign(DefaultOptions(smildFile.projectType), smildFile, {
            projectPackage: packageJson
        });
    }

    static parseTypescript() {
        return this.parseProjectFile('tsconfig.json');
    }

    static parseBabel() {
        return this.parseProjectFile('.babelrc');
    }

    static parseProjectFile(filename) {
        try {
            return JSON.parse(fs.readFileSync(path.join(process.cwd(), filename), 'utf8'));
        } catch (error) {
            return JSON.parse(fs.readFileSync(path.join(__dirname, '../', filename), 'utf8'));
        }
    }
}

module.exports = OptionsParser;
<|edits_diff|>
--- lib/OptionsParser.js
+++ lib/OptionsParser.js
@@ -9,6 +9,8 @@

     static parse() {
         var smildFile = null,
+            packageJson = {};
+        try {
             packageJson = require(path.join(process.cwd(), 'package.json'));
         try {
             smildFile = require(path.join(process.cwd(), 'smildfile.js'));
<|current_version|>
"use strict";

const DefaultOptions = require('./DefaultOptions'),
    path = require('path'),
    _ = require('lodash'),
    fs = require('fs');

class OptionsParser {

    static parse() {
        var smildFile = null,
            packageJson = {};
        try {
            packageJson = require(path.join(process.cwd(), 'package.json'));
        try {
            smildFile = require(path.join(process.cwd(), 'smildfile.js'));
        } catch (error) {
            smildFile = {};
        }
        return _.assign(DefaultOptions(smildFile.projectType), smildFile, {
            projectPackage: packageJson
        });
    }

    static parseTypescript() {
        return this.parseProjectFile('tsconfig.json');
    }

    static parseBabel() {
        return this.parseProjectFile('.babelrc');
    }

    static parseProjectFile(filename) {
        try {
            return JSON.parse(fs.readFileSync(path.join(process.cwd(), filename), 'utf8'));
        } catch (error) {
            return JSON.parse(fs.readFileSync(path.join(__dirname, '../', filename), 'utf8'));
        }
    }
}

module.exports = OptionsParser;
<|next_version|>
"use strict";

const DefaultOptions = require('./DefaultOptions'),
    path = require('path'),
    _ = require('lodash'),
    fs = require('fs');

class OptionsParser {

    static parse() {
        var smildFile = null,
            packageJson = {};
        try {
            packageJson = require(path.join(process.cwd(), 'package.json'));
        } catch (error) {
        }
        try {
            smildFile = require(path.join(process.cwd(), 'smildfile.js'));
        } catch (error) {
            smildFile = {};
        }
        return _.assign(DefaultOptions(smildFile.projectType), smildFile, {
            projectPackage: packageJson
        });
    }

    static parseTypescript() {
        return this.parseProjectFile('tsconfig.json');
    }

    static parseBabel() {
        return this.parseProjectFile('.babelrc');
    }

    static parseProjectFile(filename) {
        try {
            return JSON.parse(fs.readFileSync(path.join(process.cwd(), filename), 'utf8'));
        } catch (error) {
            return JSON.parse(fs.readFileSync(path.join(__dirname, '../', filename), 'utf8'));
        }
    }
}

module.exports = OptionsParser;


Add variables and code for emptying output list at the beginning of a new number submission

--- js/scripts.js
+++ js/scripts.js
@@ -8,7 +8,11 @@

 $(function() {
   $("form#game").submit(function(event) {
+    $("#outputList").empty();

+    var number = parseInt($("#userNumber").val())
+    var output = pingPong(number)
+
     event.preventDefault();
   });
 });

<|original_code|>
var pingPong = function(userNumber) {
  if ((userNumber % 3 === 0) || (userNumber % 5 === 0)) {
    return true;
  } else {
    return false;
  }
};

$(function() {
  $("form#game").submit(function(event) {

    event.preventDefault();
  });
});

<|edits_diff|>
--- js/scripts.js
+++ js/scripts.js
@@ -8,6 +8,7 @@

 $(function() {
   $("form#game").submit(function(event) {
+    $("#outputList").empty();

     event.preventDefault();
   });
<|current_version|>
var pingPong = function(userNumber) {
  if ((userNumber % 3 === 0) || (userNumber % 5 === 0)) {
    return true;
  } else {
    return false;
  }
};

$(function() {
  $("form#game").submit(function(event) {
    $("#outputList").empty();

    event.preventDefault();
  });
});

<|next_version|>
var pingPong = function(userNumber) {
  if ((userNumber % 3 === 0) || (userNumber % 5 === 0)) {
    return true;
  } else {
    return false;
  }
};

$(function() {
  $("form#game").submit(function(event) {
    $("#outputList").empty();

    var number = parseInt($("#userNumber").val())
    var output = pingPong(number)

    event.preventDefault();
  });
});


Add styles for buttons and author

Add styles for buttons and author

--- js/gradient.js
+++ js/gradient.js
@@ -14,5 +14,7 @@
     var linearGradient = 'linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';

     $('body').css('background-color', rgb1);
+    $('button').css('background-color', rgb1);
     $('#quote').css('color', rgb1);
+    $('#author').css('color', rgb1);
 };

<|original_code|>
var getGradient = function () {
    var red1 = Math.floor(Math.random() * 256);
    var green1 = Math.floor(Math.random() * 256);
    var blue1 = Math.floor(Math.random() * 256);

    var red2 = Math.floor(Math.random() * 256);
    var green2 = Math.floor(Math.random() * 256);
    var blue2 = Math.floor(Math.random() * 256);

    var rgb1 = 'rgb(' + red1 + ',' + green1 + ',' + blue1 + ')';
    var rgb2 = 'rgb(' + red2 + ',' + green2 + ',' + blue2 + ')';

    var webkitLinearGradient = '-webkit-linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';
    var linearGradient = 'linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';

    $('body').css('background-color', rgb1);
    $('#quote').css('color', rgb1);
};
<|edits_diff|>
--- js/gradient.js
+++ js/gradient.js
@@ -14,5 +14,6 @@
     var linearGradient = 'linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';

     $('body').css('background-color', rgb1);
+    $('button').css('background-color', rgb1);
     $('#quote').css('color', rgb1);
 };
<|current_version|>
var getGradient = function () {
    var red1 = Math.floor(Math.random() * 256);
    var green1 = Math.floor(Math.random() * 256);
    var blue1 = Math.floor(Math.random() * 256);

    var red2 = Math.floor(Math.random() * 256);
    var green2 = Math.floor(Math.random() * 256);
    var blue2 = Math.floor(Math.random() * 256);

    var rgb1 = 'rgb(' + red1 + ',' + green1 + ',' + blue1 + ')';
    var rgb2 = 'rgb(' + red2 + ',' + green2 + ',' + blue2 + ')';

    var webkitLinearGradient = '-webkit-linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';
    var linearGradient = 'linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';

    $('body').css('background-color', rgb1);
    $('button').css('background-color', rgb1);
    $('#quote').css('color', rgb1);
};
<|next_version|>
var getGradient = function () {
    var red1 = Math.floor(Math.random() * 256);
    var green1 = Math.floor(Math.random() * 256);
    var blue1 = Math.floor(Math.random() * 256);

    var red2 = Math.floor(Math.random() * 256);
    var green2 = Math.floor(Math.random() * 256);
    var blue2 = Math.floor(Math.random() * 256);

    var rgb1 = 'rgb(' + red1 + ',' + green1 + ',' + blue1 + ')';
    var rgb2 = 'rgb(' + red2 + ',' + green2 + ',' + blue2 + ')';

    var webkitLinearGradient = '-webkit-linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';
    var linearGradient = 'linear-gradient(to left,' + rgb1 + ',' + rgb2 + ')';

    $('body').css('background-color', rgb1);
    $('button').css('background-color', rgb1);
    $('#quote').css('color', rgb1);
    $('#author').css('color', rgb1);
};


Add Collapse Button ToggleClass Function!

--- js/collapse.js
+++ js/collapse.js
@@ -10,6 +10,7 @@

 		var defaults = {
 			switchBtnClass:'.tab-btn',
+			switchBtnToggleClass:'tab-btn-closed',
 			switchTabClass:'.tab-content',
 			animationDuration: 500
 		};
@@ -33,8 +34,10 @@
 					var curHeight = $(this).siblings(options.switchTabClass).height();
 					if(curHeight <= 0 || tabContent.is(":hidden")){
 						tabContent.css({display:"block", height:0,opacity:0}).animate({'height': orgHeight,'opacity': 1},options.animationDuration);
+						$(this).removeClass(options.switchBtnToggleClass);
 					}else{
 						tabContent.animate({'height':0,'opacity': 0},options.animationDuration);
+						$(this).addClass(options.switchBtnToggleClass);
 					}
 				});
 			});

<|original_code|>
(function (window) {
	"use strict";

	var document = window.document,
		console = window.console,
		$ = window.jQuery,
		grace = window.grace;

	$.fn.graceCollapse = function (options) {

		var defaults = {
			switchBtnClass:'.tab-btn',
			switchTabClass:'.tab-content',
			animationDuration: 500
		};

		options = $.extend({}, defaults, options);

		function initEach() {
			var $graceCollapse = $(this);

			$graceCollapse.find(options.switchBtnClass).each(function(){
				var tabContent = $(this).siblings(options.switchTabClass);
				var orgHeight;
				if(!tabContent.is(":visible")){
					tabContent.show();
					orgHeight = tabContent.height();
					tabContent.hide();
				}else{
					orgHeight = tabContent.height();
				}
				$(this).click(function(){
					var curHeight = $(this).siblings(options.switchTabClass).height();
					if(curHeight <= 0 || tabContent.is(":hidden")){
						tabContent.css({display:"block", height:0,opacity:0}).animate({'height': orgHeight,'opacity': 1},options.animationDuration);
					}else{
						tabContent.animate({'height':0,'opacity': 0},options.animationDuration);
					}
				});
			});
		}

		return this.each(initEach);
	};

})(window);

<|edits_diff|>
--- js/collapse.js
+++ js/collapse.js
@@ -10,6 +10,7 @@

 		var defaults = {
 			switchBtnClass:'.tab-btn',
+			switchBtnToggleClass:'tab-btn-closed',
 			switchTabClass:'.tab-content',
 			animationDuration: 500
 		};
@@ -33,6 +34,7 @@
 					var curHeight = $(this).siblings(options.switchTabClass).height();
 					if(curHeight <= 0 || tabContent.is(":hidden")){
 						tabContent.css({display:"block", height:0,opacity:0}).animate({'height': orgHeight,'opacity': 1},options.animationDuration);
+						$(this).removeClass(options.switchBtnToggleClass);
 					}else{
 						tabContent.animate({'height':0,'opacity': 0},options.animationDuration);
 					}
<|current_version|>
(function (window) {
	"use strict";

	var document = window.document,
		console = window.console,
		$ = window.jQuery,
		grace = window.grace;

	$.fn.graceCollapse = function (options) {

		var defaults = {
			switchBtnClass:'.tab-btn',
			switchBtnToggleClass:'tab-btn-closed',
			switchTabClass:'.tab-content',
			animationDuration: 500
		};

		options = $.extend({}, defaults, options);

		function initEach() {
			var $graceCollapse = $(this);

			$graceCollapse.find(options.switchBtnClass).each(function(){
				var tabContent = $(this).siblings(options.switchTabClass);
				var orgHeight;
				if(!tabContent.is(":visible")){
					tabContent.show();
					orgHeight = tabContent.height();
					tabContent.hide();
				}else{
					orgHeight = tabContent.height();
				}
				$(this).click(function(){
					var curHeight = $(this).siblings(options.switchTabClass).height();
					if(curHeight <= 0 || tabContent.is(":hidden")){
						tabContent.css({display:"block", height:0,opacity:0}).animate({'height': orgHeight,'opacity': 1},options.animationDuration);
						$(this).removeClass(options.switchBtnToggleClass);
					}else{
						tabContent.animate({'height':0,'opacity': 0},options.animationDuration);
					}
				});
			});
		}

		return this.each(initEach);
	};

})(window);

<|next_version|>
(function (window) {
	"use strict";

	var document = window.document,
		console = window.console,
		$ = window.jQuery,
		grace = window.grace;

	$.fn.graceCollapse = function (options) {

		var defaults = {
			switchBtnClass:'.tab-btn',
			switchBtnToggleClass:'tab-btn-closed',
			switchTabClass:'.tab-content',
			animationDuration: 500
		};

		options = $.extend({}, defaults, options);

		function initEach() {
			var $graceCollapse = $(this);

			$graceCollapse.find(options.switchBtnClass).each(function(){
				var tabContent = $(this).siblings(options.switchTabClass);
				var orgHeight;
				if(!tabContent.is(":visible")){
					tabContent.show();
					orgHeight = tabContent.height();
					tabContent.hide();
				}else{
					orgHeight = tabContent.height();
				}
				$(this).click(function(){
					var curHeight = $(this).siblings(options.switchTabClass).height();
					if(curHeight <= 0 || tabContent.is(":hidden")){
						tabContent.css({display:"block", height:0,opacity:0}).animate({'height': orgHeight,'opacity': 1},options.animationDuration);
						$(this).removeClass(options.switchBtnToggleClass);
					}else{
						tabContent.animate({'height':0,'opacity': 0},options.animationDuration);
						$(this).addClass(options.switchBtnToggleClass);
					}
				});
			});
		}

		return this.each(initEach);
	};

})(window);


Add express-session and create a new session

--- config/expressConfig.js
+++ config/expressConfig.js
@@ -7,11 +7,13 @@
 var logger = require('morgan');
 var cookieParser = require('cookie-parser');
 var bodyParser = require('body-parser');
+var session = require('express-session');

 exports.setup = function(app, express) {
 	app.use(logger('dev'));
 	app.use(bodyParser.json());
 	app.use(bodyParser.urlencoded({ extended: false }));
 	app.use(cookieParser());
+  app.use(session({ secret: 'mylittlesecret' , resave: false, saveUninitialized: false }));
 	app.use(express.static(path.join(__dirname, 'public')));
 }

<|original_code|>
/*
 * This file exports the configuration Express.js back to the application
 * so that it can be used in other parts of the product.
 */

var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

exports.setup = function(app, express) {
	app.use(logger('dev'));
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({ extended: false }));
	app.use(cookieParser());
	app.use(express.static(path.join(__dirname, 'public')));
}
<|edits_diff|>
--- config/expressConfig.js
+++ config/expressConfig.js
@@ -7,6 +7,7 @@
 var logger = require('morgan');
 var cookieParser = require('cookie-parser');
 var bodyParser = require('body-parser');
+var session = require('express-session');

 exports.setup = function(app, express) {
 	app.use(logger('dev'));
<|current_version|>
/*
 * This file exports the configuration Express.js back to the application
 * so that it can be used in other parts of the product.
 */

var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');

exports.setup = function(app, express) {
	app.use(logger('dev'));
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({ extended: false }));
	app.use(cookieParser());
	app.use(express.static(path.join(__dirname, 'public')));
}
<|next_version|>
/*
 * This file exports the configuration Express.js back to the application
 * so that it can be used in other parts of the product.
 */

var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');

exports.setup = function(app, express) {
	app.use(logger('dev'));
	app.use(bodyParser.json());
	app.use(bodyParser.urlencoded({ extended: false }));
	app.use(cookieParser());
  app.use(session({ secret: 'mylittlesecret' , resave: false, saveUninitialized: false }));
	app.use(express.static(path.join(__dirname, 'public')));
}


Add second argument checking to prevent unexpected behavior.

--- lib/path.js
+++ lib/path.js
@@ -28,12 +28,18 @@
 }

 path.fileNameWithPostfix = function (filePath, postfix) {
+  if (typeof postfix !== 'string') {
+    throw TypeError(`second argument 'postfix' must be string, got ${typeof postfix}`)
+  }
   var ext = path.extname(filePath)
   var fileNameWithoutExt = path.basename(filePath, ext)
   return path.join(path.dirname(filePath), fileNameWithoutExt + postfix + ext)
 }

 path.fileNameWithPrefix = function (filePath, prefix) {
+  if (typeof prefix !== 'string') {
+    throw TypeError(`second argument 'prefix' must be string, got ${typeof prefix}`)
+  }
   var ext = path.extname(filePath)
   var fileNameWithoutExt = path.basename(filePath, ext)
   return path.join(path.dirname(filePath), prefix + fileNameWithoutExt + ext)

<|original_code|>
var path = require('path')

var p = {}

Object.keys(path).forEach(function (key) {
  p[key] = path[key]
})

path = p

path.replaceExt = require('replace-ext')

path.normalizeTrim = function (str) {
  var escapeRegexp = require('escape-string-regexp')
  return path.normalize(str).replace(new RegExp(escapeRegexp(path.sep) + '$'), '')
}

path.base = function (str, includeExt) {
  if (includeExt) {
    return path.basename(str)
  } else {
    return path.basename(str, path.extname(str))
  }
}

path.removeExt = function (str) {
  return str.slice(0, -path.extname(str).length)
}

path.fileNameWithPostfix = function (filePath, postfix) {
  var ext = path.extname(filePath)
  var fileNameWithoutExt = path.basename(filePath, ext)
  return path.join(path.dirname(filePath), fileNameWithoutExt + postfix + ext)
}

path.fileNameWithPrefix = function (filePath, prefix) {
  var ext = path.extname(filePath)
  var fileNameWithoutExt = path.basename(filePath, ext)
  return path.join(path.dirname(filePath), prefix + fileNameWithoutExt + ext)
}

module.exports = path

<|edits_diff|>
--- lib/path.js
+++ lib/path.js
@@ -28,6 +28,9 @@
 }

 path.fileNameWithPostfix = function (filePath, postfix) {
+  if (typeof postfix !== 'string') {
+    throw TypeError(`second argument 'postfix' must be string, got ${typeof postfix}`)
+  }
   var ext = path.extname(filePath)
   var fileNameWithoutExt = path.basename(filePath, ext)
   return path.join(path.dirname(filePath), fileNameWithoutExt + postfix + ext)
<|current_version|>
var path = require('path')

var p = {}

Object.keys(path).forEach(function (key) {
  p[key] = path[key]
})

path = p

path.replaceExt = require('replace-ext')

path.normalizeTrim = function (str) {
  var escapeRegexp = require('escape-string-regexp')
  return path.normalize(str).replace(new RegExp(escapeRegexp(path.sep) + '$'), '')
}

path.base = function (str, includeExt) {
  if (includeExt) {
    return path.basename(str)
  } else {
    return path.basename(str, path.extname(str))
  }
}

path.removeExt = function (str) {
  return str.slice(0, -path.extname(str).length)
}

path.fileNameWithPostfix = function (filePath, postfix) {
  if (typeof postfix !== 'string') {
    throw TypeError(`second argument 'postfix' must be string, got ${typeof postfix}`)
  }
  var ext = path.extname(filePath)
  var fileNameWithoutExt = path.basename(filePath, ext)
  return path.join(path.dirname(filePath), fileNameWithoutExt + postfix + ext)
}

path.fileNameWithPrefix = function (filePath, prefix) {
  var ext = path.extname(filePath)
  var fileNameWithoutExt = path.basename(filePath, ext)
  return path.join(path.dirname(filePath), prefix + fileNameWithoutExt + ext)
}

module.exports = path

<|next_version|>
var path = require('path')

var p = {}

Object.keys(path).forEach(function (key) {
  p[key] = path[key]
})

path = p

path.replaceExt = require('replace-ext')

path.normalizeTrim = function (str) {
  var escapeRegexp = require('escape-string-regexp')
  return path.normalize(str).replace(new RegExp(escapeRegexp(path.sep) + '$'), '')
}

path.base = function (str, includeExt) {
  if (includeExt) {
    return path.basename(str)
  } else {
    return path.basename(str, path.extname(str))
  }
}

path.removeExt = function (str) {
  return str.slice(0, -path.extname(str).length)
}

path.fileNameWithPostfix = function (filePath, postfix) {
  if (typeof postfix !== 'string') {
    throw TypeError(`second argument 'postfix' must be string, got ${typeof postfix}`)
  }
  var ext = path.extname(filePath)
  var fileNameWithoutExt = path.basename(filePath, ext)
  return path.join(path.dirname(filePath), fileNameWithoutExt + postfix + ext)
}

path.fileNameWithPrefix = function (filePath, prefix) {
  if (typeof prefix !== 'string') {
    throw TypeError(`second argument 'prefix' must be string, got ${typeof prefix}`)
  }
  var ext = path.extname(filePath)
  var fileNameWithoutExt = path.basename(filePath, ext)
  return path.join(path.dirname(filePath), prefix + fileNameWithoutExt + ext)
}

module.exports = path


Add compile step to tests before execution

--- gulpfile.js
+++ gulpfile.js
@@ -24,6 +24,12 @@
 });

 gulp.task('test', function () {
+    var browserified = transform(function (filename) {
+        var b = browserify({ entries: filename, debug: true });
+        return b.bundle();
+    });
+
     return gulp.src('./spec/**/*.js')
+        .pipe(browserified)
         .pipe(jasmine());
 });

<|original_code|>
'use strict';

var gulp = require('gulp'),
    browserify = require('browserify'),
    transform = require('vinyl-transform'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps'),
    jasmine = require('gulp-jasmine');

gulp.task('default', ['javascript']);

gulp.task('javascript', function () {
    var browserified = transform(function (filename) {
        var b = browserify({ entries: filename, debug: true });
        return b.bundle();
    });

    return gulp.src('./src/js/bowler.js')
        .pipe(browserified)
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(uglify())
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./dist/js'));
});

gulp.task('test', function () {
    return gulp.src('./spec/**/*.js')
        .pipe(jasmine());
});

<|edits_diff|>
--- gulpfile.js
+++ gulpfile.js
@@ -24,6 +24,11 @@
 });

 gulp.task('test', function () {
+    var browserified = transform(function (filename) {
+        var b = browserify({ entries: filename, debug: true });
+        return b.bundle();
+    });
+
     return gulp.src('./spec/**/*.js')
         .pipe(jasmine());
 });
<|current_version|>
'use strict';

var gulp = require('gulp'),
    browserify = require('browserify'),
    transform = require('vinyl-transform'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps'),
    jasmine = require('gulp-jasmine');

gulp.task('default', ['javascript']);

gulp.task('javascript', function () {
    var browserified = transform(function (filename) {
        var b = browserify({ entries: filename, debug: true });
        return b.bundle();
    });

    return gulp.src('./src/js/bowler.js')
        .pipe(browserified)
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(uglify())
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./dist/js'));
});

gulp.task('test', function () {
    var browserified = transform(function (filename) {
        var b = browserify({ entries: filename, debug: true });
        return b.bundle();
    });

    return gulp.src('./spec/**/*.js')
        .pipe(jasmine());
});

<|next_version|>
'use strict';

var gulp = require('gulp'),
    browserify = require('browserify'),
    transform = require('vinyl-transform'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps'),
    jasmine = require('gulp-jasmine');

gulp.task('default', ['javascript']);

gulp.task('javascript', function () {
    var browserified = transform(function (filename) {
        var b = browserify({ entries: filename, debug: true });
        return b.bundle();
    });

    return gulp.src('./src/js/bowler.js')
        .pipe(browserified)
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(uglify())
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./dist/js'));
});

gulp.task('test', function () {
    var browserified = transform(function (filename) {
        var b = browserify({ entries: filename, debug: true });
        return b.bundle();
    });

    return gulp.src('./spec/**/*.js')
        .pipe(browserified)
        .pipe(jasmine());
});


Enable ESLint rules that are already passing

* no-multi-spaces: error on multiple spaces in a row
* no-unused-expressions: error on unused expressions, probably an error
  or a typo

--- .eslintrc.js
+++ .eslintrc.js
@@ -15,10 +15,15 @@
     'react',
   ],
   rules: {
+    // Rules included in ESLint
     'comma-dangle': [1, 'always-multiline'],
     'no-console': 0,
+    'no-multi-spaces': 1,
+    'no-unused-expressions': 1,
     'no-var': 1,
     'prefer-const': 1,
+
+    // React rules from eslint-plugin-react
     'react/jsx-uses-vars': 1,
   },
 };

<|original_code|>
module.exports = {
  env: {
    browser: true,
  },
  extends: 'eslint:recommended',
  parser: 'babel-eslint',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 2015,
    sourceType: 'module',
  },
  plugins: [
    'react',
  ],
  rules: {
    'comma-dangle': [1, 'always-multiline'],
    'no-console': 0,
    'no-var': 1,
    'prefer-const': 1,
    'react/jsx-uses-vars': 1,
  },
};

<|edits_diff|>
--- .eslintrc.js
+++ .eslintrc.js
@@ -15,8 +15,11 @@
     'react',
   ],
   rules: {
+    // Rules included in ESLint
     'comma-dangle': [1, 'always-multiline'],
     'no-console': 0,
+    'no-multi-spaces': 1,
+    'no-unused-expressions': 1,
     'no-var': 1,
     'prefer-const': 1,
     'react/jsx-uses-vars': 1,
<|current_version|>
module.exports = {
  env: {
    browser: true,
  },
  extends: 'eslint:recommended',
  parser: 'babel-eslint',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 2015,
    sourceType: 'module',
  },
  plugins: [
    'react',
  ],
  rules: {
    // Rules included in ESLint
    'comma-dangle': [1, 'always-multiline'],
    'no-console': 0,
    'no-multi-spaces': 1,
    'no-unused-expressions': 1,
    'no-var': 1,
    'prefer-const': 1,
    'react/jsx-uses-vars': 1,
  },
};

<|next_version|>
module.exports = {
  env: {
    browser: true,
  },
  extends: 'eslint:recommended',
  parser: 'babel-eslint',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 2015,
    sourceType: 'module',
  },
  plugins: [
    'react',
  ],
  rules: {
    // Rules included in ESLint
    'comma-dangle': [1, 'always-multiline'],
    'no-console': 0,
    'no-multi-spaces': 1,
    'no-unused-expressions': 1,
    'no-var': 1,
    'prefer-const': 1,

    // React rules from eslint-plugin-react
    'react/jsx-uses-vars': 1,
  },
};


Add gateway token header for health check

--- server/data/healthcheck.js
+++ server/data/healthcheck.js
@@ -4,6 +4,8 @@

 const url = require('url');
 const superagent = require('superagent');
+
+const generateApiGatewayToken = require('../authentication/apiGateway');

 module.exports = {
     nomisApiCheck,
@@ -19,8 +21,11 @@
 function nomisApiCheck() {
     return new Promise((resolve, reject) => {

+        const gwToken = process.env.NODE_ENV === 'test' ? 'dummy' : `Bearer ${generateApiGatewayToken()}`;
+
         superagent
             .get(url.resolve(`${config.nomis.apiUrl}`, '/api/info/health'))
+            .set('Authorization', gwToken)
             .timeout({
                 response: 2000,
                 deadline: 2500

<|original_code|>
const config = require('../config.js');
const {getCollection} = require('./dataAccess/dbMethods');
const logger = require('../../log.js');

const url = require('url');
const superagent = require('superagent');

module.exports = {
    nomisApiCheck,
    dbCheck
};

function dbCheck() {
    return new Promise((resolve, reject) => {
        getCollection('SELECT 1 AS [ok]', null, resolve, reject);
    });
}

function nomisApiCheck() {
    return new Promise((resolve, reject) => {

        superagent
            .get(url.resolve(`${config.nomis.apiUrl}`, '/api/info/health'))
            .timeout({
                response: 2000,
                deadline: 2500
            })
            .end((error, result) => {
                try {
                    if (error) {
                        logger.error(error, 'Error calling Nomis API');
                        return reject(error.status);
                    }

                    if (result.status === 200) {
                        return resolve('OK');
                    }

                    return reject(result.status);
                } catch (exception) {
                    logger.error(exception, 'Exception calling Nomis API');
                    return reject(exception);
                }
            });
    });
}

<|edits_diff|>
--- server/data/healthcheck.js
+++ server/data/healthcheck.js
@@ -4,6 +4,8 @@

 const url = require('url');
 const superagent = require('superagent');
+
+const generateApiGatewayToken = require('../authentication/apiGateway');

 module.exports = {
     nomisApiCheck,
@@ -18,6 +20,8 @@

 function nomisApiCheck() {
     return new Promise((resolve, reject) => {
+
+        const gwToken = process.env.NODE_ENV === 'test' ? 'dummy' : `Bearer ${generateApiGatewayToken()}`;

         superagent
             .get(url.resolve(`${config.nomis.apiUrl}`, '/api/info/health'))
<|current_version|>
const config = require('../config.js');
const {getCollection} = require('./dataAccess/dbMethods');
const logger = require('../../log.js');

const url = require('url');
const superagent = require('superagent');

const generateApiGatewayToken = require('../authentication/apiGateway');

module.exports = {
    nomisApiCheck,
    dbCheck
};

function dbCheck() {
    return new Promise((resolve, reject) => {
        getCollection('SELECT 1 AS [ok]', null, resolve, reject);
    });
}

function nomisApiCheck() {
    return new Promise((resolve, reject) => {

        const gwToken = process.env.NODE_ENV === 'test' ? 'dummy' : `Bearer ${generateApiGatewayToken()}`;

        superagent
            .get(url.resolve(`${config.nomis.apiUrl}`, '/api/info/health'))
            .timeout({
                response: 2000,
                deadline: 2500
            })
            .end((error, result) => {
                try {
                    if (error) {
                        logger.error(error, 'Error calling Nomis API');
                        return reject(error.status);
                    }

                    if (result.status === 200) {
                        return resolve('OK');
                    }

                    return reject(result.status);
                } catch (exception) {
                    logger.error(exception, 'Exception calling Nomis API');
                    return reject(exception);
                }
            });
    });
}

<|next_version|>
const config = require('../config.js');
const {getCollection} = require('./dataAccess/dbMethods');
const logger = require('../../log.js');

const url = require('url');
const superagent = require('superagent');

const generateApiGatewayToken = require('../authentication/apiGateway');

module.exports = {
    nomisApiCheck,
    dbCheck
};

function dbCheck() {
    return new Promise((resolve, reject) => {
        getCollection('SELECT 1 AS [ok]', null, resolve, reject);
    });
}

function nomisApiCheck() {
    return new Promise((resolve, reject) => {

        const gwToken = process.env.NODE_ENV === 'test' ? 'dummy' : `Bearer ${generateApiGatewayToken()}`;

        superagent
            .get(url.resolve(`${config.nomis.apiUrl}`, '/api/info/health'))
            .set('Authorization', gwToken)
            .timeout({
                response: 2000,
                deadline: 2500
            })
            .end((error, result) => {
                try {
                    if (error) {
                        logger.error(error, 'Error calling Nomis API');
                        return reject(error.status);
                    }

                    if (result.status === 200) {
                        return resolve('OK');
                    }

                    return reject(result.status);
                } catch (exception) {
                    logger.error(exception, 'Exception calling Nomis API');
                    return reject(exception);
                }
            });
    });
}


Add route for login page

Add route for login page

--- client/components/App.js
+++ client/components/App.js
@@ -3,6 +3,7 @@
 import { hot } from 'react-hot-loader';

 import SignUpPage from './SignUp/SignUpPage';
+import LoginPage from './Login/LoginPage';

 class App extends Component {
   render() {
@@ -10,6 +11,7 @@
             <Router history = { this.props.history }>
                 <Switch>
                     <Route path = '/signup' component = { SignUpPage } />
+                    <Route path = '/login' component = { LoginPage } />
                 </Switch>
             </Router>
     );

<|original_code|>
import React, { Component } from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { hot } from 'react-hot-loader';

import SignUpPage from './SignUp/SignUpPage';

class App extends Component {
  render() {
    return (
            <Router history = { this.props.history }>
                <Switch>
                    <Route path = '/signup' component = { SignUpPage } />
                </Switch>
            </Router>
    );
  }
}

export default hot(module)(App);

<|edits_diff|>
--- client/components/App.js
+++ client/components/App.js
@@ -3,6 +3,7 @@
 import { hot } from 'react-hot-loader';

 import SignUpPage from './SignUp/SignUpPage';
+import LoginPage from './Login/LoginPage';

 class App extends Component {
   render() {
<|current_version|>
import React, { Component } from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { hot } from 'react-hot-loader';

import SignUpPage from './SignUp/SignUpPage';
import LoginPage from './Login/LoginPage';

class App extends Component {
  render() {
    return (
            <Router history = { this.props.history }>
                <Switch>
                    <Route path = '/signup' component = { SignUpPage } />
                </Switch>
            </Router>
    );
  }
}

export default hot(module)(App);

<|next_version|>
import React, { Component } from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { hot } from 'react-hot-loader';

import SignUpPage from './SignUp/SignUpPage';
import LoginPage from './Login/LoginPage';

class App extends Component {
  render() {
    return (
            <Router history = { this.props.history }>
                <Switch>
                    <Route path = '/signup' component = { SignUpPage } />
                    <Route path = '/login' component = { LoginPage } />
                </Switch>
            </Router>
    );
  }
}

export default hot(module)(App);


Add a ctx.save and a ctx.restore

Add a ctx.save and a ctx.restore

john

--- line.js
+++ line.js
@@ -7,6 +7,7 @@
 	kind: enyo.canvas.Shape,
 	//* @protected
 	renderSelf: function(ctx) {
+		ctx.save();
 		ctx.beginPath();
 		ctx.strokeStyle = this.bounds.Style;
 		ctx.lineWidth = this.bounds.width;
@@ -14,6 +15,7 @@
 		ctx.moveTo(this.bounds.start_x, this.bounds.start_y);
 		ctx.lineTo(this.bounds.finish_x, this.bounds.finish_y);
 		ctx.stroke();
+		ctx.restore();
 	}

 });

<|original_code|>
/**
	_enyo.canvas.line_ is a canvas control that draws a line fitting
	the parameters specified in	the _bounds_ property.
*/
enyo.kind({
	name: "enyo.canvas.line",
	kind: enyo.canvas.Shape,
	//* @protected
	renderSelf: function(ctx) {
		ctx.beginPath();
		ctx.strokeStyle = this.bounds.Style;
		ctx.lineWidth = this.bounds.width;
		ctx.lineCap = this.bounds.cap;
		ctx.moveTo(this.bounds.start_x, this.bounds.start_y);
		ctx.lineTo(this.bounds.finish_x, this.bounds.finish_y);
		ctx.stroke();
	}

});

<|edits_diff|>
--- line.js
+++ line.js
@@ -7,6 +7,7 @@
 	kind: enyo.canvas.Shape,
 	//* @protected
 	renderSelf: function(ctx) {
+		ctx.save();
 		ctx.beginPath();
 		ctx.strokeStyle = this.bounds.Style;
 		ctx.lineWidth = this.bounds.width;
<|current_version|>
/**
	_enyo.canvas.line_ is a canvas control that draws a line fitting
	the parameters specified in	the _bounds_ property.
*/
enyo.kind({
	name: "enyo.canvas.line",
	kind: enyo.canvas.Shape,
	//* @protected
	renderSelf: function(ctx) {
		ctx.save();
		ctx.beginPath();
		ctx.strokeStyle = this.bounds.Style;
		ctx.lineWidth = this.bounds.width;
		ctx.lineCap = this.bounds.cap;
		ctx.moveTo(this.bounds.start_x, this.bounds.start_y);
		ctx.lineTo(this.bounds.finish_x, this.bounds.finish_y);
		ctx.stroke();
	}

});

<|next_version|>
/**
	_enyo.canvas.line_ is a canvas control that draws a line fitting
	the parameters specified in	the _bounds_ property.
*/
enyo.kind({
	name: "enyo.canvas.line",
	kind: enyo.canvas.Shape,
	//* @protected
	renderSelf: function(ctx) {
		ctx.save();
		ctx.beginPath();
		ctx.strokeStyle = this.bounds.Style;
		ctx.lineWidth = this.bounds.width;
		ctx.lineCap = this.bounds.cap;
		ctx.moveTo(this.bounds.start_x, this.bounds.start_y);
		ctx.lineTo(this.bounds.finish_x, this.bounds.finish_y);
		ctx.stroke();
		ctx.restore();
	}

});


Create chain agent in Tracker

Create chain agent in Tracker

--- src/tracker/tracker.js
+++ src/tracker/tracker.js
@@ -7,6 +7,7 @@

 // Imports
 const Cache = require('../cache/cache')
+const ChainAgent = require('../chain/etherscan')

 /**
  * Private members store.
@@ -30,6 +31,7 @@
       address: new Cache(),
       tx: new Cache()
     }
+    priv.chain = new ChainAgent(priv.cache)
   }
 }

<|original_code|>
/**
 * @file Ethereum taint tracker.
 * @module tracker/tracker
 */

'use strict'

// Imports
const Cache = require('../cache/cache')

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * Ethereum taint tracker.
 * @static
 */
class Tracker {
  /**
   * No parameters.
   */
  constructor () {
    const priv = {}
    privs.set(this, priv)
    priv.cache = {
      block: new Cache(),
      address: new Cache(),
      tx: new Cache()
    }
  }
}

// Expose
module.exports = Tracker

<|edits_diff|>
--- src/tracker/tracker.js
+++ src/tracker/tracker.js
@@ -7,6 +7,7 @@

 // Imports
 const Cache = require('../cache/cache')
+const ChainAgent = require('../chain/etherscan')

 /**
  * Private members store.
<|current_version|>
/**
 * @file Ethereum taint tracker.
 * @module tracker/tracker
 */

'use strict'

// Imports
const Cache = require('../cache/cache')
const ChainAgent = require('../chain/etherscan')

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * Ethereum taint tracker.
 * @static
 */
class Tracker {
  /**
   * No parameters.
   */
  constructor () {
    const priv = {}
    privs.set(this, priv)
    priv.cache = {
      block: new Cache(),
      address: new Cache(),
      tx: new Cache()
    }
  }
}

// Expose
module.exports = Tracker

<|next_version|>
/**
 * @file Ethereum taint tracker.
 * @module tracker/tracker
 */

'use strict'

// Imports
const Cache = require('../cache/cache')
const ChainAgent = require('../chain/etherscan')

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * Ethereum taint tracker.
 * @static
 */
class Tracker {
  /**
   * No parameters.
   */
  constructor () {
    const priv = {}
    privs.set(this, priv)
    priv.cache = {
      block: new Cache(),
      address: new Cache(),
      tx: new Cache()
    }
    priv.chain = new ChainAgent(priv.cache)
  }
}

// Expose
module.exports = Tracker


Add new property to factory

Add new property to factory

--- ui/mirage/factories/deployment-task-group-summary.js
+++ ui/mirage/factories/deployment-task-group-summary.js
@@ -1,10 +1,14 @@
 import { Factory, faker } from 'ember-cli-mirage';
+
+const REF_TIME = new Date();

 export default Factory.extend({
   name: '',

   autoRevert: () => Math.random() > 0.5,
   promoted: () => Math.random() > 0.5,
+
+  requireProgressBy: () => faker.date.past(0.5 / 365, REF_TIME),

   desiredTotal: faker.random.number({ min: 1, max: 10 }),

<|original_code|>
import { Factory, faker } from 'ember-cli-mirage';

export default Factory.extend({
  name: '',

  autoRevert: () => Math.random() > 0.5,
  promoted: () => Math.random() > 0.5,

  desiredTotal: faker.random.number({ min: 1, max: 10 }),

  desiredCanaries() {
    return faker.random.number(Math.floor(this.desiredTotal / 2));
  },

  // PlacedCanaries is an array of allocation IDs. Since the IDs aren't currently
  // used for associating allocations, any random value will do for now.
  placedCanaries() {
    return Array(faker.random.number(this.desiredCanaries))
      .fill(null)
      .map(() => faker.random.uuid());
  },

  placedAllocs() {
    return faker.random.number(this.desiredTotal);
  },

  healthyAllocs() {
    return faker.random.number(this.placedAllocs);
  },

  unhealthyAllocs() {
    return this.placedAllocs - this.healthyAllocs;
  },
});

<|edits_diff|>
--- ui/mirage/factories/deployment-task-group-summary.js
+++ ui/mirage/factories/deployment-task-group-summary.js
@@ -1,4 +1,6 @@
 import { Factory, faker } from 'ember-cli-mirage';
+
+const REF_TIME = new Date();

 export default Factory.extend({
   name: '',
<|current_version|>
import { Factory, faker } from 'ember-cli-mirage';

const REF_TIME = new Date();

export default Factory.extend({
  name: '',

  autoRevert: () => Math.random() > 0.5,
  promoted: () => Math.random() > 0.5,

  desiredTotal: faker.random.number({ min: 1, max: 10 }),

  desiredCanaries() {
    return faker.random.number(Math.floor(this.desiredTotal / 2));
  },

  // PlacedCanaries is an array of allocation IDs. Since the IDs aren't currently
  // used for associating allocations, any random value will do for now.
  placedCanaries() {
    return Array(faker.random.number(this.desiredCanaries))
      .fill(null)
      .map(() => faker.random.uuid());
  },

  placedAllocs() {
    return faker.random.number(this.desiredTotal);
  },

  healthyAllocs() {
    return faker.random.number(this.placedAllocs);
  },

  unhealthyAllocs() {
    return this.placedAllocs - this.healthyAllocs;
  },
});

<|next_version|>
import { Factory, faker } from 'ember-cli-mirage';

const REF_TIME = new Date();

export default Factory.extend({
  name: '',

  autoRevert: () => Math.random() > 0.5,
  promoted: () => Math.random() > 0.5,

  requireProgressBy: () => faker.date.past(0.5 / 365, REF_TIME),

  desiredTotal: faker.random.number({ min: 1, max: 10 }),

  desiredCanaries() {
    return faker.random.number(Math.floor(this.desiredTotal / 2));
  },

  // PlacedCanaries is an array of allocation IDs. Since the IDs aren't currently
  // used for associating allocations, any random value will do for now.
  placedCanaries() {
    return Array(faker.random.number(this.desiredCanaries))
      .fill(null)
      .map(() => faker.random.uuid());
  },

  placedAllocs() {
    return faker.random.number(this.desiredTotal);
  },

  healthyAllocs() {
    return faker.random.number(this.placedAllocs);
  },

  unhealthyAllocs() {
    return this.placedAllocs - this.healthyAllocs;
  },
});