Add the simplest of simple `alert` error handling

--- js/views/save_item_mixin.js
+++ js/views/save_item_mixin.js
@@ -20,6 +20,9 @@
       this.defaultSave();
     }
   },
+  handleError: function (errorObj) {
+    alert(window.JSON.stringify(errorObj));
+  },
   defaultSave: function () {
     var that = this;

@@ -28,6 +31,9 @@
       .always(this.toggleLoaders.bind(this, false))
       .done(function () {
         window.location.href = that.model.url().replace('\/api\/', '/');
+      })
+      .fail(function (jqXHR, textStatus, error) {
+        that.handleError(jqXHR.responseJSON);
       });
   }
 }

<|original_code|>
"use strict";

var saveRow = require('../templates/save_row.html')();

module.exports = {
  events: {
    'click .save-item': '_handleSave'
  },
  render: function () {
    this.$el.append(saveRow)
  },
  toggleLoaders: function (state) {
    this.$('.save-item').prop('disabled', state);
    this.$('.loader').toggle(state);
  },
  _handleSave: function () {
    if (this.saveItem) {
      this.saveItem();
    } else {
      this.defaultSave();
    }
  },
  defaultSave: function () {
    var that = this;

    this.toggleLoaders(true);
    this.model.save()
      .always(this.toggleLoaders.bind(this, false))
      .done(function () {
        window.location.href = that.model.url().replace('\/api\/', '/');
      });
  }
}

<|edits_diff|>
--- js/views/save_item_mixin.js
+++ js/views/save_item_mixin.js
@@ -20,6 +20,9 @@
       this.defaultSave();
     }
   },
+  handleError: function (errorObj) {
+    alert(window.JSON.stringify(errorObj));
+  },
   defaultSave: function () {
     var that = this;

<|current_version|>
"use strict";

var saveRow = require('../templates/save_row.html')();

module.exports = {
  events: {
    'click .save-item': '_handleSave'
  },
  render: function () {
    this.$el.append(saveRow)
  },
  toggleLoaders: function (state) {
    this.$('.save-item').prop('disabled', state);
    this.$('.loader').toggle(state);
  },
  _handleSave: function () {
    if (this.saveItem) {
      this.saveItem();
    } else {
      this.defaultSave();
    }
  },
  handleError: function (errorObj) {
    alert(window.JSON.stringify(errorObj));
  },
  defaultSave: function () {
    var that = this;

    this.toggleLoaders(true);
    this.model.save()
      .always(this.toggleLoaders.bind(this, false))
      .done(function () {
        window.location.href = that.model.url().replace('\/api\/', '/');
      });
  }
}

<|next_version|>
"use strict";

var saveRow = require('../templates/save_row.html')();

module.exports = {
  events: {
    'click .save-item': '_handleSave'
  },
  render: function () {
    this.$el.append(saveRow)
  },
  toggleLoaders: function (state) {
    this.$('.save-item').prop('disabled', state);
    this.$('.loader').toggle(state);
  },
  _handleSave: function () {
    if (this.saveItem) {
      this.saveItem();
    } else {
      this.defaultSave();
    }
  },
  handleError: function (errorObj) {
    alert(window.JSON.stringify(errorObj));
  },
  defaultSave: function () {
    var that = this;

    this.toggleLoaders(true);
    this.model.save()
      .always(this.toggleLoaders.bind(this, false))
      .done(function () {
        window.location.href = that.model.url().replace('\/api\/', '/');
      })
      .fail(function (jqXHR, textStatus, error) {
        that.handleError(jqXHR.responseJSON);
      });
  }
}


Send root page for all non-static files (let Backbone handle routing)

--- server.js
+++ server.js
@@ -1,8 +1,13 @@
 var connect = require('connect'),
+  fs = require('fs'),
   port = process.env.PORT || 3000;

 connect()
   .use(connect.static('app'))
+  .use(function(req, res) {
+    var stream = fs.createReadStream(__dirname + '/app/index.html');
+    stream.pipe(res);
+  })
   .listen(port);

 console.log('Application listening on port ' + port);

<|original_code|>
var connect = require('connect'),
  port = process.env.PORT || 3000;

connect()
  .use(connect.static('app'))
  .listen(port);

console.log('Application listening on port ' + port);

<|edits_diff|>
--- server.js
+++ server.js
@@ -1,4 +1,5 @@
 var connect = require('connect'),
+  fs = require('fs'),
   port = process.env.PORT || 3000;

 connect()
<|current_version|>
var connect = require('connect'),
  fs = require('fs'),
  port = process.env.PORT || 3000;

connect()
  .use(connect.static('app'))
  .listen(port);

console.log('Application listening on port ' + port);

<|next_version|>
var connect = require('connect'),
  fs = require('fs'),
  port = process.env.PORT || 3000;

connect()
  .use(connect.static('app'))
  .use(function(req, res) {
    var stream = fs.createReadStream(__dirname + '/app/index.html');
    stream.pipe(res);
  })
  .listen(port);

console.log('Application listening on port ' + port);


Fix min hp and mp

Fix min hp and mp

--- src/game/model/status.js
+++ src/game/model/status.js
@@ -1,7 +1,9 @@
 class Status {
     constructor(currentHp, maxHp, currentMp, maxMp) {
         currentHp = Math.min(currentHp, maxHp);
+        currentHp = Math.max(currentHp, 0);
         currentMp = Math.min(currentMp, maxMp);
+        currentMp = Math.max(currentMp, 0);
         this.currentHp = isNaN(currentHp) ? 0 : currentHp;
         this.currentMp = isNaN(currentMp) ? 0 : currentMp;
         this.maxHp = isNaN(maxHp) ? Infinity : maxHp;

<|original_code|>
class Status {
    constructor(currentHp, maxHp, currentMp, maxMp) {
        currentHp = Math.min(currentHp, maxHp);
        currentMp = Math.min(currentMp, maxMp);
        this.currentHp = isNaN(currentHp) ? 0 : currentHp;
        this.currentMp = isNaN(currentMp) ? 0 : currentMp;
        this.maxHp = isNaN(maxHp) ? Infinity : maxHp;
        this.maxMp = isNaN(maxMp) ? Infinity : maxMp;
        Object.freeze(this);
    };

    changeHp(nextHp) {
        return new Status(nextHp, this.maxHp, this.currentMp, this.maxMp);
    }

    changeMp(nextMp) {
        return new Status(this.currentHp, this.maxHp, nextMp, this.maxMp);
    }

    canCast(spell) {
        return spell.requiredMp <= this.currentMp;
    };

    isDead() {
        return this.currentHp <= this.minHp;
    };
}

module.exports = Status;

<|edits_diff|>
--- src/game/model/status.js
+++ src/game/model/status.js
@@ -1,6 +1,7 @@
 class Status {
     constructor(currentHp, maxHp, currentMp, maxMp) {
         currentHp = Math.min(currentHp, maxHp);
+        currentHp = Math.max(currentHp, 0);
         currentMp = Math.min(currentMp, maxMp);
         this.currentHp = isNaN(currentHp) ? 0 : currentHp;
         this.currentMp = isNaN(currentMp) ? 0 : currentMp;
<|current_version|>
class Status {
    constructor(currentHp, maxHp, currentMp, maxMp) {
        currentHp = Math.min(currentHp, maxHp);
        currentHp = Math.max(currentHp, 0);
        currentMp = Math.min(currentMp, maxMp);
        this.currentHp = isNaN(currentHp) ? 0 : currentHp;
        this.currentMp = isNaN(currentMp) ? 0 : currentMp;
        this.maxHp = isNaN(maxHp) ? Infinity : maxHp;
        this.maxMp = isNaN(maxMp) ? Infinity : maxMp;
        Object.freeze(this);
    };

    changeHp(nextHp) {
        return new Status(nextHp, this.maxHp, this.currentMp, this.maxMp);
    }

    changeMp(nextMp) {
        return new Status(this.currentHp, this.maxHp, nextMp, this.maxMp);
    }

    canCast(spell) {
        return spell.requiredMp <= this.currentMp;
    };

    isDead() {
        return this.currentHp <= this.minHp;
    };
}

module.exports = Status;

<|next_version|>
class Status {
    constructor(currentHp, maxHp, currentMp, maxMp) {
        currentHp = Math.min(currentHp, maxHp);
        currentHp = Math.max(currentHp, 0);
        currentMp = Math.min(currentMp, maxMp);
        currentMp = Math.max(currentMp, 0);
        this.currentHp = isNaN(currentHp) ? 0 : currentHp;
        this.currentMp = isNaN(currentMp) ? 0 : currentMp;
        this.maxHp = isNaN(maxHp) ? Infinity : maxHp;
        this.maxMp = isNaN(maxMp) ? Infinity : maxMp;
        Object.freeze(this);
    };

    changeHp(nextHp) {
        return new Status(nextHp, this.maxHp, this.currentMp, this.maxMp);
    }

    changeMp(nextMp) {
        return new Status(this.currentHp, this.maxHp, nextMp, this.maxMp);
    }

    canCast(spell) {
        return spell.requiredMp <= this.currentMp;
    };

    isDead() {
        return this.currentHp <= this.minHp;
    };
}

module.exports = Status;


Use VueMoment as Vue plugin

Use VueMoment as Vue plugin

--- ui/main.js
+++ ui/main.js
@@ -1,5 +1,6 @@
 import Vue from "vue";
 import VueRouter from "vue-router";
+import VueMoment from 'vue-moment';

 import {createProvider} from './apollo';
 import {store} from "./store";
@@ -14,6 +15,7 @@
 import Repository from './repository/repository.vue';

 Vue.use(VueRouter);
+Vue.use(VueMoment);

 const router = new VueRouter({
 	mode: 'history',

<|original_code|>
import Vue from "vue";
import VueRouter from "vue-router";

import {createProvider} from './apollo';
import {store} from "./store";

import App from "./app.vue";
import Login from "./login.vue";
import UserList from "./user/list.vue";
import UserProfile from "./user/profile.vue";
import UserEdit from "./user/edit.vue";
import Pulls from "./pulls/pulls.vue";
import Issues from "./issues/issues.vue";
import Repository from './repository/repository.vue';

Vue.use(VueRouter);

const router = new VueRouter({
	mode: 'history',
	routes: [
		{path: "/", component: UserList},
		{path: "/login", component: Login},
		{path: '/pulls', component: Pulls},
		{path: '/issues', component: Issues},
		{path: "/:username", component: UserProfile},
		{path: "/:username/edit", component: UserEdit},
		{path: '/:owner/:repository', component: Repository},
	],
});

new Vue({
	el: '#app',
	store: store,
	router: router,
	apolloProvider: createProvider(),
	render: h => h(App)
});

<|edits_diff|>
--- ui/main.js
+++ ui/main.js
@@ -1,5 +1,6 @@
 import Vue from "vue";
 import VueRouter from "vue-router";
+import VueMoment from 'vue-moment';

 import {createProvider} from './apollo';
 import {store} from "./store";
<|current_version|>
import Vue from "vue";
import VueRouter from "vue-router";
import VueMoment from 'vue-moment';

import {createProvider} from './apollo';
import {store} from "./store";

import App from "./app.vue";
import Login from "./login.vue";
import UserList from "./user/list.vue";
import UserProfile from "./user/profile.vue";
import UserEdit from "./user/edit.vue";
import Pulls from "./pulls/pulls.vue";
import Issues from "./issues/issues.vue";
import Repository from './repository/repository.vue';

Vue.use(VueRouter);

const router = new VueRouter({
	mode: 'history',
	routes: [
		{path: "/", component: UserList},
		{path: "/login", component: Login},
		{path: '/pulls', component: Pulls},
		{path: '/issues', component: Issues},
		{path: "/:username", component: UserProfile},
		{path: "/:username/edit", component: UserEdit},
		{path: '/:owner/:repository', component: Repository},
	],
});

new Vue({
	el: '#app',
	store: store,
	router: router,
	apolloProvider: createProvider(),
	render: h => h(App)
});

<|next_version|>
import Vue from "vue";
import VueRouter from "vue-router";
import VueMoment from 'vue-moment';

import {createProvider} from './apollo';
import {store} from "./store";

import App from "./app.vue";
import Login from "./login.vue";
import UserList from "./user/list.vue";
import UserProfile from "./user/profile.vue";
import UserEdit from "./user/edit.vue";
import Pulls from "./pulls/pulls.vue";
import Issues from "./issues/issues.vue";
import Repository from './repository/repository.vue';

Vue.use(VueRouter);
Vue.use(VueMoment);

const router = new VueRouter({
	mode: 'history',
	routes: [
		{path: "/", component: UserList},
		{path: "/login", component: Login},
		{path: '/pulls', component: Pulls},
		{path: '/issues', component: Issues},
		{path: "/:username", component: UserProfile},
		{path: "/:username/edit", component: UserEdit},
		{path: '/:owner/:repository', component: Repository},
	],
});

new Vue({
	el: '#app',
	store: store,
	router: router,
	apolloProvider: createProvider(),
	render: h => h(App)
});


Add traversable and foldable to Id

Add traversable and foldable to Id

--- id.js
+++ id.js
@@ -12,6 +12,11 @@
     return new Id(this.value.empty ? this.value.empty() : this.value.constructor.empty());
 };

+// Foldable
+Id.prototype.reduce = function(f, acc) {
+    return f(acc, this.value);
+};
+
 // Functor
 Id.prototype.map = function(f) {
     return new Id(f(this.value));
@@ -20,6 +25,11 @@
 // Applicative
 Id.prototype.ap = function(b) {
     return new Id(this.value(b.value));
+};
+
+// Traversable
+Id.prototype.traverse = function(f, of) {
+    return f(this.value).map(function(y){ return new Id(y); });
 };

 // Chain

<|original_code|>
function Id(a) {
    this.value = a;
}

// Semigroup (value must also be a Semigroup)
Id.prototype.concat = function(b) {
    return new Id(this.value.concat(b.value));
};

// Monoid (value must also be a Monoid)
Id.prototype.empty = function() {
    return new Id(this.value.empty ? this.value.empty() : this.value.constructor.empty());
};

// Functor
Id.prototype.map = function(f) {
    return new Id(f(this.value));
};

// Applicative
Id.prototype.ap = function(b) {
    return new Id(this.value(b.value));
};

// Chain
Id.prototype.chain = function(f) {
    return f(this.value);
};

// Monad
Id.of = function(a) {
    return new Id(a);
};

if(typeof module == 'object') module.exports = Id;

<|edits_diff|>
--- id.js
+++ id.js
@@ -10,6 +10,11 @@
 // Monoid (value must also be a Monoid)
 Id.prototype.empty = function() {
     return new Id(this.value.empty ? this.value.empty() : this.value.constructor.empty());
+};
+
+// Foldable
+Id.prototype.reduce = function(f, acc) {
+    return f(acc, this.value);
 };

 // Functor
<|current_version|>
function Id(a) {
    this.value = a;
}

// Semigroup (value must also be a Semigroup)
Id.prototype.concat = function(b) {
    return new Id(this.value.concat(b.value));
};

// Monoid (value must also be a Monoid)
Id.prototype.empty = function() {
    return new Id(this.value.empty ? this.value.empty() : this.value.constructor.empty());
};

// Foldable
Id.prototype.reduce = function(f, acc) {
    return f(acc, this.value);
};

// Functor
Id.prototype.map = function(f) {
    return new Id(f(this.value));
};

// Applicative
Id.prototype.ap = function(b) {
    return new Id(this.value(b.value));
};

// Chain
Id.prototype.chain = function(f) {
    return f(this.value);
};

// Monad
Id.of = function(a) {
    return new Id(a);
};

if(typeof module == 'object') module.exports = Id;

<|next_version|>
function Id(a) {
    this.value = a;
}

// Semigroup (value must also be a Semigroup)
Id.prototype.concat = function(b) {
    return new Id(this.value.concat(b.value));
};

// Monoid (value must also be a Monoid)
Id.prototype.empty = function() {
    return new Id(this.value.empty ? this.value.empty() : this.value.constructor.empty());
};

// Foldable
Id.prototype.reduce = function(f, acc) {
    return f(acc, this.value);
};

// Functor
Id.prototype.map = function(f) {
    return new Id(f(this.value));
};

// Applicative
Id.prototype.ap = function(b) {
    return new Id(this.value(b.value));
};

// Traversable
Id.prototype.traverse = function(f, of) {
    return f(this.value).map(function(y){ return new Id(y); });
};

// Chain
Id.prototype.chain = function(f) {
    return f(this.value);
};

// Monad
Id.of = function(a) {
    return new Id(a);
};

if(typeof module == 'object') module.exports = Id;


Send index.html on all requests

Send index.html on all requests

--- server.js
+++ server.js
@@ -11,10 +11,20 @@

 app.use(express.static(path.join(__dirname, 'public')))

+app.get('/*', (req, res) => {
+  res.sendFile(path.join(__dirname, '/index.html'))
+})
+
 if (process.env.NODE_ENV !== 'production') {
   const compiler = webpack(config)
   const devServer = new WebpackDevServer(compiler, {
+    contentBase: __dirname,
+    hot: true,
+    quiet: false,
+    noInfo: false,
+    publicPath: '/assets/',

+    stats: { colors: true }
   })

   devServer.listen(8081)

<|original_code|>
const path = require('path')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const proxy = require('proxy-middleware')
const url = require('url')
const express = require('express')

const config = require('./webpack.config.js')

const app = express()

app.use(express.static(path.join(__dirname, 'public')))

if (process.env.NODE_ENV !== 'production') {
  const compiler = webpack(config)
  const devServer = new WebpackDevServer(compiler, {

  })

  devServer.listen(8081)

  app.use('/assets', proxy(url.parse('http://localhost:8081/assets')))
}

module.exports = app

<|edits_diff|>
--- server.js
+++ server.js
@@ -11,9 +11,18 @@

 app.use(express.static(path.join(__dirname, 'public')))

+app.get('/*', (req, res) => {
+  res.sendFile(path.join(__dirname, '/index.html'))
+})
+
 if (process.env.NODE_ENV !== 'production') {
   const compiler = webpack(config)
   const devServer = new WebpackDevServer(compiler, {
+    contentBase: __dirname,
+    hot: true,
+    quiet: false,
+    noInfo: false,
+    publicPath: '/assets/',

   })

<|current_version|>
const path = require('path')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const proxy = require('proxy-middleware')
const url = require('url')
const express = require('express')

const config = require('./webpack.config.js')

const app = express()

app.use(express.static(path.join(__dirname, 'public')))

app.get('/*', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'))
})

if (process.env.NODE_ENV !== 'production') {
  const compiler = webpack(config)
  const devServer = new WebpackDevServer(compiler, {
    contentBase: __dirname,
    hot: true,
    quiet: false,
    noInfo: false,
    publicPath: '/assets/',

  })

  devServer.listen(8081)

  app.use('/assets', proxy(url.parse('http://localhost:8081/assets')))
}

module.exports = app

<|next_version|>
const path = require('path')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const proxy = require('proxy-middleware')
const url = require('url')
const express = require('express')

const config = require('./webpack.config.js')

const app = express()

app.use(express.static(path.join(__dirname, 'public')))

app.get('/*', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'))
})

if (process.env.NODE_ENV !== 'production') {
  const compiler = webpack(config)
  const devServer = new WebpackDevServer(compiler, {
    contentBase: __dirname,
    hot: true,
    quiet: false,
    noInfo: false,
    publicPath: '/assets/',

    stats: { colors: true }
  })

  devServer.listen(8081)

  app.use('/assets', proxy(url.parse('http://localhost:8081/assets')))
}

module.exports = app


ADD toId back to core for chromatic

ADD toId back to core for chromatic

--- lib/core/src/client/preview/index.js
+++ lib/core/src/client/preview/index.js
@@ -1,8 +1,10 @@
 import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
+import { toId } from '@storybook/router/utils';
 import start from './start';

 export default {
   start,
+  toId,
   ClientApi,
   ConfigApi,
   StoryStore,

<|original_code|>
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import start from './start';

export default {
  start,
  ClientApi,
  ConfigApi,
  StoryStore,
};

<|edits_diff|>
--- lib/core/src/client/preview/index.js
+++ lib/core/src/client/preview/index.js
@@ -1,4 +1,5 @@
 import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
+import { toId } from '@storybook/router/utils';
 import start from './start';

 export default {
<|current_version|>
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import { toId } from '@storybook/router/utils';
import start from './start';

export default {
  start,
  ClientApi,
  ConfigApi,
  StoryStore,
};

<|next_version|>
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import { toId } from '@storybook/router/utils';
import start from './start';

export default {
  start,
  toId,
  ClientApi,
  ConfigApi,
  StoryStore,
};


Add the disabled and readOnly props directly to the SingleLineInputBase

--- src/components/input/TimeInput.js
+++ src/components/input/TimeInput.js
@@ -14,12 +14,15 @@
   };

   render() {
+    const { disabled, readOnly } = this.props;
     return (
       <InputMask {...this.props} mask="99:99" maskChar="0" beforeMaskedValueChange={this.beforeMaskedValueChange}>
         {inputProps => (
           <SingleLineInputBase
             {...inputProps}
             autoComplete="off"
+            readOnly={readOnly}
+            disabled={disabled}
             prefix={
               <Icon color="neutral" tint="darkest">
                 <IconTimerSmallOutline />

<|original_code|>
import React, { PureComponent } from 'react';
import InputMask from 'react-input-mask';
import Icon from '../icon';
import SingleLineInputBase from './SingleLineInputBase';
import { IconTimerSmallOutline } from '@teamleader/ui-icons';

const isValidTime = input => RegExp('([0-1][0-9]|[2][0-3]):([0-5][0-9])').test(input);
class TimeInput extends PureComponent {
  beforeMaskedValueChange = ({ value: newValue, selection }, { value: oldValue }) => {
    if (!isValidTime(newValue)) {
      return { value: oldValue, selection };
    }
    return { value: newValue, selection };
  };

  render() {
    return (
      <InputMask {...this.props} mask="99:99" maskChar="0" beforeMaskedValueChange={this.beforeMaskedValueChange}>
        {inputProps => (
          <SingleLineInputBase
            {...inputProps}
            autoComplete="off"
            prefix={
              <Icon color="neutral" tint="darkest">
                <IconTimerSmallOutline />
              </Icon>
            }
          />
        )}
      </InputMask>
    );
  }
}

export default TimeInput;

<|edits_diff|>
--- src/components/input/TimeInput.js
+++ src/components/input/TimeInput.js
@@ -14,6 +14,7 @@
   };

   render() {
+    const { disabled, readOnly } = this.props;
     return (
       <InputMask {...this.props} mask="99:99" maskChar="0" beforeMaskedValueChange={this.beforeMaskedValueChange}>
         {inputProps => (
<|current_version|>
import React, { PureComponent } from 'react';
import InputMask from 'react-input-mask';
import Icon from '../icon';
import SingleLineInputBase from './SingleLineInputBase';
import { IconTimerSmallOutline } from '@teamleader/ui-icons';

const isValidTime = input => RegExp('([0-1][0-9]|[2][0-3]):([0-5][0-9])').test(input);
class TimeInput extends PureComponent {
  beforeMaskedValueChange = ({ value: newValue, selection }, { value: oldValue }) => {
    if (!isValidTime(newValue)) {
      return { value: oldValue, selection };
    }
    return { value: newValue, selection };
  };

  render() {
    const { disabled, readOnly } = this.props;
    return (
      <InputMask {...this.props} mask="99:99" maskChar="0" beforeMaskedValueChange={this.beforeMaskedValueChange}>
        {inputProps => (
          <SingleLineInputBase
            {...inputProps}
            autoComplete="off"
            prefix={
              <Icon color="neutral" tint="darkest">
                <IconTimerSmallOutline />
              </Icon>
            }
          />
        )}
      </InputMask>
    );
  }
}

export default TimeInput;

<|next_version|>
import React, { PureComponent } from 'react';
import InputMask from 'react-input-mask';
import Icon from '../icon';
import SingleLineInputBase from './SingleLineInputBase';
import { IconTimerSmallOutline } from '@teamleader/ui-icons';

const isValidTime = input => RegExp('([0-1][0-9]|[2][0-3]):([0-5][0-9])').test(input);
class TimeInput extends PureComponent {
  beforeMaskedValueChange = ({ value: newValue, selection }, { value: oldValue }) => {
    if (!isValidTime(newValue)) {
      return { value: oldValue, selection };
    }
    return { value: newValue, selection };
  };

  render() {
    const { disabled, readOnly } = this.props;
    return (
      <InputMask {...this.props} mask="99:99" maskChar="0" beforeMaskedValueChange={this.beforeMaskedValueChange}>
        {inputProps => (
          <SingleLineInputBase
            {...inputProps}
            autoComplete="off"
            readOnly={readOnly}
            disabled={disabled}
            prefix={
              <Icon color="neutral" tint="darkest">
                <IconTimerSmallOutline />
              </Icon>
            }
          />
        )}
      </InputMask>
    );
  }
}

export default TimeInput;


Load file content and set file base for proper destination

--- index.js
+++ index.js
@@ -8,6 +8,7 @@
 var gutil = require('gulp-util');
 var PluginError = gutil.PluginError;
 var mainBowerFiles = require('main-bower-files');
+var fs = require('fs');

 module.exports = function () {
     return through.obj(function (file, enc, cb) {
@@ -22,6 +23,8 @@
             fileNames.forEach(function (fileName) {
                 var newFile = file.clone();
                 newFile.path = fileName;
+                newFile.base += 'bower_components/';
+                newFile.contents = fs.readFileSync(newFile.path);
                 this.push(newFile);
             }, this);
         }

<|original_code|>
/**
 * Created by Maurice on 6/13/2015.
 */

'use strict';

var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var mainBowerFiles = require('main-bower-files');

module.exports = function () {
    return through.obj(function (file, enc, cb) {
        if (file.isStream()) {
            this.emit('error', new PluginError('gulp-main-bower-files', 'Streams are not supported!'));
            return cb();
        }

        if (file.isBuffer()) {
            var fileNames = mainBowerFiles();

            fileNames.forEach(function (fileName) {
                var newFile = file.clone();
                newFile.path = fileName;
                this.push(newFile);
            }, this);
        }

        cb();
    });
};
<|edits_diff|>
--- index.js
+++ index.js
@@ -8,6 +8,7 @@
 var gutil = require('gulp-util');
 var PluginError = gutil.PluginError;
 var mainBowerFiles = require('main-bower-files');
+var fs = require('fs');

 module.exports = function () {
     return through.obj(function (file, enc, cb) {
<|current_version|>
/**
 * Created by Maurice on 6/13/2015.
 */

'use strict';

var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var mainBowerFiles = require('main-bower-files');
var fs = require('fs');

module.exports = function () {
    return through.obj(function (file, enc, cb) {
        if (file.isStream()) {
            this.emit('error', new PluginError('gulp-main-bower-files', 'Streams are not supported!'));
            return cb();
        }

        if (file.isBuffer()) {
            var fileNames = mainBowerFiles();

            fileNames.forEach(function (fileName) {
                var newFile = file.clone();
                newFile.path = fileName;
                this.push(newFile);
            }, this);
        }

        cb();
    });
};
<|next_version|>
/**
 * Created by Maurice on 6/13/2015.
 */

'use strict';

var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var mainBowerFiles = require('main-bower-files');
var fs = require('fs');

module.exports = function () {
    return through.obj(function (file, enc, cb) {
        if (file.isStream()) {
            this.emit('error', new PluginError('gulp-main-bower-files', 'Streams are not supported!'));
            return cb();
        }

        if (file.isBuffer()) {
            var fileNames = mainBowerFiles();

            fileNames.forEach(function (fileName) {
                var newFile = file.clone();
                newFile.path = fileName;
                newFile.base += 'bower_components/';
                newFile.contents = fs.readFileSync(newFile.path);
                this.push(newFile);
            }, this);
        }

        cb();
    });
};


Add filters module to deps

Add filters module to deps

--- app/js/main.js
+++ app/js/main.js
@@ -12,6 +12,7 @@
 require('./services/_index');
 require('./directives/_index');
 require('./components/_index');
+require('./filters/_index');

 // create and bootstrap application
 angular.element(document).ready(function() {
@@ -25,6 +26,7 @@
     'app.controllers',
     'app.services',
     'app.directives',
+    'app.filters',
     'ui.bootstrap.datetimepicker',
     'wu.masonry'
   ];

<|original_code|>
'use strict';

var angular = require('angular');

// angular modules
require('angular-ui-router');
require('angular-animate');
require('angular-moment');
require('angular-loading-bar');
require('./templates');
require('./controllers/_index');
require('./services/_index');
require('./directives/_index');
require('./components/_index');

// create and bootstrap application
angular.element(document).ready(function() {

  var requires = [
    'ui.router',
    'ngAnimate',
    'angularMoment',
    'angular-loading-bar',
    'templates',
    'app.controllers',
    'app.services',
    'app.directives',
    'ui.bootstrap.datetimepicker',
    'wu.masonry'
  ];

  // mount on window for testing
  window.app = angular.module('app', requires);

  angular.module('app').constant('AppSettings', require('./constants'));

  angular.module('app').config(require('./routes'));

  angular.module('app').run(require('./on_run'));

  angular.bootstrap(document, ['app']);

});
<|edits_diff|>
--- app/js/main.js
+++ app/js/main.js
@@ -12,6 +12,7 @@
 require('./services/_index');
 require('./directives/_index');
 require('./components/_index');
+require('./filters/_index');

 // create and bootstrap application
 angular.element(document).ready(function() {
<|current_version|>
'use strict';

var angular = require('angular');

// angular modules
require('angular-ui-router');
require('angular-animate');
require('angular-moment');
require('angular-loading-bar');
require('./templates');
require('./controllers/_index');
require('./services/_index');
require('./directives/_index');
require('./components/_index');
require('./filters/_index');

// create and bootstrap application
angular.element(document).ready(function() {

  var requires = [
    'ui.router',
    'ngAnimate',
    'angularMoment',
    'angular-loading-bar',
    'templates',
    'app.controllers',
    'app.services',
    'app.directives',
    'ui.bootstrap.datetimepicker',
    'wu.masonry'
  ];

  // mount on window for testing
  window.app = angular.module('app', requires);

  angular.module('app').constant('AppSettings', require('./constants'));

  angular.module('app').config(require('./routes'));

  angular.module('app').run(require('./on_run'));

  angular.bootstrap(document, ['app']);

});
<|next_version|>
'use strict';

var angular = require('angular');

// angular modules
require('angular-ui-router');
require('angular-animate');
require('angular-moment');
require('angular-loading-bar');
require('./templates');
require('./controllers/_index');
require('./services/_index');
require('./directives/_index');
require('./components/_index');
require('./filters/_index');

// create and bootstrap application
angular.element(document).ready(function() {

  var requires = [
    'ui.router',
    'ngAnimate',
    'angularMoment',
    'angular-loading-bar',
    'templates',
    'app.controllers',
    'app.services',
    'app.directives',
    'app.filters',
    'ui.bootstrap.datetimepicker',
    'wu.masonry'
  ];

  // mount on window for testing
  window.app = angular.module('app', requires);

  angular.module('app').constant('AppSettings', require('./constants'));

  angular.module('app').config(require('./routes'));

  angular.module('app').run(require('./on_run'));

  angular.bootstrap(document, ['app']);

});


Check for "to " with verbs

Check for "to " with verbs

--- app/validators/definitionlike.js
+++ app/validators/definitionlike.js
@@ -3,12 +3,15 @@

 export default Base.extend({
   call: function() {
+    var pos = (this.model.get("model.pos.pos") || this.model.get("model.meaning.pos"));
     var prop = this.model.get(this.property);
     var backtick = "`";
     var endingPunctuation = [".", "?", "!"];

     if (Ember.isBlank(prop)) {
       this.errors.pushObject("We need something here!");
+    } else if ((pos === "verb") && (prop.substr(0,3) !== "to ")) {
+      this.errors.pushObject("Verb definitions should start with 'to '");
     } else if (prop[0] === prop[0].toUpperCase()) {
       this.errors.pushObject("Start your definition with a lowercase letter.");
     } else if (endingPunctuation.contains(prop[prop.length - 1])) {

<|original_code|>
import Ember from 'ember';
import Base from 'ember-validations/validators/base';

export default Base.extend({
  call: function() {
    var prop = this.model.get(this.property);
    var backtick = "`";
    var endingPunctuation = [".", "?", "!"];

    if (Ember.isBlank(prop)) {
      this.errors.pushObject("We need something here!");
    } else if (prop[0] === prop[0].toUpperCase()) {
      this.errors.pushObject("Start your definition with a lowercase letter.");
    } else if (endingPunctuation.contains(prop[prop.length - 1])) {
      if (prop.substr(prop.length - 4) === "etc.") {
        // etc. is fine at the end of a definition
      }
      else {
        this.errors.pushObject("Don't finish your definition with punctuation.");
      }
    } else if (!Ember.isBlank(prop) && prop.indexOf(backtick) !== -1){
      this.errors.pushObject("No need for backticks.");
    }
  }
});

<|edits_diff|>
--- app/validators/definitionlike.js
+++ app/validators/definitionlike.js
@@ -3,6 +3,7 @@

 export default Base.extend({
   call: function() {
+    var pos = (this.model.get("model.pos.pos") || this.model.get("model.meaning.pos"));
     var prop = this.model.get(this.property);
     var backtick = "`";
     var endingPunctuation = [".", "?", "!"];
<|current_version|>
import Ember from 'ember';
import Base from 'ember-validations/validators/base';

export default Base.extend({
  call: function() {
    var pos = (this.model.get("model.pos.pos") || this.model.get("model.meaning.pos"));
    var prop = this.model.get(this.property);
    var backtick = "`";
    var endingPunctuation = [".", "?", "!"];

    if (Ember.isBlank(prop)) {
      this.errors.pushObject("We need something here!");
    } else if (prop[0] === prop[0].toUpperCase()) {
      this.errors.pushObject("Start your definition with a lowercase letter.");
    } else if (endingPunctuation.contains(prop[prop.length - 1])) {
      if (prop.substr(prop.length - 4) === "etc.") {
        // etc. is fine at the end of a definition
      }
      else {
        this.errors.pushObject("Don't finish your definition with punctuation.");
      }
    } else if (!Ember.isBlank(prop) && prop.indexOf(backtick) !== -1){
      this.errors.pushObject("No need for backticks.");
    }
  }
});

<|next_version|>
import Ember from 'ember';
import Base from 'ember-validations/validators/base';

export default Base.extend({
  call: function() {
    var pos = (this.model.get("model.pos.pos") || this.model.get("model.meaning.pos"));
    var prop = this.model.get(this.property);
    var backtick = "`";
    var endingPunctuation = [".", "?", "!"];

    if (Ember.isBlank(prop)) {
      this.errors.pushObject("We need something here!");
    } else if ((pos === "verb") && (prop.substr(0,3) !== "to ")) {
      this.errors.pushObject("Verb definitions should start with 'to '");
    } else if (prop[0] === prop[0].toUpperCase()) {
      this.errors.pushObject("Start your definition with a lowercase letter.");
    } else if (endingPunctuation.contains(prop[prop.length - 1])) {
      if (prop.substr(prop.length - 4) === "etc.") {
        // etc. is fine at the end of a definition
      }
      else {
        this.errors.pushObject("Don't finish your definition with punctuation.");
      }
    } else if (!Ember.isBlank(prop) && prop.indexOf(backtick) !== -1){
      this.errors.pushObject("No need for backticks.");
    }
  }
});


feat(Provider): Allow passing props to 'Notification' through 'Provider'

--- src/provider.js
+++ src/provider.js
@@ -25,6 +25,7 @@
           ref={(ref) => {
             this.notification = ref;
           }}
+          {...this.props}
         />
       </Context.Provider>
     );
@@ -32,6 +33,7 @@
 }

 Provider.propTypes = {
+  ...Notification.propTypes,
   children: PropTypes.element.isRequired,
 };

<|original_code|>
import React, { Children } from 'react';
import PropTypes from 'prop-types';

import Context from './context';
import Notification from './notification';

class Provider extends React.PureComponent {
  constructor(props) {
    super(props);

    this.showNotification = this.showNotification.bind(this);
  }

  showNotification(notificationOptions) {
    if (this.notification) {
      this.notification.show(notificationOptions);
    }
  }

  render() {
    return (
      <Context.Provider value={this.showNotification}>
        {Children.only(this.props.children)}
        <Notification
          ref={(ref) => {
            this.notification = ref;
          }}
        />
      </Context.Provider>
    );
  }
}

Provider.propTypes = {
  children: PropTypes.element.isRequired,
};

export default Provider;

<|edits_diff|>
--- src/provider.js
+++ src/provider.js
@@ -25,6 +25,7 @@
           ref={(ref) => {
             this.notification = ref;
           }}
+          {...this.props}
         />
       </Context.Provider>
     );
<|current_version|>
import React, { Children } from 'react';
import PropTypes from 'prop-types';

import Context from './context';
import Notification from './notification';

class Provider extends React.PureComponent {
  constructor(props) {
    super(props);

    this.showNotification = this.showNotification.bind(this);
  }

  showNotification(notificationOptions) {
    if (this.notification) {
      this.notification.show(notificationOptions);
    }
  }

  render() {
    return (
      <Context.Provider value={this.showNotification}>
        {Children.only(this.props.children)}
        <Notification
          ref={(ref) => {
            this.notification = ref;
          }}
          {...this.props}
        />
      </Context.Provider>
    );
  }
}

Provider.propTypes = {
  children: PropTypes.element.isRequired,
};

export default Provider;

<|next_version|>
import React, { Children } from 'react';
import PropTypes from 'prop-types';

import Context from './context';
import Notification from './notification';

class Provider extends React.PureComponent {
  constructor(props) {
    super(props);

    this.showNotification = this.showNotification.bind(this);
  }

  showNotification(notificationOptions) {
    if (this.notification) {
      this.notification.show(notificationOptions);
    }
  }

  render() {
    return (
      <Context.Provider value={this.showNotification}>
        {Children.only(this.props.children)}
        <Notification
          ref={(ref) => {
            this.notification = ref;
          }}
          {...this.props}
        />
      </Context.Provider>
    );
  }
}

Provider.propTypes = {
  ...Notification.propTypes,
  children: PropTypes.element.isRequired,
};

export default Provider;


Allow for config overrides without recompiling bundles

--- app/src/index.js
+++ app/src/index.js
@@ -6,12 +6,14 @@
 import MainScreen from './react/MainScreen';

 import config from './config';
+import localConfig from '../config';
 import SculptureApp from './app';

 window.onload = () => {
   const manifest = chrome.runtime.getManifest();
   console.log(`Version: ${manifest.version}`);

+  config.applyLocalConfig(localConfig);
   const app = new SculptureApp(config);
   ReactDOM.render(<MainScreen app={app} restart={() => chrome.runtime.reload()}/>, document.getElementById('anyware-root'));
 };

<|original_code|>
import 'babel-polyfill';

import React from 'react';
import ReactDOM from 'react-dom';

import MainScreen from './react/MainScreen';

import config from './config';
import SculptureApp from './app';

window.onload = () => {
  const manifest = chrome.runtime.getManifest();
  console.log(`Version: ${manifest.version}`);

  const app = new SculptureApp(config);
  ReactDOM.render(<MainScreen app={app} restart={() => chrome.runtime.reload()}/>, document.getElementById('anyware-root'));
};

<|edits_diff|>
--- app/src/index.js
+++ app/src/index.js
@@ -6,6 +6,7 @@
 import MainScreen from './react/MainScreen';

 import config from './config';
+import localConfig from '../config';
 import SculptureApp from './app';

 window.onload = () => {
<|current_version|>
import 'babel-polyfill';

import React from 'react';
import ReactDOM from 'react-dom';

import MainScreen from './react/MainScreen';

import config from './config';
import localConfig from '../config';
import SculptureApp from './app';

window.onload = () => {
  const manifest = chrome.runtime.getManifest();
  console.log(`Version: ${manifest.version}`);

  const app = new SculptureApp(config);
  ReactDOM.render(<MainScreen app={app} restart={() => chrome.runtime.reload()}/>, document.getElementById('anyware-root'));
};

<|next_version|>
import 'babel-polyfill';

import React from 'react';
import ReactDOM from 'react-dom';

import MainScreen from './react/MainScreen';

import config from './config';
import localConfig from '../config';
import SculptureApp from './app';

window.onload = () => {
  const manifest = chrome.runtime.getManifest();
  console.log(`Version: ${manifest.version}`);

  config.applyLocalConfig(localConfig);
  const app = new SculptureApp(config);
  ReactDOM.render(<MainScreen app={app} restart={() => chrome.runtime.reload()}/>, document.getElementById('anyware-root'));
};


Add comments to actions for detail

Add comments to actions for detail

--- src/js/actions/MapActions.js
+++ src/js/actions/MapActions.js
@@ -1,11 +1,19 @@
 import { SWITCH_FACTION, TOGGLE_FILTER, TOGGLE_GROUP } from '../constants/MapConstants';

+/*
+  Associated with the FactionSwitch component
+  Changes whether the map should display from the perspective of radiant or dire
+*/
 export function switchFaction() {
   return {
     type: SWITCH_FACTION
   };
 }

+/*
+  Associated wtih the FilterToggle component
+  Changes whether a category of entities (rune wards, push wards, etc) should be shown
+*/
 export function toggleFilter(group, filter) {
   return {
     type: TOGGLE_FILTER,
@@ -16,6 +24,10 @@
   };
 }

+/*
+  Associated wtih the ControlLabel component
+  Changes whether an entire group of filters (wards, camps, etc) should be shown
+*/
 export function toggleGroup(group, on) {
   return {
     type: TOGGLE_GROUP,

<|original_code|>
import { SWITCH_FACTION, TOGGLE_FILTER, TOGGLE_GROUP } from '../constants/MapConstants';

export function switchFaction() {
  return {
    type: SWITCH_FACTION
  };
}

export function toggleFilter(group, filter) {
  return {
    type: TOGGLE_FILTER,
    payload: {
      group,
      filter
    }
  };
}

export function toggleGroup(group, on) {
  return {
    type: TOGGLE_GROUP,
    payload: {
      group,
      on
    }
  };
}

<|edits_diff|>
--- src/js/actions/MapActions.js
+++ src/js/actions/MapActions.js
@@ -1,11 +1,19 @@
 import { SWITCH_FACTION, TOGGLE_FILTER, TOGGLE_GROUP } from '../constants/MapConstants';

+/*
+  Associated with the FactionSwitch component
+  Changes whether the map should display from the perspective of radiant or dire
+*/
 export function switchFaction() {
   return {
     type: SWITCH_FACTION
   };
 }

+/*
+  Associated wtih the FilterToggle component
+  Changes whether a category of entities (rune wards, push wards, etc) should be shown
+*/
 export function toggleFilter(group, filter) {
   return {
     type: TOGGLE_FILTER,
<|current_version|>
import { SWITCH_FACTION, TOGGLE_FILTER, TOGGLE_GROUP } from '../constants/MapConstants';

/*
  Associated with the FactionSwitch component
  Changes whether the map should display from the perspective of radiant or dire
*/
export function switchFaction() {
  return {
    type: SWITCH_FACTION
  };
}

/*
  Associated wtih the FilterToggle component
  Changes whether a category of entities (rune wards, push wards, etc) should be shown
*/
export function toggleFilter(group, filter) {
  return {
    type: TOGGLE_FILTER,
    payload: {
      group,
      filter
    }
  };
}

export function toggleGroup(group, on) {
  return {
    type: TOGGLE_GROUP,
    payload: {
      group,
      on
    }
  };
}

<|next_version|>
import { SWITCH_FACTION, TOGGLE_FILTER, TOGGLE_GROUP } from '../constants/MapConstants';

/*
  Associated with the FactionSwitch component
  Changes whether the map should display from the perspective of radiant or dire
*/
export function switchFaction() {
  return {
    type: SWITCH_FACTION
  };
}

/*
  Associated wtih the FilterToggle component
  Changes whether a category of entities (rune wards, push wards, etc) should be shown
*/
export function toggleFilter(group, filter) {
  return {
    type: TOGGLE_FILTER,
    payload: {
      group,
      filter
    }
  };
}

/*
  Associated wtih the ControlLabel component
  Changes whether an entire group of filters (wards, camps, etc) should be shown
*/
export function toggleGroup(group, on) {
  return {
    type: TOGGLE_GROUP,
    payload: {
      group,
      on
    }
  };
}


Update store blueprint as per docs

Update store blueprint as per docs

--- blueprints/store/index.js
+++ blueprints/store/index.js
@@ -9,11 +9,16 @@
 var Blueprint = require('../../lib/models/blueprint');

 module.exports = {
+
   description: 'Generates new store',
+
+  // Create __name__/actions.js and update state/cursor with appropriate elements
   beforeInstall: function(options) {
     return Promise.all([
+      Blueprint.load('action').install(options),
       Blueprint.load('state').install(options),
       Blueprint.load('cursor').install(options)
     ]);
   }
+
 };

<|original_code|>
/*
 * @fileOverview
 * @author: Mike Grabowski (@grabbou)
 */

'use strict';

var Promise = require('bluebird');
var Blueprint = require('../../lib/models/blueprint');

module.exports = {
  description: 'Generates new store',
  beforeInstall: function(options) {
    return Promise.all([
      Blueprint.load('state').install(options),
      Blueprint.load('cursor').install(options)
    ]);
  }
};
<|edits_diff|>
--- blueprints/store/index.js
+++ blueprints/store/index.js
@@ -9,9 +9,13 @@
 var Blueprint = require('../../lib/models/blueprint');

 module.exports = {
+
   description: 'Generates new store',
+
+  // Create __name__/actions.js and update state/cursor with appropriate elements
   beforeInstall: function(options) {
     return Promise.all([
+      Blueprint.load('action').install(options),
       Blueprint.load('state').install(options),
       Blueprint.load('cursor').install(options)
     ]);
<|current_version|>
/*
 * @fileOverview
 * @author: Mike Grabowski (@grabbou)
 */

'use strict';

var Promise = require('bluebird');
var Blueprint = require('../../lib/models/blueprint');

module.exports = {

  description: 'Generates new store',

  // Create __name__/actions.js and update state/cursor with appropriate elements
  beforeInstall: function(options) {
    return Promise.all([
      Blueprint.load('action').install(options),
      Blueprint.load('state').install(options),
      Blueprint.load('cursor').install(options)
    ]);
  }
};
<|next_version|>
/*
 * @fileOverview
 * @author: Mike Grabowski (@grabbou)
 */

'use strict';

var Promise = require('bluebird');
var Blueprint = require('../../lib/models/blueprint');

module.exports = {

  description: 'Generates new store',

  // Create __name__/actions.js and update state/cursor with appropriate elements
  beforeInstall: function(options) {
    return Promise.all([
      Blueprint.load('action').install(options),
      Blueprint.load('state').install(options),
      Blueprint.load('cursor').install(options)
    ]);
  }

};


[+] Add 'scenes' field to the Xsplit resource

--- server/src/models/xsplit.js
+++ server/src/models/xsplit.js
@@ -23,6 +23,7 @@
       this.media = data.media
       this.created = data.created
       this.modified = data.modified
+      this.scenes = data.scenes
     } else { // default values
       this.title = null
       this.picture = null
@@ -31,6 +32,7 @@
       this.episode = null // or {} or search for playing episode in the database
       this.topic = null // same
       this.media = null // same
+      this.scenes = []
       this.created = Date.now()
       this.modified = Date.now()
     }

<|original_code|>
const cache = require('memory-cache')
const websockets = require('../websockets')()

/**
 * Class representing the displayed data for XSplit
 */
class XSplit {
  constructor () {
    "use strict";
    let data = cache.get('xsplit')
    if (data !== null) {
      this.title = data.title
      this.picture = data.picture
      this.background = data.background
      this.logo = data.logo
      /**
       * actually, we should store the program, episode, topic and media currently playing :
       * that way, the client knows what to display (Media > Topic > Episode)
       * and the server doesn't need to tell the client what title or picture
       */
      this.episode = data.episode
      this.topic = data.topic
      this.media = data.media
      this.created = data.created
      this.modified = data.modified
    } else { // default values
      this.title = null
      this.picture = null
      this.background = null
      this.logo = null
      this.episode = null // or {} or search for playing episode in the database
      this.topic = null // same
      this.media = null // same
      this.created = Date.now()
      this.modified = Date.now()
    }
  }

  save() {
    cache.put('xsplit', this)
    websockets.sockets.emit('xsplit', this)
  }
}

module.exports = XSplit;

<|edits_diff|>
--- server/src/models/xsplit.js
+++ server/src/models/xsplit.js
@@ -23,6 +23,7 @@
       this.media = data.media
       this.created = data.created
       this.modified = data.modified
+      this.scenes = data.scenes
     } else { // default values
       this.title = null
       this.picture = null
<|current_version|>
const cache = require('memory-cache')
const websockets = require('../websockets')()

/**
 * Class representing the displayed data for XSplit
 */
class XSplit {
  constructor () {
    "use strict";
    let data = cache.get('xsplit')
    if (data !== null) {
      this.title = data.title
      this.picture = data.picture
      this.background = data.background
      this.logo = data.logo
      /**
       * actually, we should store the program, episode, topic and media currently playing :
       * that way, the client knows what to display (Media > Topic > Episode)
       * and the server doesn't need to tell the client what title or picture
       */
      this.episode = data.episode
      this.topic = data.topic
      this.media = data.media
      this.created = data.created
      this.modified = data.modified
      this.scenes = data.scenes
    } else { // default values
      this.title = null
      this.picture = null
      this.background = null
      this.logo = null
      this.episode = null // or {} or search for playing episode in the database
      this.topic = null // same
      this.media = null // same
      this.created = Date.now()
      this.modified = Date.now()
    }
  }

  save() {
    cache.put('xsplit', this)
    websockets.sockets.emit('xsplit', this)
  }
}

module.exports = XSplit;

<|next_version|>
const cache = require('memory-cache')
const websockets = require('../websockets')()

/**
 * Class representing the displayed data for XSplit
 */
class XSplit {
  constructor () {
    "use strict";
    let data = cache.get('xsplit')
    if (data !== null) {
      this.title = data.title
      this.picture = data.picture
      this.background = data.background
      this.logo = data.logo
      /**
       * actually, we should store the program, episode, topic and media currently playing :
       * that way, the client knows what to display (Media > Topic > Episode)
       * and the server doesn't need to tell the client what title or picture
       */
      this.episode = data.episode
      this.topic = data.topic
      this.media = data.media
      this.created = data.created
      this.modified = data.modified
      this.scenes = data.scenes
    } else { // default values
      this.title = null
      this.picture = null
      this.background = null
      this.logo = null
      this.episode = null // or {} or search for playing episode in the database
      this.topic = null // same
      this.media = null // same
      this.scenes = []
      this.created = Date.now()
      this.modified = Date.now()
    }
  }

  save() {
    cache.put('xsplit', this)
    websockets.sockets.emit('xsplit', this)
  }
}

module.exports = XSplit;


Add routes to the router middleware.

Add routes to the router middleware.

--- app/routes/index.js
+++ app/routes/index.js
@@ -1,10 +1,14 @@
 'use strict';

 var express = require('express');
+
+var fileRoutes = require('./file.routes');

 module.exports = function () {

   var router = express.Router();

+  fileRoutes(router);
+
   return router;
 };

<|original_code|>
'use strict';

var express = require('express');

module.exports = function () {

  var router = express.Router();

  return router;
};

<|edits_diff|>
--- app/routes/index.js
+++ app/routes/index.js
@@ -1,6 +1,8 @@
 'use strict';

 var express = require('express');
+
+var fileRoutes = require('./file.routes');

 module.exports = function () {

<|current_version|>
'use strict';

var express = require('express');

var fileRoutes = require('./file.routes');

module.exports = function () {

  var router = express.Router();

  return router;
};

<|next_version|>
'use strict';

var express = require('express');

var fileRoutes = require('./file.routes');

module.exports = function () {

  var router = express.Router();

  fileRoutes(router);

  return router;
};


Update Firefox profile: Disable WebRTC, DNS prefetch and IPv6, safebrowsing; Enable socks remote DNS

--- browser-profiles/firefox/prefs.js
+++ browser-profiles/firefox/prefs.js
@@ -11,6 +11,12 @@
 user_pref("network.proxy.share_proxy_settings", true);
 user_pref("network.proxy.socks", "127.0.0.1");
 user_pref("network.proxy.socks_port", 3090);
+user_pref("network.proxy.socks_remote_dns", true);
 user_pref("network.proxy.ssl", "127.0.0.1");
 user_pref("network.proxy.ssl_port", 3090);
 user_pref("network.proxy.type", 1);
+user_pref("media.peerconnection.enabled", false);
+user_pref("browser.safebrowsing.malware.enabled", false);
+user_pref("browser.safebrowsing.enabled", false);
+user_pref("network.dns.disablePrefetch", true);
+user_pref("network.dns.disableIPv6", true);

<|original_code|>
user_pref("network.proxy.backup.ftp", "");
user_pref("network.proxy.backup.ftp_port", 0);
user_pref("network.proxy.backup.socks", "");
user_pref("network.proxy.backup.socks_port", 0);
user_pref("network.proxy.backup.ssl", "");
user_pref("network.proxy.backup.ssl_port", 0);
user_pref("network.proxy.ftp", "127.0.0.1");
user_pref("network.proxy.ftp_port", 3090);
user_pref("network.proxy.http", "127.0.0.1");
user_pref("network.proxy.http_port", 3090);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 3090);
user_pref("network.proxy.ssl", "127.0.0.1");
user_pref("network.proxy.ssl_port", 3090);
user_pref("network.proxy.type", 1);

<|edits_diff|>
--- browser-profiles/firefox/prefs.js
+++ browser-profiles/firefox/prefs.js
@@ -11,6 +11,7 @@
 user_pref("network.proxy.share_proxy_settings", true);
 user_pref("network.proxy.socks", "127.0.0.1");
 user_pref("network.proxy.socks_port", 3090);
+user_pref("network.proxy.socks_remote_dns", true);
 user_pref("network.proxy.ssl", "127.0.0.1");
 user_pref("network.proxy.ssl_port", 3090);
 user_pref("network.proxy.type", 1);
<|current_version|>
user_pref("network.proxy.backup.ftp", "");
user_pref("network.proxy.backup.ftp_port", 0);
user_pref("network.proxy.backup.socks", "");
user_pref("network.proxy.backup.socks_port", 0);
user_pref("network.proxy.backup.ssl", "");
user_pref("network.proxy.backup.ssl_port", 0);
user_pref("network.proxy.ftp", "127.0.0.1");
user_pref("network.proxy.ftp_port", 3090);
user_pref("network.proxy.http", "127.0.0.1");
user_pref("network.proxy.http_port", 3090);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 3090);
user_pref("network.proxy.socks_remote_dns", true);
user_pref("network.proxy.ssl", "127.0.0.1");
user_pref("network.proxy.ssl_port", 3090);
user_pref("network.proxy.type", 1);

<|next_version|>
user_pref("network.proxy.backup.ftp", "");
user_pref("network.proxy.backup.ftp_port", 0);
user_pref("network.proxy.backup.socks", "");
user_pref("network.proxy.backup.socks_port", 0);
user_pref("network.proxy.backup.ssl", "");
user_pref("network.proxy.backup.ssl_port", 0);
user_pref("network.proxy.ftp", "127.0.0.1");
user_pref("network.proxy.ftp_port", 3090);
user_pref("network.proxy.http", "127.0.0.1");
user_pref("network.proxy.http_port", 3090);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 3090);
user_pref("network.proxy.socks_remote_dns", true);
user_pref("network.proxy.ssl", "127.0.0.1");
user_pref("network.proxy.ssl_port", 3090);
user_pref("network.proxy.type", 1);
user_pref("media.peerconnection.enabled", false);
user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.safebrowsing.enabled", false);
user_pref("network.dns.disablePrefetch", true);
user_pref("network.dns.disableIPv6", true);


Add plugins to included configs

Add plugins to included configs

--- index.js
+++ index.js
@@ -15,6 +15,7 @@
   rules: rules,
   configs: {
     recommended: {
+      plugins: ['redux-saga'],
       rules: {
         "redux-saga/no-yield-in-race": 2,
         "redux-saga/yield-effects": 2,
@@ -22,6 +23,7 @@
       }
     },
     all: {
+      plugins: ['redux-saga'],
       rules: allRules
     }
   }

<|original_code|>
"use strict"

var rules = {
  "no-yield-in-race": require("./lib/rules/no-yield-in-race"),
  "yield-effects": require("./lib/rules/yield-effects"),
  "no-unhandled-errors": require("./lib/rules/no-unhandled-errors")
}

var allRules = Object.keys(rules).reduce(function(result, name) {
  result["redux-saga/" + name] = 2
  return result
}, {})

module.exports = {
  rules: rules,
  configs: {
    recommended: {
      rules: {
        "redux-saga/no-yield-in-race": 2,
        "redux-saga/yield-effects": 2,
        "redux-saga/no-unhandled-errors": 2
      }
    },
    all: {
      rules: allRules
    }
  }
}

<|edits_diff|>
--- index.js
+++ index.js
@@ -15,6 +15,7 @@
   rules: rules,
   configs: {
     recommended: {
+      plugins: ['redux-saga'],
       rules: {
         "redux-saga/no-yield-in-race": 2,
         "redux-saga/yield-effects": 2,
<|current_version|>
"use strict"

var rules = {
  "no-yield-in-race": require("./lib/rules/no-yield-in-race"),
  "yield-effects": require("./lib/rules/yield-effects"),
  "no-unhandled-errors": require("./lib/rules/no-unhandled-errors")
}

var allRules = Object.keys(rules).reduce(function(result, name) {
  result["redux-saga/" + name] = 2
  return result
}, {})

module.exports = {
  rules: rules,
  configs: {
    recommended: {
      plugins: ['redux-saga'],
      rules: {
        "redux-saga/no-yield-in-race": 2,
        "redux-saga/yield-effects": 2,
        "redux-saga/no-unhandled-errors": 2
      }
    },
    all: {
      rules: allRules
    }
  }
}

<|next_version|>
"use strict"

var rules = {
  "no-yield-in-race": require("./lib/rules/no-yield-in-race"),
  "yield-effects": require("./lib/rules/yield-effects"),
  "no-unhandled-errors": require("./lib/rules/no-unhandled-errors")
}

var allRules = Object.keys(rules).reduce(function(result, name) {
  result["redux-saga/" + name] = 2
  return result
}, {})

module.exports = {
  rules: rules,
  configs: {
    recommended: {
      plugins: ['redux-saga'],
      rules: {
        "redux-saga/no-yield-in-race": 2,
        "redux-saga/yield-effects": 2,
        "redux-saga/no-unhandled-errors": 2
      }
    },
    all: {
      plugins: ['redux-saga'],
      rules: allRules
    }
  }
}


Fix test to work with ngNotify

Fix test to work with ngNotify

--- app/login/login_test.js
+++ app/login/login_test.js
@@ -5,6 +5,7 @@

   // Mock unavailable modules
   angular.module('ngMessages', []);
+  angular.module('ngNotify', []);
   angular.module('angularBasicAuthExample.user', []);

   beforeEach(module('angularBasicAuthExample.login'));
@@ -15,6 +16,7 @@
       var user = {login: function() {}};
       var parameters = {
         $scope: scope,
+        ngNotify: null,
         User: user
       };
       var loginCtrl = $controller('LoginCtrl', parameters);

<|original_code|>
'use strict';

describe('angularBasicAuthExample.login module', function() {
  var scope;

  // Mock unavailable modules
  angular.module('ngMessages', []);
  angular.module('angularBasicAuthExample.user', []);

  beforeEach(module('angularBasicAuthExample.login'));

  describe('login controller', function() {
    it('should ....', inject(function($rootScope, $controller) {
      scope = $rootScope.$new();
      var user = {login: function() {}};
      var parameters = {
        $scope: scope,
        User: user
      };
      var loginCtrl = $controller('LoginCtrl', parameters);
      expect(loginCtrl).toBeDefined();
    }));

  });
});

<|edits_diff|>
--- app/login/login_test.js
+++ app/login/login_test.js
@@ -5,6 +5,7 @@

   // Mock unavailable modules
   angular.module('ngMessages', []);
+  angular.module('ngNotify', []);
   angular.module('angularBasicAuthExample.user', []);

   beforeEach(module('angularBasicAuthExample.login'));
<|current_version|>
'use strict';

describe('angularBasicAuthExample.login module', function() {
  var scope;

  // Mock unavailable modules
  angular.module('ngMessages', []);
  angular.module('ngNotify', []);
  angular.module('angularBasicAuthExample.user', []);

  beforeEach(module('angularBasicAuthExample.login'));

  describe('login controller', function() {
    it('should ....', inject(function($rootScope, $controller) {
      scope = $rootScope.$new();
      var user = {login: function() {}};
      var parameters = {
        $scope: scope,
        User: user
      };
      var loginCtrl = $controller('LoginCtrl', parameters);
      expect(loginCtrl).toBeDefined();
    }));

  });
});

<|next_version|>
'use strict';

describe('angularBasicAuthExample.login module', function() {
  var scope;

  // Mock unavailable modules
  angular.module('ngMessages', []);
  angular.module('ngNotify', []);
  angular.module('angularBasicAuthExample.user', []);

  beforeEach(module('angularBasicAuthExample.login'));

  describe('login controller', function() {
    it('should ....', inject(function($rootScope, $controller) {
      scope = $rootScope.$new();
      var user = {login: function() {}};
      var parameters = {
        $scope: scope,
        ngNotify: null,
        User: user
      };
      var loginCtrl = $controller('LoginCtrl', parameters);
      expect(loginCtrl).toBeDefined();
    }));

  });
});


Disable action buttons until AJAX is finished.

--- src/client/btnAction.js
+++ src/client/btnAction.js
@@ -20,12 +20,16 @@

     const data = JSON.parse($btn.attr('data-keys-json') || '{}');

+    $btn.prop('disabled', true);
+
     Keys.stdAjax({
       type: $btn.attr('data-keys-method'),
       url: $btn.attr('data-keys-action'),
       redirect: $btn.attr('data-keys-redirect'),
       dataType: $btn.attr('data-keys-params-data-type'),
       data,
+
+      always: () => $btn.prop('disabled', false),
     });
   });
 });

<|original_code|>
/* global confirm */

const $ = require('jquery');

const Keys = require('keys/dist/client');

$(() => {
  $('body').on('click', 'button[data-keys-action]', ev => {
    ev.preventDefault();

    const $btn = $(ev.target);

    {
      const confirmationQuestion = $btn.attr('data-keys-confirm');

      if (confirmationQuestion && !confirm(confirmationQuestion)) {
        return;
      }
    }

    const data = JSON.parse($btn.attr('data-keys-json') || '{}');

    Keys.stdAjax({
      type: $btn.attr('data-keys-method'),
      url: $btn.attr('data-keys-action'),
      redirect: $btn.attr('data-keys-redirect'),
      dataType: $btn.attr('data-keys-params-data-type'),
      data,
    });
  });
});

<|edits_diff|>
--- src/client/btnAction.js
+++ src/client/btnAction.js
@@ -20,6 +20,8 @@

     const data = JSON.parse($btn.attr('data-keys-json') || '{}');

+    $btn.prop('disabled', true);
+
     Keys.stdAjax({
       type: $btn.attr('data-keys-method'),
       url: $btn.attr('data-keys-action'),
<|current_version|>
/* global confirm */

const $ = require('jquery');

const Keys = require('keys/dist/client');

$(() => {
  $('body').on('click', 'button[data-keys-action]', ev => {
    ev.preventDefault();

    const $btn = $(ev.target);

    {
      const confirmationQuestion = $btn.attr('data-keys-confirm');

      if (confirmationQuestion && !confirm(confirmationQuestion)) {
        return;
      }
    }

    const data = JSON.parse($btn.attr('data-keys-json') || '{}');

    $btn.prop('disabled', true);

    Keys.stdAjax({
      type: $btn.attr('data-keys-method'),
      url: $btn.attr('data-keys-action'),
      redirect: $btn.attr('data-keys-redirect'),
      dataType: $btn.attr('data-keys-params-data-type'),
      data,
    });
  });
});

<|next_version|>
/* global confirm */

const $ = require('jquery');

const Keys = require('keys/dist/client');

$(() => {
  $('body').on('click', 'button[data-keys-action]', ev => {
    ev.preventDefault();

    const $btn = $(ev.target);

    {
      const confirmationQuestion = $btn.attr('data-keys-confirm');

      if (confirmationQuestion && !confirm(confirmationQuestion)) {
        return;
      }
    }

    const data = JSON.parse($btn.attr('data-keys-json') || '{}');

    $btn.prop('disabled', true);

    Keys.stdAjax({
      type: $btn.attr('data-keys-method'),
      url: $btn.attr('data-keys-action'),
      redirect: $btn.attr('data-keys-redirect'),
      dataType: $btn.attr('data-keys-params-data-type'),
      data,

      always: () => $btn.prop('disabled', false),
    });
  });
});


Add docs to server init

Add docs to server init

--- app/main.js
+++ app/main.js
@@ -3,9 +3,12 @@
 let less = require('less-middleware');
 let app = express();

+// Set up EJS views
 app.set('views', __dirname + '/views');
 app.set('view engine', 'ejs');
+// Set LESS for CSS pre-processing
 app.use(less(__dirname + '/static'));
+// Set up static directory
 app.use(express.static(__dirname + '/static'));

 const port = 3000;

<|original_code|>
// {{{ Express HTTP server setup
let express = require('express');
let less = require('less-middleware');
let app = express();

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(less(__dirname + '/static'));
app.use(express.static(__dirname + '/static'));

const port = 3000;

// Routers
let index = require('./routes/index');

app.use('/', index);
// }}}

// {{{ MongoDB database client setup
let mongo = require('mongodb').MongoClient;
let config = require('config');

let mConf = config.get('mongo');
let url = 'mongodb://' + mConf.host + ':' + mConf.port + '/' + mConf.database;
console.log(url);

mongo.connect(url, function(err, db) {
  if (err) {
    console.log('Unable to connect to database. Exiting...');
    exit(1);
  } else {
    console.log('Successfully connected to database');
  }
});

// }}}

app.listen(port);
// Log to console
console.log('Pigeon has started.');
console.log(__dirname);
console.log('Listening for connections on port ' + port + '.');

<|edits_diff|>
--- app/main.js
+++ app/main.js
@@ -3,8 +3,10 @@
 let less = require('less-middleware');
 let app = express();

+// Set up EJS views
 app.set('views', __dirname + '/views');
 app.set('view engine', 'ejs');
+// Set LESS for CSS pre-processing
 app.use(less(__dirname + '/static'));
 app.use(express.static(__dirname + '/static'));

<|current_version|>
// {{{ Express HTTP server setup
let express = require('express');
let less = require('less-middleware');
let app = express();

// Set up EJS views
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// Set LESS for CSS pre-processing
app.use(less(__dirname + '/static'));
app.use(express.static(__dirname + '/static'));

const port = 3000;

// Routers
let index = require('./routes/index');

app.use('/', index);
// }}}

// {{{ MongoDB database client setup
let mongo = require('mongodb').MongoClient;
let config = require('config');

let mConf = config.get('mongo');
let url = 'mongodb://' + mConf.host + ':' + mConf.port + '/' + mConf.database;
console.log(url);

mongo.connect(url, function(err, db) {
  if (err) {
    console.log('Unable to connect to database. Exiting...');
    exit(1);
  } else {
    console.log('Successfully connected to database');
  }
});

// }}}

app.listen(port);
// Log to console
console.log('Pigeon has started.');
console.log(__dirname);
console.log('Listening for connections on port ' + port + '.');

<|next_version|>
// {{{ Express HTTP server setup
let express = require('express');
let less = require('less-middleware');
let app = express();

// Set up EJS views
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// Set LESS for CSS pre-processing
app.use(less(__dirname + '/static'));
// Set up static directory
app.use(express.static(__dirname + '/static'));

const port = 3000;

// Routers
let index = require('./routes/index');

app.use('/', index);
// }}}

// {{{ MongoDB database client setup
let mongo = require('mongodb').MongoClient;
let config = require('config');

let mConf = config.get('mongo');
let url = 'mongodb://' + mConf.host + ':' + mConf.port + '/' + mConf.database;
console.log(url);

mongo.connect(url, function(err, db) {
  if (err) {
    console.log('Unable to connect to database. Exiting...');
    exit(1);
  } else {
    console.log('Successfully connected to database');
  }
});

// }}}

app.listen(port);
// Log to console
console.log('Pigeon has started.');
console.log(__dirname);
console.log('Listening for connections on port ' + port + '.');


Add comments to example module

Add comments to example module

--- server/EchoChat.js
+++ server/EchoChat.js
@@ -7,6 +7,11 @@
         this.ws = ws;
     }

+    /**
+     * Default message routing function for this object.
+     * The routing server assumes all modules will have a
+     * doAction() function.
+     */
     doAction( messageObj ) {
         console.log( "do action", messageObj );
         switch( messageObj.data.action ) {
@@ -19,6 +24,9 @@
         }
     }

+    /**
+     * Simple function to echo the user message back to them.
+     */
     echoMessage( messageObj ) {
         this.ws.send( JSON.stringify( {
             isSuccess: true,
@@ -30,6 +38,9 @@
         } ) );
     }

+    /**
+     * Send the user a generic response message
+     */
     sendResponse( messageObj ) {
         this.ws.send( JSON.stringify( {
             isSuccess: true,

<|original_code|>
/**
 * Example WebSocket module.
 */

class EchoChat {
    constructor( ws ) {
        this.ws = ws;
    }

    doAction( messageObj ) {
        console.log( "do action", messageObj );
        switch( messageObj.data.action ) {
            case 'echo_message':
                this.echoMessage( messageObj );
                break;
            case 'send_response':
                this.sendResponse( messageObj );
                break;
        }
    }

    echoMessage( messageObj ) {
        this.ws.send( JSON.stringify( {
            isSuccess: true,
            call_id:   messageObj.call_id,
            data:      {
                message: messageObj.data.message,
                user:    'dan',
            }
        } ) );
    }

    sendResponse( messageObj ) {
        this.ws.send( JSON.stringify( {
            isSuccess: true,
            call_id:   messageObj.call_id,
            data:      {
                message: 'Response Message',
                user:    'brian',
            }
        } ) );
    }
}

module.exports.EchoChat = EchoChat;

<|edits_diff|>
--- server/EchoChat.js
+++ server/EchoChat.js
@@ -7,6 +7,11 @@
         this.ws = ws;
     }

+    /**
+     * Default message routing function for this object.
+     * The routing server assumes all modules will have a
+     * doAction() function.
+     */
     doAction( messageObj ) {
         console.log( "do action", messageObj );
         switch( messageObj.data.action ) {
@@ -19,6 +24,9 @@
         }
     }

+    /**
+     * Simple function to echo the user message back to them.
+     */
     echoMessage( messageObj ) {
         this.ws.send( JSON.stringify( {
             isSuccess: true,
<|current_version|>
/**
 * Example WebSocket module.
 */

class EchoChat {
    constructor( ws ) {
        this.ws = ws;
    }

    /**
     * Default message routing function for this object.
     * The routing server assumes all modules will have a
     * doAction() function.
     */
    doAction( messageObj ) {
        console.log( "do action", messageObj );
        switch( messageObj.data.action ) {
            case 'echo_message':
                this.echoMessage( messageObj );
                break;
            case 'send_response':
                this.sendResponse( messageObj );
                break;
        }
    }

    /**
     * Simple function to echo the user message back to them.
     */
    echoMessage( messageObj ) {
        this.ws.send( JSON.stringify( {
            isSuccess: true,
            call_id:   messageObj.call_id,
            data:      {
                message: messageObj.data.message,
                user:    'dan',
            }
        } ) );
    }

    sendResponse( messageObj ) {
        this.ws.send( JSON.stringify( {
            isSuccess: true,
            call_id:   messageObj.call_id,
            data:      {
                message: 'Response Message',
                user:    'brian',
            }
        } ) );
    }
}

module.exports.EchoChat = EchoChat;

<|next_version|>
/**
 * Example WebSocket module.
 */

class EchoChat {
    constructor( ws ) {
        this.ws = ws;
    }

    /**
     * Default message routing function for this object.
     * The routing server assumes all modules will have a
     * doAction() function.
     */
    doAction( messageObj ) {
        console.log( "do action", messageObj );
        switch( messageObj.data.action ) {
            case 'echo_message':
                this.echoMessage( messageObj );
                break;
            case 'send_response':
                this.sendResponse( messageObj );
                break;
        }
    }

    /**
     * Simple function to echo the user message back to them.
     */
    echoMessage( messageObj ) {
        this.ws.send( JSON.stringify( {
            isSuccess: true,
            call_id:   messageObj.call_id,
            data:      {
                message: messageObj.data.message,
                user:    'dan',
            }
        } ) );
    }

    /**
     * Send the user a generic response message
     */
    sendResponse( messageObj ) {
        this.ws.send( JSON.stringify( {
            isSuccess: true,
            call_id:   messageObj.call_id,
            data:      {
                message: 'Response Message',
                user:    'brian',
            }
        } ) );
    }
}

module.exports.EchoChat = EchoChat;


Add more badges to README

feat(templates): Add more badges to README

--- src/templates/readme.js
+++ src/templates/readme.js
@@ -8,7 +8,10 @@
     path: 'README.md',
     content: `
       # ${packageName}
+      ![npm](https://img.shields.io/npm/v/${packageName}.svg)
       [![Build Status](https://travis-ci.org/${repoName}.svg?branch=master)](https://travis-ci.org/${repoName})
+      [![dependencies Status](https://david-dm.org/${repoName}/status.svg)](https://david-dm.org/${repoName})
+      [![devDependencies Status](https://david-dm.org/${repoName}/dev-status.svg)](https://david-dm.org/${repoName}?type=dev)

       An awesome package

<|original_code|>
/* @flow */
import type { Template } from 'create-npm/lib/template'

export default function({ repoName }: { repoName: string }): Template {
  const [, packageName] = repoName.split('/')

  return {
    path: 'README.md',
    content: `
      # ${packageName}
      [![Build Status](https://travis-ci.org/${repoName}.svg?branch=master)](https://travis-ci.org/${repoName})

      An awesome package

      ## Usage
      Install [${packageName}](https://yarnpkg.com/en/package/${packageName})
      by running:

      \`\`\`sh
      yarn add ${packageName}
      \`\`\`
    `
  }
}

<|edits_diff|>
--- src/templates/readme.js
+++ src/templates/readme.js
@@ -8,6 +8,7 @@
     path: 'README.md',
     content: `
       # ${packageName}
+      ![npm](https://img.shields.io/npm/v/${packageName}.svg)
       [![Build Status](https://travis-ci.org/${repoName}.svg?branch=master)](https://travis-ci.org/${repoName})

       An awesome package
<|current_version|>
/* @flow */
import type { Template } from 'create-npm/lib/template'

export default function({ repoName }: { repoName: string }): Template {
  const [, packageName] = repoName.split('/')

  return {
    path: 'README.md',
    content: `
      # ${packageName}
      ![npm](https://img.shields.io/npm/v/${packageName}.svg)
      [![Build Status](https://travis-ci.org/${repoName}.svg?branch=master)](https://travis-ci.org/${repoName})

      An awesome package

      ## Usage
      Install [${packageName}](https://yarnpkg.com/en/package/${packageName})
      by running:

      \`\`\`sh
      yarn add ${packageName}
      \`\`\`
    `
  }
}

<|next_version|>
/* @flow */
import type { Template } from 'create-npm/lib/template'

export default function({ repoName }: { repoName: string }): Template {
  const [, packageName] = repoName.split('/')

  return {
    path: 'README.md',
    content: `
      # ${packageName}
      ![npm](https://img.shields.io/npm/v/${packageName}.svg)
      [![Build Status](https://travis-ci.org/${repoName}.svg?branch=master)](https://travis-ci.org/${repoName})
      [![dependencies Status](https://david-dm.org/${repoName}/status.svg)](https://david-dm.org/${repoName})
      [![devDependencies Status](https://david-dm.org/${repoName}/dev-status.svg)](https://david-dm.org/${repoName}?type=dev)

      An awesome package

      ## Usage
      Install [${packageName}](https://yarnpkg.com/en/package/${packageName})
      by running:

      \`\`\`sh
      yarn add ${packageName}
      \`\`\`
    `
  }
}


Add custom prop isOwn to descriptor

Add custom prop isOwn to descriptor

Makes it possible to see if the descriptor
originates from the object or its prototype chain

--- lib/sinon/util/core/get-property-descriptor.js
+++ lib/sinon/util/core/get-property-descriptor.js
@@ -3,9 +3,15 @@
 module.exports = function getPropertyDescriptor(object, property) {
     var proto = object;
     var descriptor;
+    var isOwn = object && Object.getOwnPropertyDescriptor(object, property);

     while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
         proto = Object.getPrototypeOf(proto);
     }
+
+    if (descriptor) {
+        descriptor.isOwn = isOwn;
+    }
+
     return descriptor;
 };

<|original_code|>
"use strict";

module.exports = function getPropertyDescriptor(object, property) {
    var proto = object;
    var descriptor;

    while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
        proto = Object.getPrototypeOf(proto);
    }
    return descriptor;
};

<|edits_diff|>
--- lib/sinon/util/core/get-property-descriptor.js
+++ lib/sinon/util/core/get-property-descriptor.js
@@ -3,6 +3,7 @@
 module.exports = function getPropertyDescriptor(object, property) {
     var proto = object;
     var descriptor;
+    var isOwn = object && Object.getOwnPropertyDescriptor(object, property);

     while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
         proto = Object.getPrototypeOf(proto);
<|current_version|>
"use strict";

module.exports = function getPropertyDescriptor(object, property) {
    var proto = object;
    var descriptor;
    var isOwn = object && Object.getOwnPropertyDescriptor(object, property);

    while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
        proto = Object.getPrototypeOf(proto);
    }
    return descriptor;
};

<|next_version|>
"use strict";

module.exports = function getPropertyDescriptor(object, property) {
    var proto = object;
    var descriptor;
    var isOwn = object && Object.getOwnPropertyDescriptor(object, property);

    while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
        proto = Object.getPrototypeOf(proto);
    }

    if (descriptor) {
        descriptor.isOwn = isOwn;
    }

    return descriptor;
};


Add socket echo util function for adminBroadcast

--- server/utils.js
+++ server/utils.js
@@ -27,6 +27,11 @@
   socket.to('admin').emit('action', createSocketObject(channel, payload, metadata));
 };

+function adminBroadcastAndEmit(socket, channel, payload, metadata) {
+  adminBroadcast(socket, channel, payload, metadata);
+  emit(socket, channel, payload, metadata);
+}
+
 let errorCounter = 0;

 const emitError = (socket, error) => {
@@ -46,5 +51,6 @@
   emit,
   broadcastAndEmit,
   adminBroadcast,
+  adminBroadcastAndEmit,
   emitError,
 };

<|original_code|>
const { ERROR } = require('../common/actionTypes/error');

const mergePermanentAndMetadata = (perm, meta) => Object.assign(perm, meta);

const createSocketObject = (channel, payload, metadata) => {
  const obj = mergePermanentAndMetadata({
    type: channel,
  }, metadata);
  obj.data = payload;
  return obj;
};

const broadcast = (socket, channel, payload, metadata) => {
  socket.broadcast.emit('action', createSocketObject(channel, payload, metadata));
};

const emit = (socket, channel, payload, metadata) => {
  socket.emit('action', createSocketObject(channel, payload, metadata));
};

const broadcastAndEmit = (socket, channel, payload, metadata) => {
  broadcast(socket, channel, payload, metadata);
  emit(socket, channel, payload, metadata);
};

const adminBroadcast = (socket, channel, payload, metadata) => {
  socket.to('admin').emit('action', createSocketObject(channel, payload, metadata));
};

let errorCounter = 0;

const emitError = (socket, error) => {
  emit(socket, ERROR, {
    message: error.message,
    id: errorCounter,
  });

  // Hack to produce deterministic snapshots
  if (process.env.NODE_ENV !== 'test') {
    errorCounter += 1;
  }
};

module.exports = {
  broadcast,
  emit,
  broadcastAndEmit,
  adminBroadcast,
  emitError,
};

<|edits_diff|>
--- server/utils.js
+++ server/utils.js
@@ -27,6 +27,11 @@
   socket.to('admin').emit('action', createSocketObject(channel, payload, metadata));
 };

+function adminBroadcastAndEmit(socket, channel, payload, metadata) {
+  adminBroadcast(socket, channel, payload, metadata);
+  emit(socket, channel, payload, metadata);
+}
+
 let errorCounter = 0;

 const emitError = (socket, error) => {
<|current_version|>
const { ERROR } = require('../common/actionTypes/error');

const mergePermanentAndMetadata = (perm, meta) => Object.assign(perm, meta);

const createSocketObject = (channel, payload, metadata) => {
  const obj = mergePermanentAndMetadata({
    type: channel,
  }, metadata);
  obj.data = payload;
  return obj;
};

const broadcast = (socket, channel, payload, metadata) => {
  socket.broadcast.emit('action', createSocketObject(channel, payload, metadata));
};

const emit = (socket, channel, payload, metadata) => {
  socket.emit('action', createSocketObject(channel, payload, metadata));
};

const broadcastAndEmit = (socket, channel, payload, metadata) => {
  broadcast(socket, channel, payload, metadata);
  emit(socket, channel, payload, metadata);
};

const adminBroadcast = (socket, channel, payload, metadata) => {
  socket.to('admin').emit('action', createSocketObject(channel, payload, metadata));
};

function adminBroadcastAndEmit(socket, channel, payload, metadata) {
  adminBroadcast(socket, channel, payload, metadata);
  emit(socket, channel, payload, metadata);
}

let errorCounter = 0;

const emitError = (socket, error) => {
  emit(socket, ERROR, {
    message: error.message,
    id: errorCounter,
  });

  // Hack to produce deterministic snapshots
  if (process.env.NODE_ENV !== 'test') {
    errorCounter += 1;
  }
};

module.exports = {
  broadcast,
  emit,
  broadcastAndEmit,
  adminBroadcast,
  emitError,
};

<|next_version|>
const { ERROR } = require('../common/actionTypes/error');

const mergePermanentAndMetadata = (perm, meta) => Object.assign(perm, meta);

const createSocketObject = (channel, payload, metadata) => {
  const obj = mergePermanentAndMetadata({
    type: channel,
  }, metadata);
  obj.data = payload;
  return obj;
};

const broadcast = (socket, channel, payload, metadata) => {
  socket.broadcast.emit('action', createSocketObject(channel, payload, metadata));
};

const emit = (socket, channel, payload, metadata) => {
  socket.emit('action', createSocketObject(channel, payload, metadata));
};

const broadcastAndEmit = (socket, channel, payload, metadata) => {
  broadcast(socket, channel, payload, metadata);
  emit(socket, channel, payload, metadata);
};

const adminBroadcast = (socket, channel, payload, metadata) => {
  socket.to('admin').emit('action', createSocketObject(channel, payload, metadata));
};

function adminBroadcastAndEmit(socket, channel, payload, metadata) {
  adminBroadcast(socket, channel, payload, metadata);
  emit(socket, channel, payload, metadata);
}

let errorCounter = 0;

const emitError = (socket, error) => {
  emit(socket, ERROR, {
    message: error.message,
    id: errorCounter,
  });

  // Hack to produce deterministic snapshots
  if (process.env.NODE_ENV !== 'test') {
    errorCounter += 1;
  }
};

module.exports = {
  broadcast,
  emit,
  broadcastAndEmit,
  adminBroadcast,
  adminBroadcastAndEmit,
  emitError,
};


test: Make sure env isn't going to troll us before running the test

Some test leaves a node_modules folder in test/tap and that makes
this test fail. =/

--- test/tap/bin.js
+++ test/tap/bin.js
@@ -1,9 +1,15 @@
 var path = require('path')
 var test = require('tap').test
+var rimraf = require('rimraf')
 var common = require('../common-tap.js')
 var opts = { cwd: __dirname }
 var binDir = '../../node_modules/.bin'
 var fixture = path.resolve(__dirname, binDir)
+
+test('setup', function (t) {
+  rimraf.sync(path.join(__dirname, 'node_modules'))
+  t.end()
+})

 test('npm bin', function (t) {
   common.npm(['bin'], opts, function (err, code, stdout, stderr) {

<|original_code|>
var path = require('path')
var test = require('tap').test
var common = require('../common-tap.js')
var opts = { cwd: __dirname }
var binDir = '../../node_modules/.bin'
var fixture = path.resolve(__dirname, binDir)

test('npm bin', function (t) {
  common.npm(['bin'], opts, function (err, code, stdout, stderr) {
    t.ifError(err, 'bin ran without issue')
    t.notOk(stderr, 'should have no stderr')
    t.equal(code, 0, 'exit ok')
    var res = path.resolve(stdout)
    t.equal(res, fixture + '\n')
    t.end()
  })
})

<|edits_diff|>
--- test/tap/bin.js
+++ test/tap/bin.js
@@ -1,5 +1,6 @@
 var path = require('path')
 var test = require('tap').test
+var rimraf = require('rimraf')
 var common = require('../common-tap.js')
 var opts = { cwd: __dirname }
 var binDir = '../../node_modules/.bin'
<|current_version|>
var path = require('path')
var test = require('tap').test
var rimraf = require('rimraf')
var common = require('../common-tap.js')
var opts = { cwd: __dirname }
var binDir = '../../node_modules/.bin'
var fixture = path.resolve(__dirname, binDir)

test('npm bin', function (t) {
  common.npm(['bin'], opts, function (err, code, stdout, stderr) {
    t.ifError(err, 'bin ran without issue')
    t.notOk(stderr, 'should have no stderr')
    t.equal(code, 0, 'exit ok')
    var res = path.resolve(stdout)
    t.equal(res, fixture + '\n')
    t.end()
  })
})

<|next_version|>
var path = require('path')
var test = require('tap').test
var rimraf = require('rimraf')
var common = require('../common-tap.js')
var opts = { cwd: __dirname }
var binDir = '../../node_modules/.bin'
var fixture = path.resolve(__dirname, binDir)

test('setup', function (t) {
  rimraf.sync(path.join(__dirname, 'node_modules'))
  t.end()
})

test('npm bin', function (t) {
  common.npm(['bin'], opts, function (err, code, stdout, stderr) {
    t.ifError(err, 'bin ran without issue')
    t.notOk(stderr, 'should have no stderr')
    t.equal(code, 0, 'exit ok')
    var res = path.resolve(stdout)
    t.equal(res, fixture + '\n')
    t.end()
  })
})


Add the "strict" ESLint rule

Internal: Add the "strict" ESLint rule

Refs. #4

--- .eslintrc.js
+++ .eslintrc.js
@@ -1,3 +1,5 @@
+"use strict";
+
 module.exports = {
   extends: ["google", "plugin:react/all", "./index.js", "./react.js"],
   plugins: ["react", "prettier"],
@@ -6,6 +8,7 @@
     node: true
   },
   rules: {
+    strict: "error",
     "require-jsdoc": "off",
     "prettier/prettier": "error"
   }

<|original_code|>
module.exports = {
  extends: ["google", "plugin:react/all", "./index.js", "./react.js"],
  plugins: ["react", "prettier"],
  env: {
    es6: true,
    node: true
  },
  rules: {
    "require-jsdoc": "off",
    "prettier/prettier": "error"
  }
};

<|edits_diff|>
--- .eslintrc.js
+++ .eslintrc.js
@@ -1,3 +1,5 @@
+"use strict";
+
 module.exports = {
   extends: ["google", "plugin:react/all", "./index.js", "./react.js"],
   plugins: ["react", "prettier"],
<|current_version|>
"use strict";

module.exports = {
  extends: ["google", "plugin:react/all", "./index.js", "./react.js"],
  plugins: ["react", "prettier"],
  env: {
    es6: true,
    node: true
  },
  rules: {
    "require-jsdoc": "off",
    "prettier/prettier": "error"
  }
};

<|next_version|>
"use strict";

module.exports = {
  extends: ["google", "plugin:react/all", "./index.js", "./react.js"],
  plugins: ["react", "prettier"],
  env: {
    es6: true,
    node: true
  },
  rules: {
    strict: "error",
    "require-jsdoc": "off",
    "prettier/prettier": "error"
  }
};


Remove unused code in loose.

Remove unused code in loose.

--- src/lib/propertyMeta.js
+++ src/lib/propertyMeta.js
@@ -1,3 +1,4 @@
+//>>includeStart('strict', pragmas.strict);
 define(['./isImmutable'], function (isImmutable) {

     'use strict';
@@ -39,3 +40,4 @@

     return propertyMeta;
 });
+//>>includeEnd('strict');

<|original_code|>
define(['./isImmutable'], function (isImmutable) {

    'use strict';

    /**
     * Extract meta data from a property.
     *
     * @param {Mixed} prop The property
     * @param {String} name The name of the property
     *
     * @return {Object} An object containg the metadata
     */
    function propertyMeta(prop, name) {
        var ret = {};

        // Is it undefined?
        if (prop === undefined) {
            return null;
        }

        // Analyze visibility
        if (name) {
            if (name.charAt(0) === '_') {
                if (name.charAt(1) === '_') {
                    ret.isPrivate = true;
                } else {
                    ret.isProtected = true;
                }
            } else {
                ret.isPublic = true;
            }
        }

        ret.isImmutable = isImmutable(prop);
        ret.value = prop;

        return ret;
    }

    return propertyMeta;
});
<|edits_diff|>
--- src/lib/propertyMeta.js
+++ src/lib/propertyMeta.js
@@ -39,3 +39,4 @@

     return propertyMeta;
 });
+//>>includeEnd('strict');
<|current_version|>
define(['./isImmutable'], function (isImmutable) {

    'use strict';

    /**
     * Extract meta data from a property.
     *
     * @param {Mixed} prop The property
     * @param {String} name The name of the property
     *
     * @return {Object} An object containg the metadata
     */
    function propertyMeta(prop, name) {
        var ret = {};

        // Is it undefined?
        if (prop === undefined) {
            return null;
        }

        // Analyze visibility
        if (name) {
            if (name.charAt(0) === '_') {
                if (name.charAt(1) === '_') {
                    ret.isPrivate = true;
                } else {
                    ret.isProtected = true;
                }
            } else {
                ret.isPublic = true;
            }
        }

        ret.isImmutable = isImmutable(prop);
        ret.value = prop;

        return ret;
    }

    return propertyMeta;
});
//>>includeEnd('strict');

<|next_version|>
//>>includeStart('strict', pragmas.strict);
define(['./isImmutable'], function (isImmutable) {

    'use strict';

    /**
     * Extract meta data from a property.
     *
     * @param {Mixed} prop The property
     * @param {String} name The name of the property
     *
     * @return {Object} An object containg the metadata
     */
    function propertyMeta(prop, name) {
        var ret = {};

        // Is it undefined?
        if (prop === undefined) {
            return null;
        }

        // Analyze visibility
        if (name) {
            if (name.charAt(0) === '_') {
                if (name.charAt(1) === '_') {
                    ret.isPrivate = true;
                } else {
                    ret.isProtected = true;
                }
            } else {
                ret.isPublic = true;
            }
        }

        ret.isImmutable = isImmutable(prop);
        ret.value = prop;

        return ret;
    }

    return propertyMeta;
});
//>>includeEnd('strict');


CRM-4487: Add handle loaded content to calendar event form view

--- src/Oro/Bundle/CalendarBundle/Resources/public/js/app/views/calendar-event-form-view.js
+++ src/Oro/Bundle/CalendarBundle/Resources/public/js/app/views/calendar-event-form-view.js
@@ -26,8 +26,10 @@

         render: function() {
             var self = this;
+            var renderDeferred = this.renderDeferred = $.Deferred();
             this.initLayout().done(function() {
                 self.handleLayoutInit();
+                renderDeferred.resolve();
             });
         },

<|original_code|>
define([
    'jquery',
    'oroui/js/mediator',
    'oroui/js/app/views/base/view',
    'oroform/js/app/views/datepair-view'
], function($, mediator, BaseView, DatepairView) {
    'use strict';

    var CalendarEventFormView;
    CalendarEventFormView = BaseView.extend({

        /**
         * Options
         */
        options: {},

        /**
         * @constructor
         *
         * @param {Object} options
         */
        initialize: function(options) {
            this.options = options || {};
            this.render();
        },

        render: function() {
            var self = this;
            this.initLayout().done(function() {
                self.handleLayoutInit();
            });
        },

        handleLayoutInit: function() {
            var opts;
            var datepair;
            opts = this.options;
            datepair = new DatepairView(opts);
            this.subview('datepair', datepair);
        }
    });

    return CalendarEventFormView;
});

<|edits_diff|>
--- src/Oro/Bundle/CalendarBundle/Resources/public/js/app/views/calendar-event-form-view.js
+++ src/Oro/Bundle/CalendarBundle/Resources/public/js/app/views/calendar-event-form-view.js
@@ -26,6 +26,7 @@

         render: function() {
             var self = this;
+            var renderDeferred = this.renderDeferred = $.Deferred();
             this.initLayout().done(function() {
                 self.handleLayoutInit();
             });
<|current_version|>
define([
    'jquery',
    'oroui/js/mediator',
    'oroui/js/app/views/base/view',
    'oroform/js/app/views/datepair-view'
], function($, mediator, BaseView, DatepairView) {
    'use strict';

    var CalendarEventFormView;
    CalendarEventFormView = BaseView.extend({

        /**
         * Options
         */
        options: {},

        /**
         * @constructor
         *
         * @param {Object} options
         */
        initialize: function(options) {
            this.options = options || {};
            this.render();
        },

        render: function() {
            var self = this;
            var renderDeferred = this.renderDeferred = $.Deferred();
            this.initLayout().done(function() {
                self.handleLayoutInit();
            });
        },

        handleLayoutInit: function() {
            var opts;
            var datepair;
            opts = this.options;
            datepair = new DatepairView(opts);
            this.subview('datepair', datepair);
        }
    });

    return CalendarEventFormView;
});

<|next_version|>
define([
    'jquery',
    'oroui/js/mediator',
    'oroui/js/app/views/base/view',
    'oroform/js/app/views/datepair-view'
], function($, mediator, BaseView, DatepairView) {
    'use strict';

    var CalendarEventFormView;
    CalendarEventFormView = BaseView.extend({

        /**
         * Options
         */
        options: {},

        /**
         * @constructor
         *
         * @param {Object} options
         */
        initialize: function(options) {
            this.options = options || {};
            this.render();
        },

        render: function() {
            var self = this;
            var renderDeferred = this.renderDeferred = $.Deferred();
            this.initLayout().done(function() {
                self.handleLayoutInit();
                renderDeferred.resolve();
            });
        },

        handleLayoutInit: function() {
            var opts;
            var datepair;
            opts = this.options;
            datepair = new DatepairView(opts);
            this.subview('datepair', datepair);
        }
    });

    return CalendarEventFormView;
});


Add auth reducer to root reducer

Add auth reducer to root reducer

--- src/reducers/index.js
+++ src/reducers/index.js
@@ -1,8 +1,10 @@
 import { combineReducers } from 'redux';
 import runtime from './runtime';
 import intl from './intl';
+import auth from './auth';

 export default combineReducers({
   runtime,
   intl,
+  auth,
 });

<|original_code|>
import { combineReducers } from 'redux';
import runtime from './runtime';
import intl from './intl';

export default combineReducers({
  runtime,
  intl,
});

<|edits_diff|>
--- src/reducers/index.js
+++ src/reducers/index.js
@@ -1,6 +1,7 @@
 import { combineReducers } from 'redux';
 import runtime from './runtime';
 import intl from './intl';
+import auth from './auth';

 export default combineReducers({
   runtime,
<|current_version|>
import { combineReducers } from 'redux';
import runtime from './runtime';
import intl from './intl';
import auth from './auth';

export default combineReducers({
  runtime,
  intl,
});

<|next_version|>
import { combineReducers } from 'redux';
import runtime from './runtime';
import intl from './intl';
import auth from './auth';

export default combineReducers({
  runtime,
  intl,
  auth,
});