"use strict";

var restify = require('restify');
var async = require('async');
var Anyfetch = require('anyfetch');

module.exports.get = function get(req, res, next) {
  if(!req.query.context) {
    return next(new restify.ConflictError("Missing query parameter"));
  }
  async.waterfall([
    function getDocuments(cb) {
      var params = {
        search: req.query.context,
        render_templates: true,
        sort: "-modificationDate",
        strict: true,
        fields: "data",
      };

      if(req.query.limit) {
        params.limit = req.query.limit;
      }

      var anyfetchClient = new Anyfetch(req.accessToken.token);
      anyfetchClient.getDocuments(params, cb);
    },
    function remapDocuments(documentsRes, cb) {
      res.set("Cache-Control", "max-age=3600");
      res.send(200, documentsRes.body.data.map(function mapDocuments(document) {
        return {
          documentId: document.id,
          typeId: document.document_type.id,
          providerId: document.provider.client.id,
          date: document.modification_date,
          snippet: document.rendered_snippet,
          title: document.rendered_title
        };
      }));
      cb();
    }
  ], next);
};

"use strict";

var restify = require('restify');
var async = require('async');
var Anyfetch = require('anyfetch');

module.exports.get = function get(req, res, next) {
  if(!req.query.context) {
    return next(new restify.ConflictError("Missing query parameter"));
  }
  async.waterfall([
    function getDocuments(cb) {
      var params = {
        search: req.query.context,
        render_templates: true,
        sort: "-modificationDate",
        strict: true,
        fields: "data",
      };

      if(req.query.limit) {
        params.limit = req.query.limit;
      }

      var anyfetchClient = new Anyfetch(req.accessToken.token);
      anyfetchClient.getDocuments(params, cb);
    },
    function remapDocuments(documentsRes, cb) {
      res.set("Cache-Control", "max-age=3600");
      res.send(200, documentsRes.body.data.map(function mapDocuments(document) {
        return {
          documentId: document.id,
          typeId: document.document_type.id,
          providerId: document.provider.client ? document.provider.client.id : null,
          date: document.modification_date,
          snippet: document.rendered_snippet,
          title: document.rendered_title
        };
      }));
      cb();
    }
  ], next);
};

Handle null case for client id


import React from 'react';
import Notebook from './components/notebook';

import * as commutable from 'commutable';
import Immutable from 'immutable';

const NotebookPreview = (props) => {
  const nb = props.notebook;
  const notebook = Immutable.Map.isMap(nb) ? nb : commutable.fromJS(nb);
  return <Notebook notebook={notebook} />;
};

NotebookPreview.propTypes = {
  notebook: React.PropTypes.any,
};

export default NotebookPreview;

import React from 'react';
import Notebook from './components/notebook';

import * as commutable from 'commutable';
import Immutable from 'immutable';

const NotebookPreview = (props) => {
  if (props.notebook) {
    const nb = props.notebook;
    const notebook = Immutable.Map.isMap(nb) ? nb : commutable.fromJS(nb);
    return <Notebook notebook={notebook} />;
  } else {
    return <h1>Notebook not provided. </h1>;
  }
};

NotebookPreview.propTypes = {
  notebook: React.PropTypes.any,
};

export default NotebookPreview;

Check if notebook prop is null


import NGN from './ngn.js'
import { register } from './internal.js'

// Register the instance so it can be detected by plugins
register('INSTANCE', NGN)

export const {
  EventEmitter,
  Middleware,
  Exception,
  Class,
  version,
  OS,
  nodelike,
  platform,
  platformVersion,
  runtime,
  runtimeVersion,
  WARN_EVENT,
  INFO_EVENT,
  ERROR_EVENT,
  INTERNAL_EVENT,
  WARN,
  INFO,
  ERROR,
  INTERNAL,
  wrapClass,
  deprecateClass,
  wrap,
  deprecate,
  stack,
  defineException,
  BUS,
  LEDGER,
  Relationship,
  Relationships,
  plugins
} = NGN

export { NGN as default, NGN }

import NGN from './ngn.js'
import { register } from './internal.js'

// Register the instance so it can be detected by plugins
register('INSTANCE', NGN)

export const {
  BaseEventEmitter,
  EventEmitter,
  Middleware,
  Exception,
  Class,
  version,
  OS,
  nodelike,
  platform,
  platformVersion,
  runtime,
  runtimeVersion,
  WARN_EVENT,
  INFO_EVENT,
  ERROR_EVENT,
  INTERNAL_EVENT,
  WARN,
  INFO,
  ERROR,
  INTERNAL,
  wrapClass,
  deprecateClass,
  wrap,
  deprecate,
  stack,
  defineException,
  BUS,
  LEDGER,
  Relationship,
  Relationships,
  plugins
} = NGN

export { NGN as default, NGN }

Add Basic Event Emitter export


import express from 'express';
import leagueTips from 'league-tooltips';
import runTask from './cronTask';
import taskGenerator from './cronTasks/generator';
import config from './config';
import routes from './routes';

// ==== Server ====

const app = express();

app.use(leagueTips(config.key.riot, 'euw', {
  url: '/tooltips',
  fileName: 'league-tips.min.js',
  protocol: 'https',
  cors: {
    origin: 'lol-item-sets-generator.org',
    methods: 'GET',
    headers: 'Content-Type'
  }
}));

app.use('/sprites', routes.sprites);
app.use('/tooltips', routes.tooltips);
app.use('/', routes.index);

app.listen(config.port, () => {
  console.log('[SERVER] Listening on port ' + config.port);
});

// ==== Generator ====

const version = require('../package.json').version;
console.log(`[GENERATOR] Generator version : ${version}.`);

runTask(taskGenerator, config.cron);

import express from 'express';
import leagueTips from 'league-tooltips';
import runTask from './cronTask';
import taskGenerator from './cronTasks/generator';
import config from './config';
import routes from './routes';

// ==== Server ====

const app = express();

app.use(leagueTips(config.key.riot, 'euw', {
  url: '/tooltips',
  fileName: 'league-tips.min.js',
  protocol: 'https',
  cors: {
    origin: 'https://lol-item-sets-generator.org/',
    methods: 'GET',
    headers: 'Content-Type'
  }
}));

app.use('/sprites', routes.sprites);
app.use('/tooltips', routes.tooltips);
app.use('/', routes.index);

app.listen(config.port, () => {
  console.log('[SERVER] Listening on port ' + config.port);
});

// ==== Generator ====

const version = require('../package.json').version;
console.log(`[GENERATOR] Generator version : ${version}.`);

runTask(taskGenerator, config.cron);

Fix https origin in CORS.


import React , { Component , PropTypes }from 'react';
import { Provider } from 'react-redux';
import createStore from './store/create';
import NotificationCenter from './component/notification-center';
import {extendConfig} from './config';
import metadata from '../package.json';
import DevTools from './container/dev-tools';
//Import sass files
import './component/style';

const store = createStore();

class SmartNotificationCenter extends Component {
    componentWillMount() {
        const {config} = this.props;
        console.log('SMART PROPS',this.props)
        extendConfig(config);
    }
    render() {
        return <Provider store={store}>
<NotificationCenter hasAddNotif={false} onSingleClick={this.props.onSingleClick} /><DevTools/>
</Provider>
    }
}
SmartNotificationCenter.displayName = SmartNotificationCenter;
SmartNotificationCenter.propTypes = {
    config: PropTypes.object
};
SmartNotificationCenter.VERSION = metadata.version;
export default SmartNotificationCenter;
export const VERSION = metadata.version;

import React , { Component , PropTypes }from 'react';
import { Provider } from 'react-redux';
import createStore from './store/create';
import NotificationCenter from './component/notification-center';
import {extendConfig} from './config';
import DevTools from './container/dev-tools';
const metadata = require(`${__PACKAGE_JSON_PATH__}/package.json`);
//Import sass files
import './component/style';

const notificationStore = createStore();

function NotificationCenterDev({onSingleClick, store}){
  return <Provider store={store}>
<NotificationCenter hasAddNotif={false} onSingleClick={onSingleClick} /><DevTools/>
</Provider>;
}
NotificationCenterDev.displayName = 'NotificationCenterDev';

function NotificationCenterProd({onSingleClick, store}){
  return <Provider store={store}><NotificationCenter hasAddNotif={false} onSingleClick={onSingleClick} /></Provider>;
}
NotificationCenterProd.displayName = 'NotificationCenterProd';

class SmartNotificationCenter extends Component {
    componentWillMount() {
        const {config} = this.props;
        console.log('SMART PROPS',this.props)
        extendConfig(config);
    }
    render() {
        const NotificationCenterComponent =  !__DEV__ ?  NotificationCenterProd : NotificationCenterDev;
        return <NotificationCenterComponent onSingleClick={this.props.onSingleClick} store={notificationStore} />
    }
}
SmartNotificationCenter.displayName = SmartNotificationCenter;
SmartNotificationCenter.propTypes = {
    config: PropTypes.object
};
SmartNotificationCenter.VERSION = metadata.version;
export default SmartNotificationCenter;
export const VERSION = metadata.version;

Add dev and porod mode.


import { AST_Node, Compressor, TreeWalker } from 'uglify-js';

var compressor = Compressor();

class LocationFixer extends TreeWalker {
	constructor(path) {
		var filename = path.hub.file.opts.filenameRelative;
		super(node => {
			node.start.file = node.end.file = filename;
		});
	}
}

export default ({ Plugin, types: t }) => new Plugin('uglify', {
	visitor: {
		Program(ast) {
			// Convert to UglifyJS AST
			var uAST = AST_Node.from_mozilla_ast(ast);

			// Fix locations (Babel doesn't insert `loc.source` into nodes for some reason)
			uAST.walk(new LocationFixer(this));

			// Compress
			uAST.figure_out_scope();
			uAST = uAST.transform(compressor);

			// Mangle names
			uAST.figure_out_scope();
			uAST.compute_char_frequency();
			uAST.mangle_names();

			// Convert back to ESTree AST
			return uAST.to_mozilla_ast();
		}
	}
});

import { AST_Node, Compressor, TreeWalker } from 'uglify-js';

var compressor = Compressor();

class LocationFixer extends TreeWalker {
	constructor(path) {
		var filename = path.hub.file.opts.filenameRelative;
		super(node => {
			node.start.file = node.end.file = filename;
		});
	}
}

export default ({ types: t }) => ({
	visitor: {
		Program(ast) {
			// Convert to UglifyJS AST
			var uAST = AST_Node.from_mozilla_ast(ast);

			// Fix locations (Babel doesn't insert `loc.source` into nodes for some reason)
			uAST.walk(new LocationFixer(this));

			// Compress
			uAST.figure_out_scope();
			uAST = uAST.transform(compressor);

			// Mangle names
			uAST.figure_out_scope();
			uAST.compute_char_frequency();
			uAST.mangle_names();

			// Convert back to ESTree AST
			return uAST.to_mozilla_ast();
		}
	}
});

Return a plain object to support Babel 6


import 'regenerator-runtime/runtime';
import KinveyProvider from './provider';
import { NetworkRack } from 'kinvey-javascript-sdk-core/es5/rack/rack';
import { HttpMiddleware } from 'kinvey-javascript-sdk-core/es5/rack/middleware/http';
import { AngularHttpMiddleware } from './http';
import { AngularDevice } from './device';
import { AngularPopup } from './popup';

// Add the Http Middleware to the network rack
const networkRack = NetworkRack.sharedInstance();
networkRack.swap(HttpMiddleware, new AngularHttpMiddleware());

// Expose globals
global.KinveyDevice = AngularDevice;
global.KinveyPopup = AngularPopup;

// Register the SDK as a provider
const ngKinvey = angular.module('kinvey', []);
ngKinvey.provider('$kinvey', KinveyProvider);

Include the regenerator-runtime in the build


var test = require('tape');
var toDo = require('../libs/to-do-handler');

test('shouldGetToDoListForUsername', function(t) {
  t.plan(2);

  toDo.getToDoListForUsername('bhish',
    function(result) {
      var parsedToDo = result;
      var expected = [
        ['Make to-do app', 'A to-do application should be made for doing fun to-do type doing stuff. And it should be done before xmas!', '20151224'],
        ['Admire to-do app', 'And then he read his to-dos, and, behold, it was very good.', '20151225']
      ];
      t.deepEqual(parsedToDo, expected);
    });

  toDo.getToDoListForUsername('bart',
    function(result) {
      var parsedToDo = result;
      var expected = [
        ['FLAnnoy Homer', 'Annoy him really badly', '20160101'],
        ['Laugh at Milhouse', 'Because, why not?', '20160101']
      ];
      t.deepEqual(parsedToDo, expected);
    });

});

var test = require('tape');
var toDo = require('../libs/to-do-handler');

test('shouldGetToDoListForUsername', function(t) {
  t.plan(2);

  toDo.getToDoListForUsername('bhish',
    function(result) {
      var parsedToDo = result;
      var expected = [
        ['Make to-do app', 'A to-do application should be made for doing fun to-do type doing stuff. And it should be done before xmas!', '20151224'],
        ['Admire to-do app', 'And then he read his to-dos, and, behold, it was very good.', '20151225']
      ];
      t.deepEqual(parsedToDo, expected);
    });

  toDo.getToDoListForUsername('bart',
    function(result) {
      var parsedToDo = result;
      var expected = [
        ['Annoy Homer', 'Annoy him really badly', '20160101'],
        ['Laugh at Milhouse', 'Because, why not?', '20160101']
      ];
      t.deepEqual(parsedToDo, expected);
    });

});

Revert "Breaking change to test Travis"


import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import createBrowserHistory from 'history/lib/createBrowserHistory'
import { compose, createStore, applyMiddleware } from 'redux'
import { reduxReactRouter, routerStateReducer } from 'redux-router'
import { analytics, uploader, requester } from './middleware'
import { autoRehydrate } from 'redux-persist'
import routes from './routes'
import * as reducers from './reducers'

const logger = createLogger({ collapsed: true })
function reducer(state = {}, action) {
  return {
    json: reducers.json(state.json, action, state.router),
    devtools: reducers.devtools(state.devtools, action),
    modals: reducers.modals(state.modals, action),
    profile: reducers.profile(state.profile, action),
    router: routerStateReducer(state.router, action),
    stream: reducers.stream(state.stream, action),
  }
}
const store = compose(
  autoRehydrate(),
  applyMiddleware(thunk, uploader, requester, analytics, logger),
  reduxReactRouter({routes: routes, createHistory: createBrowserHistory})
)(createStore)(reducer)

export default store

import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import createBrowserHistory from 'history/lib/createBrowserHistory'
import { compose, createStore, applyMiddleware } from 'redux'
import { reduxReactRouter, routerStateReducer } from 'redux-router'
import { analytics, uploader, requester } from './middleware'
import { autoRehydrate } from 'redux-persist'
import routes from './routes'
import * as reducers from './reducers'

const logger = createLogger({ collapsed: true })
function reducer(state = {}, action) {
  if (!state && window.__INITIAL_STATE__) { return window.__INITIAL_STATE__ }
  return {
    json: reducers.json(state.json, action, state.router),
    devtools: reducers.devtools(state.devtools, action),
    modals: reducers.modals(state.modals, action),
    profile: reducers.profile(state.profile, action),
    router: routerStateReducer(state.router, action),
    stream: reducers.stream(state.stream, action),
  }
}
const store = compose(
  autoRehydrate(),
  applyMiddleware(thunk, uploader, requester, analytics, logger),
  reduxReactRouter({routes: routes, createHistory: createBrowserHistory})
)(createStore)(reducer)

export default store

Return initial state when stat is undefined.


'use strict';
const childProcess = require('child_process');
const dargs = require('dargs');
const resolveCwd = require('resolve-cwd');

const BIN = require.resolve('ava/cli.js');

module.exports = grunt => {
	grunt.registerMultiTask('ava', 'Run AVA tests', function () {
		const cb = this.async();
		const opts = this.options();
		const args = [BIN].concat(this.filesSrc, '--color', dargs(opts, {excludes: ['nyc']}));

		if (opts.nyc) {
			const nycBin = resolveCwd('nyc/bin/nyc.js');

			if (nycBin) {
				args.unshift(nycBin);
			} else {
				grunt.warn('Couldn\'t find the `nyc` binary');
				cb();
				return;
			}
		}

		childProcess.execFile(process.execPath, args, (err, stdout, stderr) => {
			if (err) {
				grunt.warn(stderr || stdout || err);
				cb();
				return;
			}

			grunt.log.write(stderr + stdout);
			cb();
		});
	});
};

'use strict';
const childProcess = require('child_process');
const dargs = require('dargs');
const resolveCwd = require('resolve-cwd');

const BIN = require.resolve('ava/cli.js');
const HUNDRED_MEGABYTES = 1000 * 1000 * 100;

module.exports = grunt => {
	grunt.registerMultiTask('ava', 'Run AVA tests', function () {
		const cb = this.async();
		const opts = this.options();
		const args = [BIN].concat(this.filesSrc, '--color', dargs(opts, {excludes: ['nyc']}));

		if (opts.nyc) {
			const nycBin = resolveCwd('nyc/bin/nyc.js');

			if (nycBin) {
				args.unshift(nycBin);
			} else {
				grunt.warn('Couldn\'t find the `nyc` binary');
				cb();
				return;
			}
		}

		childProcess.execFile(process.execPath, args, {
			maxBuffer: HUNDRED_MEGABYTES
		}, (err, stdout, stderr) => {
			if (err) {
				grunt.warn(stderr || stdout || err);
				cb();
				return;
			}

			grunt.log.write(stderr + stdout);
			cb();
		});
	});
};

Increase the max buffer so it never errors on that


import Ember from 'ember';

export default Ember.Controller.extend({
  open: false,

  openClass: Ember.computed('open', function() {
    return this.get('open') ? 'open' : '';
  }),
  session: Ember.inject.service('session'),

  isSign: Ember.computed('session.isAuthenticated', function() {
    return this.get('session.isAuthenticated') ? '' : 'wrapper__no-sign';
  }),

  actions: {
    invalidateSession() {
      this.get('session').invalidate();
    },
    slide() {
      this.toggleProperty('open');
    },
    hideMenu() {
      this.set('open', false);
    }
  }

});

import Ember from 'ember';

export default Ember.Controller.extend({
  session: Ember.inject.service('session'),
  open: false,

  openClass: Ember.computed('open', function() {
    return this.get('open') ? 'open' : '';
  }),

  isSign: Ember.computed('session.isAuthenticated', function() {
    return this.get('session.isAuthenticated') ? '' : 'wrapper__no-sign';
  }),

  actions: {
    invalidateSession() {
      this.get('session').invalidate();
    },
    slide() {
      this.toggleProperty('open');
    },
    hideMenu() {
      this.set('open', false);
    }
  }

});

Move session injection to the top of the app controller


"use strict";
var ConcatSource = require('webpack-sources/lib/ConcatSource');
var fs = require('fs');

class PrependPlugin {
    constructor(args) {
        if (typeof args !== 'object') {
            throw new TypeError('Argument "args" must be an object.');
        }

        this.filePath = args.hasOwnProperty('filePath') ? args.filePath : null;
    }

    apply(compiler) {
        const prependFile = (compilation, fileName) =>
            compilation.assets[fileName] = new ConcatSource(
                fs.readFileSync(this.filePath, 'utf8'),
                compilation.assets[fileName]
            );

        const wrapChunks = (compilation, chunks) =>
            chunks.forEach(chunk => {
                if (chunk.hasRuntime() && chunk.name) {
                    chunk.files.forEach(fileName => prependFile(compilation, fileName));
                }
            });

        if (this.filePath) {
            compiler.plugin('compilation', compilation =>
                compilation.plugin('optimize-chunk-assets', (chunks, done) => {
                    wrapChunks(compilation, chunks);
                    done();
                })
            );
        }
    }
}

module.exports = PrependPlugin;

"use strict";
var ConcatSource = require('webpack-sources/lib/ConcatSource');
var fs = require('fs');

class PrependPlugin {
    constructor(args) {
        if (typeof args !== 'object') {
            throw new TypeError('Argument "args" must be an object.');
        }

        this.filePath = args.hasOwnProperty('filePath') ? args.filePath : null;
    }

    apply(compiler) {
        const prependFile = (compilation, fileName) =>
            compilation.assets[fileName] = new ConcatSource(
                fs.readFileSync(this.filePath, 'utf8'),
                compilation.assets[fileName]
            );

        const wrapChunks = (compilation, chunks) =>
            chunks.forEach(chunk => {
                if (chunk.hasRuntime() && chunk.name) {
                    chunk.files.forEach(fileName => {
                        if (fileName.match(/\.js$/)) {
                            prependFile(compilation, fileName)
                        }
                    });
                }
            });

        if (this.filePath) {
            compiler.plugin('compilation', compilation =>
                compilation.plugin('optimize-chunk-assets', (chunks, done) => {
                    wrapChunks(compilation, chunks);
                    done();
                })
            );
        }
    }
}

module.exports = PrependPlugin;

Check if extension is .js before prepending


'use strict';

var parseConcat = require('..');

var stread = require('stread');

it('should concat-stream and JSON.parse', function (done) {
  var data = {
    name: null,
    version: "1.1.1",
    tags: [true, "awesomeness", [{}]]
  };

  stread(JSON.stringify(data, null, 2))
             .pipe(parseConcat(function (err, result) {
               (err == null).should.be.true;
               result.should.eql(data);
               done();
             }));
});

it('should propagate the error', function (done) {
  stread('{')
    .pipe(parseConcat(function (err) {
      err.should.be.an.Error;
      done();
    }));
});

it('should accept custom parsers', function (done) {
  var caps = function (string) {
    return (string.match(/[A-Z]/g) || []).join('');
  };

  stread('   {\nMEdiS]]\n} SorAs    \tGEt')
    .pipe(parseConcat({ parse: caps }, function (err, result) {
      (err == null).should.be.true;
      result.should.equal('MESSAGE');
      done();
    }));
});

'use strict';

var parseConcat = require('..');

var stread = require('stread');

it('should concat-stream and JSON.parse', function (done) {
  var data = {
    name: null,
    version: "1.1.1",
    tags: [true, "awesomeness", [{}]]
  };

  stread(JSON.stringify(data, null, 2))
             .pipe(parseConcat(function (err, result) {
               (err == null).should.be.true;
               result.should.eql(data);
               done();
             }));
});

it('should propagate the error', function (done) {
  stread('{')
    .pipe(parseConcat(function (err) {
      err.should.be.an.Error;
      done();
    }));
});

it('should accept custom parsers', function (done) {
  var caps = function (string) {
    return (string.match(/[A-Z]/g) || []).join('').toLowerCase();
  };

  stread('   {\nMEdiS]]\n} SorAs    \tGEt')
    .pipe(parseConcat({ parse: caps }, function (err, result) {
      (err == null).should.be.true;
      result.should.equal('message');
      done();
    }));
});

Convert hidden message to lower case JFF


"use strict";

function simplePassing() {
  describe('test embedded mocha', function() {
    it('should run jasmine-style tests', function() {
      expect(1)
        .toBe(1);
    });
    it('should run should-style tests', function() {
      should(1).ok;
    });
  });
}

function simpleFailing() {
  describe('test embedded mocha', function() {
    it('should fail', function() {
      expect(1)
        .toBe(2);
    });
  });
}

function getSourceFrom(func) {
  var lines = func.toString().split('\n');
  return lines.slice(1, -1).join('\n');
}

module.exports = {
  simplePassingTestCode: getSourceFrom(simplePassing),
  simpleFailingTestCode: getSourceFrom(simpleFailing)
};

"use strict";

function simplePassing() {
  describe('test embedded mocha', function() {
    it('should run jasmine-style tests', function() {
      expect(1)
        .toBe(1);
    });
    it('should run should-style tests', function() {
      should(1).ok;
    });
  });
}

function simpleFailing() {
  describe('test embedded mocha', function() {
    it('should fail', function() {
      expect(1)
        .toBe(2);
    });
  });
}

// Make sure the code block starts with no indentation.
function _replaceTrailingWhitespaces(lines) {
  var firstLineTrailingSpaces = lines[1].match(/^[\s\t]+/);
  if (firstLineTrailingSpaces) {
    lines = lines.map(function(line) {
      return line.replace(firstLineTrailingSpaces, '');
    });
  }
  return lines;
}

function getSourceFrom(func) {
  var lines = func.toString().split('\n');
  lines = _replaceTrailingWhitespaces(lines);
  return lines.slice(1, -1).join('\n');
}

module.exports = {
  simplePassingTestCode: getSourceFrom(simplePassing),
  simpleFailingTestCode: getSourceFrom(simpleFailing)
};

Replace trailing whitespaces for example code.


#!/usr/bin/env node

var spawn = require('child_process').spawn
var npm = require.resolve('npm/cli')

spawn(npm, process.argv.slice(2), {stdio: 'inherit'})

#!/usr/bin/env node

var spawn = require('child_process').spawn
var npm = require.resolve('npm/cli')

spawn(process.execPath, [npm].concat(process.argv.slice(2)), {stdio: 'inherit'})

Make this works on windows too


var mongoose   = require('mongoose');
var config     = require('config');
var semver     = require('semver');

// configure mongodb
mongoose.connect(config.mongodb.connectionString || 'mongodb://' + config.mongodb.user + ':' + config.mongodb.password + '@' + config.mongodb.server +'/' + config.mongodb.database);
mongoose.connection.on('error', function (err) {
  console.error('MongoDB error: ' + err.message);
  console.error('Make sure a mongoDB server is running and accessible by this application');
  process.exit(1);
});
mongoose.connection.on('open', function (err) {
  mongoose.connection.db.admin().serverStatus(function(err, data) {
    if (err) {
      if (err.name === "MongoError" && err.errmsg === 'need to login') {
        console.log('Forcing MongoDB authentication');
        mongoose.connection.db.authenticate(config.mongodb.user, config.mongodb.password, function(err) {
          if (!err) return;
          console.error(err);
          process.exit(1);
        });
        return;
      } else {
        console.error(err);
        process.exit(1);
      }
    }
    if (!semver.satisfies(data.version, '>=2.1.0')) {
      console.error('Error: Uptime requires MongoDB v2.1 minimum. The current MongoDB server uses only '+ data.version);
      process.exit(1);
    }
  });
});

module.exports = mongoose;

var mongoose   = require('mongoose');
var config     = require('config');
var semver     = require('semver');

// configure mongodb
mongoose.connect(config.mongodb.connectionString || 'mongodb://' + config.mongodb.user + ':' + config.mongodb.password + '@' + config.mongodb.server +'/' + config.mongodb.database);
mongoose.connection.on('error', function (err) {
  console.error('MongoDB error: ' + err.message);
  console.error('Make sure a mongoDB server is running and accessible by this application');
  process.exit(1);
});
mongoose.connection.on('open', function (err) {
  mongoose.connection.db.admin().serverStatus(function(err, data) {
    if (err) {
      if (err.name === "MongoError" && (err.errmsg === 'need to login' || err.errmsg === 'unauthorized')) {
        console.log('Forcing MongoDB authentication');
        mongoose.connection.db.authenticate(config.mongodb.user, config.mongodb.password, function(err) {
          if (!err) return;
          console.error(err);
          process.exit(1);
        });
        return;
      } else {
        console.error(err);
        process.exit(1);
      }
    }
    if (!semver.satisfies(data.version, '>=2.1.0')) {
      console.error('Error: Uptime requires MongoDB v2.1 minimum. The current MongoDB server uses only '+ data.version);
      process.exit(1);
    }
  });
});

module.exports = mongoose;

Add support for MongoDB 2.4.1.


import http from "k6/http";
import { check } from "k6";

export default function() {
    // Passing username and password as part of URL will authenticate using HTTP Basic Auth
    let res = http.get("http://user:passwd@httpbin.org/basic-auth/user/passwd");

    // Verify response
    check(res, {
        "status is 200": (r) => r.status === 200,
        "is authenticated": (r) => r.json().authenticated === true,
        "is correct user": (r) => r.json().user === "user"
    });
}

import encoding from "k6/encoding";
import http from "k6/http";
import { check } from "k6";

export default function() {
    // Passing username and password as part of URL will authenticate using HTTP Basic Auth
    let res = http.get("http://user:passwd@httpbin.org/basic-auth/user/passwd");

    // Verify response
    check(res, {
        "status is 200": (r) => r.status === 200,
        "is authenticated": (r) => r.json().authenticated === true,
        "is correct user": (r) => r.json().user === "user"
    });

    // Alternatively you can create the header yourself to authenticate using HTTP Basic Auth
    res = http.get("http://httpbin.org/basic-auth/user/passwd", { headers: { "Authorization": "Basic " + encoding.b64encode("user:passwd") }});

    // Verify response
    check(res, {
        "status is 200": (r) => r.status === 200,
        "is authenticated": (r) => r.json().authenticated === true,
        "is correct user": (r) => r.json().user === "user"
    });
}

Extend HTTP basic auth example


(function() {
  'use strict';

  angular.module('PDRClient')
      .controller('InviteInventoryUserCtrl', InviteInventoryUserCtrl);

  InviteInventoryUserCtrl.$inject = [
    '$scope',
    '$stateParams',
    'InventoryInvitation'
  ];

  function InviteInventoryUserCtrl($scope, $stateParams, InventoryInvitation) {
    var vm = this;

    vm.sendInvitation = function(invitation) {
      vm.alerts = [];
      vm.addAlert = function(message) {
        vm.alerts.push({type: 'danger', msg: message});
      };

      vm.closeAlert = function(index) {
        vm.alerts.splice(index, 1);
      };

      InventoryInvitation.create({inventory_id: $stateParams.id}, invitation)
          .$promise
          .then(function() {
            $scope.$emit('invite-sent');
          })
          .catch(function(response) {
            var errors = response.data.errors;
            angular.forEach(errors, function(error, field) {
              vm.addAlert(field + " : " + error);
            });
          });
    };
  }
})();

(function() {
  'use strict';

  angular.module('PDRClient')
      .controller('InviteInventoryUserCtrl', InviteInventoryUserCtrl);

  InviteInventoryUserCtrl.$inject = [
    '$scope',
    '$stateParams',
    'InventoryInvitation'
  ];

  function InviteInventoryUserCtrl($scope, $stateParams, InventoryInvitation) {
    var vm = this;

    vm.sendInvitation = function(invitation) {
      vm.alerts = [];
      vm.addAlert = function(message) {
        vm.alerts.push({type: 'danger', msg: message});
      };

      vm.closeAlert = function(index) {
        vm.alerts.splice(index, 1);
      };

      InventoryInvitation.create({inventory_id: $stateParams.id}, invitation)
          .$promise
          .then(function() {
            $scope.$emit('invite-sent');
            $scope.$emit('update_participants');
          })
          .catch(function(response) {
            var errors = response.data.errors;
            angular.forEach(errors, function(error, field) {
              vm.addAlert(field + " : " + error);
            });
          });
    };
  }
})();

Enable auto-refresh when inviting a participant to an inventory


'use strict';

var BowerAdapter = require('../dependency-manager-adapters/bower');
var NpmAdapter = require('../dependency-manager-adapters/npm');

module.exports = {
  generateFromConfig: function(config, root) {
    var hasNpm = false;
    var hasBower = false;
    var adapters = [];
    if (!config || !config.scenarios) {
      return [];
    }

    config.scenarios.forEach(function(scenario) {
      if (scenario.npm) {
        hasNpm = true;
      }
      if (scenario.bower || scenario.dependencies || scenario.devDependencies) {
        hasBower = true;
      }
    });
    if (hasNpm) {
      adapters.push(new NpmAdapter({ cwd: root, managerOptions: config.npmOptions }));
    }
    if (hasBower) {
      adapters.push(new BowerAdapter({ cwd: root, managerOptions: config.bowerOptions }));
    }
    return adapters;
  }
};

'use strict';

var BowerAdapter = require('../dependency-manager-adapters/bower');
var NpmAdapter = require('../dependency-manager-adapters/npm');

module.exports = {
  generateFromConfig: function(config, root) {
    var hasNpm = false;
    var hasBower = false;
    var adapters = [];
    if (!config || !config.scenarios) {
      return [];
    }

    config.scenarios.forEach(function(scenario) {
      if (scenario.npm) {
        hasNpm = true;
      }
      if (scenario.bower || scenario.dependencies || scenario.devDependencies) {
        hasBower = true;
      }
    });
    if (hasNpm) {
      adapters.push(new NpmAdapter({ cwd: root, managerOptions: config.npmOptions, useYarnCommand: config.useYarn }));
    }
    if (hasBower) {
      adapters.push(new BowerAdapter({ cwd: root, managerOptions: config.bowerOptions }));
    }
    return adapters;
  }
};

Add useYarn to npm adapter initialisation


import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import CounterApp from './App';

export default class Root extends Component {
  static propTypes = {
    store: PropTypes.object.isRequired
  };

  render() {
    const { store } = this.props;
    return (
      <Provider store={store}>
        <CounterApp />
      </Provider>
    );
  }
}

import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import App from './App';

export default class Root extends Component {
  static propTypes = {
    store: PropTypes.object.isRequired
  };

  render() {
    const { store } = this.props;
    return (
      <Provider store={store}>
        <App />
      </Provider>
    );
  }
}

Rename container to App to be easer to extend the boilerplate


import webpack from '../webpack';

export default {
    description: `
    # roc-plugin-typescript
    A roc plugin for compiling typescript (*.ts and *.tsx) files. It uses
    [ts-loader](https://github.com/TypeStrong/ts-loader) for to let webpack compile
    typescript files and adds source maps via
    [source-map-loader](https://github.com/webpack/source-map-loader).

    ## How to use?
    Add the plugin as a dev dependency of your [roc](http://www.getroc.org) application:
    \`\`\`
    npm install --save-dev roc-plugin-typescript
    \`\`\`

    The plugin will automatically hook into webpacks build process and add a loader
    for *.ts and *.tsx files. The compiler will look for a \`tsconfig.json\` file in
    the root of you roc project, which you can use for configuration.
    `,
    actions: [{
        hook: 'build-webpack',
        description: 'Adds typescript support to Webpack.',
        action: webpack,
    }],
    required: {
        'roc-package-webpack': '^1.0.0-beta.1',
    },
};

import { lazyFunctionRequire } from 'roc';

const lazyRequire = lazyFunctionRequire(require);

export default {
    description: `
    # roc-plugin-typescript
    A roc plugin for compiling typescript (*.ts and *.tsx) files. It uses
    [ts-loader](https://github.com/TypeStrong/ts-loader) for to let webpack compile
    typescript files and adds source maps via
    [source-map-loader](https://github.com/webpack/source-map-loader).

    ## How to use?
    Add the plugin as a dev dependency of your [roc](http://www.getroc.org) application:
    \`\`\`
    npm install --save-dev roc-plugin-typescript
    \`\`\`

    The plugin will automatically hook into webpacks build process and add a loader
    for *.ts and *.tsx files. The compiler will look for a \`tsconfig.json\` file in
    the root of you roc project, which you can use for configuration.
    `,
    actions: [{
        hook: 'build-webpack',
        description: 'Adds typescript support to Webpack.',
        action: lazyRequire('../webpack'),
    }],
    required: {
        'roc-package-webpack': '^1.0.0-beta.1',
    },
};

Use lazyFunctionRequire for improved import performance.


import config from '../config/environment';
import {
  inject as service
} from '@ember/service';
import AuthenticateRoute from 'wholetale/routes/authenticate';

export default AuthenticateRoute.extend({
  internalState: service(),
  model: function (params) {
    // console.log("Called Authenticate, proceeding in Application");
    let router = this;
    return router._super(...arguments)
      .then(_ => {
        let user = router.get('userAuth').getCurrentUser();
        return user;
      });
  },
  setupController: function (controller, model) {
    this._super(controller, model);

    if (model) {
      controller.set('loggedIn', true);
      controller.set('user', model);
      controller.set('gravatarUrl', config.apiUrl + "/user/" + model.get('_id') + "/gravatar?size=64");
      this.store.findAll('job', {
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }).then(jobs => {
        controller.set('jobs', jobs);
        controller.set('isLoadingJobs', false);
      });
    }
  },
  actions: {
    toRoute() {
      this.transitionTo.call(this, ...arguments);
      return true;
    },

    showModal(modalDialogName, modalContext) {
        const applicationController = this.controller;

        Ember.setProperties(applicationController, {
          modalDialogName,
          modalContext,
          isModalVisible: true
        });
      },

    closeModal() {
        debugger;
        const applicationController = this.controller;
        Ember.set(applicationController, 'isModalVisible', false);
      }
  }
});

import config from '../config/environment';
import {
  inject as service
} from '@ember/service';
import AuthenticateRoute from 'wholetale/routes/authenticate';

export default AuthenticateRoute.extend({
  internalState: service(),
  model: function (params) {
    // console.log("Called Authenticate, proceeding in Application");
    let router = this;
    return router._super(...arguments)
      .then(_ => {
        let user = router.get('userAuth').getCurrentUser();
        return user;
      });
  },
  setupController: function (controller, model) {
    this._super(controller, model);

    if (model) {
      controller.set('loggedIn', true);
      controller.set('user', model);
      controller.set('gravatarUrl', config.apiUrl + "/user/" + model.get('_id') + "/gravatar?size=64");
      this.store.findAll('job', {
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }).then(jobs => {
        controller.set('jobs', jobs);
        controller.set('isLoadingJobs', false);
      });
    }
  },
  actions: {
    toRoute() {
      this.transitionTo.call(this, ...arguments);
      return true;
    },

    showModal(modalDialogName, modalContext) {
        const applicationController = this.controller;

        Ember.setProperties(applicationController, {
          modalDialogName,
          modalContext,
          isModalVisible: true
        });
      },

    closeModal() {
        const applicationController = this.controller;
        Ember.set(applicationController, 'isModalVisible', false);
      }
  }
});

Remove Debugger Statement From Route


/*!
 * thought <https://github.com/nknapp/thought>
 *
 * Copyright (c) 2015 Nils Knappmeier.
 * Released under the MIT license.
 */

'use strict'

var path = require('path')

/**
 *
 * Create a spec that can be loaded with `customize` using the `load()` function.
 *
 * @param {String} workingDir the working directory of thought
 * @returns {Function} the Customize-Spec
 */
module.exports = function createSpec (workingDir) {
  return function thoughtSpec (customize) {
    return customize
      .registerEngine('handlebars', require('customize-engine-handlebars'))
      .merge({
        handlebars: {
          partials: path.join(__dirname, 'handlebars', 'partials'),
          templates: path.join(__dirname, 'handlebars', 'templates'),
          helpers: require.resolve('./handlebars/helpers.js'),
          data: {
            'package': require(path.resolve('package.json')),
            'workingDir': workingDir
          },
          preprocessor: require('./handlebars/preprocessor.js')
        }
      })
      .merge({
        handlebars: {
          partials: path.join(workingDir, '.thought', 'partials'),
          templates: path.join(workingDir, '.thought', 'templates'),
          helpers: path.join(workingDir, '.thought', 'handlebars-helpers,js')
        }
      })
      // .tap(console.log)

  }
}

/*!
 * thought <https://github.com/nknapp/thought>
 *
 * Copyright (c) 2015 Nils Knappmeier.
 * Released under the MIT license.
 */

'use strict'

var path = require('path')

/**
 *
 * Create a spec that can be loaded with `customize` using the `load()` function.
 *
 * @param {String} workingDir the working directory of thought
 * @returns {Function} the Customize-Spec
 */
module.exports = function createSpec (workingDir) {
  return function thoughtSpec (customize) {
    return customize
      .registerEngine('handlebars', require('customize-engine-handlebars'))
      .merge({
        handlebars: {
          partials: path.join(__dirname, 'handlebars', 'partials'),
          templates: path.join(__dirname, 'handlebars', 'templates'),
          helpers: require.resolve('./handlebars/helpers.js'),
          data: {
            'package': require(path.resolve('package.json')),
            'workingDir': workingDir
          },
          preprocessor: require('./handlebars/preprocessor.js')
        }
      })
      .merge({
        handlebars: {
          partials: path.join(workingDir, '.thought', 'partials'),
          templates: path.join(workingDir, '.thought', 'templates'),
          helpers: path.resolve(workingDir, '.thought', 'hb-helpers,js'),
          preprocessor: path.resolve(workingDir, '.thought','hb-preprocessor.js')
        }
      })
      // .tap(console.log)

  }
}

Load custom preprocessor from ".thought/hb-preprocessor.js" change name of custom helper file to ".thought/hb-helpers.js"


(function(root) {

  var McasScaledChart = function initializeMcasScaledChart (series) {
    this.title = 'MCAS score';
    this.series = series;
  };

  McasScaledChart.fromChartData = function mcasScaledChartFromChartData(chartData) {
    var datums = [];
    var math_scaled_data = chartData.data('mcas-series-math-scaled');
    var ela_scaled_data = chartData.data('mcas-series-ela-scaled')

    if (math_scaled_data !== null) {
      var math_scaled = new ProfileChartData("Math scale score", math_scaled_data).toDateChart();
      datums.push(math_scaled);
    }

    if (ela_scaled_data !== null) {
      var ela_scaled = new ProfileChartData("English scale score", ela_scaled_data).toDateChart();
      datums.push(math_scaled);
    }
    return new McasScaledChart(datums);
  };

  McasScaledChart.prototype.toHighChart = function mcasChartToHighChart () {
    return $.extend({}, ChartSettings.base_options, {
      xAxis: ChartSettings.x_axis_datetime,
      yAxis: ChartSettings.default_yaxis,
      series: this.series
    });
  };

  McasScaledChart.prototype.render = function renderMcasScaledChart (controller) {
    controller.renderChartOrEmptyView(this);
  };

  root.McasScaledChart = McasScaledChart;

})(window)

(function(root) {

  var McasScaledChart = function initializeMcasScaledChart (series) {
    this.title = 'MCAS score';
    this.series = series;
  };

  McasScaledChart.fromChartData = function mcasScaledChartFromChartData(chartData) {
    var datums = [];
    var math_scaled_data = chartData.data('mcas-series-math-scaled');
    var ela_scaled_data = chartData.data('mcas-series-ela-scaled')

    if (math_scaled_data !== null) {
      var math_scaled = new ProfileChartData("Math scale score", math_scaled_data).toDateChart();
      datums.push(math_scaled);
    }

    if (ela_scaled_data !== null) {
      var ela_scaled = new ProfileChartData("English scale score", ela_scaled_data).toDateChart();
      datums.push(ela_scaled);
    }
    return new McasScaledChart(datums);
  };

  McasScaledChart.prototype.toHighChart = function mcasChartToHighChart () {
    return $.extend({}, ChartSettings.base_options, {
      xAxis: ChartSettings.x_axis_datetime,
      yAxis: ChartSettings.default_yaxis,
      series: this.series
    });
  };

  McasScaledChart.prototype.render = function renderMcasScaledChart (controller) {
    controller.renderChartOrEmptyView(this);
  };

  root.McasScaledChart = McasScaledChart;

})(window)

Fix chart js copy/paste error


import CSVReader from 'readers/csv/csv';
import { isNumber } from 'base/utils';

const CSVTimeInColumnsReader = CSVReader.extend({

  _name: 'csv-time_in_columns',

  init(readerInfo) {
    this._super(readerInfo);
  },

  load() {
    return this._super()
      .then(({ data, columns }) => {
        const indicatorKey = columns[this.keySize];

        const concepts = data.reduce((result, row) => {
          Object.keys(row).forEach((concept) => {
            concept = concept === indicatorKey ? row[indicatorKey] : concept;

            if (Number(concept) != concept && !result.includes(concept)) {
              result.push(concept);
            }
          });

          return result;
        }, []).concat('time');

        const indicators = concepts.slice(1, -1);
        const [entityDomain] = concepts;
        return data.reduce((result, row) => {
          Object.keys(row).forEach((key) => {
            if (![entityDomain, indicatorKey].includes(key)) {
              result.push(
                Object.assign({
                    [entityDomain]: row[entityDomain],
                    time: key,
                  }, indicators.reduce((result, indicator) => {
                    result[indicator] = row[indicatorKey] === indicator ? row[key] : null;
                    return result;
                  }, {})
                )
              );
            }
          });

          return result;
        }, []);
      });
  }

});

export default CSVTimeInColumnsReader;

import CSVReader from 'readers/csv/csv';
import { isNumber } from 'base/utils';

const CSVTimeInColumnsReader = CSVReader.extend({

  _name: 'csv-time_in_columns',

  init(readerInfo) {
    this._super(readerInfo);
  },

  load() {
    return this._super()
      .then(({ data, columns }) => {
        const indicatorKey = columns[this.keySize];

        let concepts = data.reduce((result, row) => {
          Object.keys(row).forEach((concept) => {
            concept = concept === indicatorKey ? row[indicatorKey] : concept;

            if (Number(concept) != concept && !result.includes(concept)) {
              result.push(concept);
            }
          });

          return result;
        }, []);
        concepts.splice(1, 0, 'time');

        const indicators = concepts.slice(2);
        const [entityDomain] = concepts;
        return {
          columns: concepts,
          data: data.reduce((result, row) => {
            Object.keys(row).forEach((key) => {
              if (![entityDomain, indicatorKey].includes(key)) {
                result.push(
                  Object.assign({
                      [entityDomain]: row[entityDomain],
                      time: key,
                    }, indicators.reduce((result, indicator) => {
                      result[indicator] = row[indicatorKey] === indicator ? row[key] : null;
                      return result;
                    }, {})
                  )
                );
              }
            });

            return result;
          }, [])
        };
      });
  }

});

export default CSVTimeInColumnsReader;

Fix load method response for csv time in columns reader


#!/usr/bin/env node

var repl = require('repl');
var util = require('util');
var program = require('commander');
var protocol = require('../lib/protocol.json');
var Chrome = require('../');

program
    .option('-h, --host <host>', 'Remote Debugging Protocol host')
    .option('-p, --port <port>', 'Remote Debugging Protocol port')
    .parse(process.argv);

var options = {
    'host': program.host,
    'port': program.port
};

Chrome(options, function (chrome) {
    var chromeRepl = repl.start({
        'prompt': 'chrome> ',
        'ignoreUndefined': true,
        'writer': function (object) {
            return util.inspect(object, {
                'colors': true,
                'depth': null
            });
        }
    });

    // disconnect on exit
    chromeRepl.on('exit', function () {
        chrome.close();
    });

    // add protocol API
    for (var domainIdx in protocol.domains) {
        var domainName = protocol.domains[domainIdx].domain;
        chromeRepl.context[domainName] = chrome[domainName];
    }
}).on('error', function () {
    console.error('Cannot connect to Chrome');
});

#!/usr/bin/env node

var repl = require('repl');
var util = require('util');
var program = require('commander');
var protocol = require('../lib/protocol.json');
var Chrome = require('../');

program
    .option('-t, --host <host>', 'Remote Debugging Protocol host')
    .option('-p, --port <port>', 'Remote Debugging Protocol port')
    .parse(process.argv);

var options = {
    'host': program.host,
    'port': program.port
};

Chrome(options, function (chrome) {
    var chromeRepl = repl.start({
        'prompt': 'chrome> ',
        'ignoreUndefined': true,
        'writer': function (object) {
            return util.inspect(object, {
                'colors': true,
                'depth': null
            });
        }
    });

    // disconnect on exit
    chromeRepl.on('exit', function () {
        chrome.close();
    });

    // add protocol API
    for (var domainIdx in protocol.domains) {
        var domainName = protocol.domains[domainIdx].domain;
        chromeRepl.context[domainName] = chrome[domainName];
    }
}).on('error', function () {
    console.error('Cannot connect to Chrome');
});

Change the flag name for the host option in the REPL


/**
 * First we will load all of this project's JavaScript dependencies which
 * include Vue and Vue Resource. This gives a great starting point for
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the body of the page. From here, you may begin adding components to
 * the application, or feel free to tweak this setup for your needs.
 */

Vue.component('example', require('./components/Example.vue'));

var app = new Vue({
    el: 'body'
});

/**
 * First we will load all of this project's JavaScript dependencies which
 * include Vue and Vue Resource. This gives a great starting point for
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the body of the page. From here, you may begin adding components to
 * the application, or feel free to tweak this setup for your needs.
 */

Vue.component('example', require('./components/Example.vue'));

const app = new Vue({
    el: 'body'
});

Use const instead of var in Vue instance


'use strict';
angular.module('arethusa.core').constant('CONF_ROUTE', {
  controller: 'ConfEditorCtrl',
  templateUrl: 'templates/conf_editor.html',
  resolve: {
    load: function ($http, configurator) {
      var url = './static/configs/conf_editor/1.json';
      return $http.get(url).then(function (res) {
        configurator.defineConfiguration(res.data, url);
      });
    }
  }
});

'use strict';
angular.module('arethusa.core').constant('CONF_ROUTE', {
  controller: 'ConfEditorCtrl',
  templateUrl: 'templates/conf_editor.html',
  resolve: {
    load: ['$http', 'configurator', function ($http, configurator) {
      var url = './static/configs/conf_editor/1.json';
      return $http.get(url).then(function (res) {
        configurator.defineConfiguration(res.data, url);
      });
    }]
  }
});

Fix minification errors in confEditor


'use strict';

var dragula = require('dragula');

/*jshint unused: false*/
function register (angular) {
  return ['dragulaService', function angularDragula (dragulaService) {
    return {
      restrict: 'A',
      scope: {
        dragulaScope: '=',
        dragulaModel: '='
      },
      link: link
    };

    function link (scope, elem, attrs) {
      var dragulaScope = scope.dragulaScope || scope.$parent;
      var container = elem[0];
      var name = scope.$eval(attrs.dragula);

      var bag = dragulaService.find(dragulaScope, name);
      if (bag) {
        var drake = bag.drake;
        drake.containers.push(container);
      } else {
        var drake = dragula({
          containers: [container]
        });
        dragulaService.add(dragulaScope, name, drake);
      }

      scope.$watch('dragulaModel', function(model) {
        if(model){
          if(drake.models){
            drake.models.push(model);
          }else{
            drake.models = [model];
          }
        }
      });
    }
  }];
}

module.exports = register;

'use strict';

var dragula = require('dragula');

/*jshint unused: false*/
function register (angular) {
  return ['dragulaService', function angularDragula (dragulaService) {
    return {
      restrict: 'A',
      scope: {
        dragulaScope: '=',
        dragulaModel: '='
      },
      link: link
    };

    function link (scope, elem, attrs) {
      var dragulaScope = scope.dragulaScope || scope.$parent;
      var container = elem[0];
      var name = scope.$eval(attrs.dragula);

      var bag = dragulaService.find(dragulaScope, name);
      if (bag) {
        var drake = bag.drake;
        drake.containers.push(container);
      } else {
        var drake = dragula({
          containers: [container]
        });
        dragulaService.add(dragulaScope, name, drake);
      }

      scope.$watch('dragulaModel', function(newValue, oldValue) {
        if(newValue){
          if(drake.models){
            var modelIndex = drake.models.indexOf(oldValue);
            drake.models.splice(modelIndex, 1, newValue);
          }else{
            drake.models = [newValue];
          }
        }
      });
    }
  }];
}

module.exports = register;

Substitute the model in its corresponding place.


var selectMode = false;
var selected = [];
var selectModeToggle = document.getElementById('selectModeToggle');
var deleteButton = document.getElementById('delete');
var emoticonsContainer = document.getElementById('emoticons');

selectModeToggle.addEventListener('click', function() {
  if (selectMode) {
    selectMode = false;
    // change style of select link to indicate select mode is OFF somehow
    deleteButton.classList.add('hide');
  } else {
    selectMode = true;
    deleteButton.classList.remove('hide');
    emoticonsContainer.addEventListener('click', function(event) {
      if (event.target.matches('.emoticon')) {
        event.stopPropagation();
        event.target.classList.toggle('selected');
      }
    });
  }
});

var selectMode = false;
var selected = [];
var selectModeToggle = document.getElementById('selectModeToggle');
var deleteButton = document.getElementById('delete');
var emoticonsContainer = document.getElementById('emoticons');

function toggleSelectedArrItems(emoticon) {
  var index = selected.indexOf(emoticon);
  if (index === -1) {
    selected.push(emoticon);
  } else {
    selected.splice(index, 1);
  }
}

selectModeToggle.addEventListener('click', function() {
  if (selectMode) {
    selectMode = false;
    // change style of select link to indicate select mode is OFF somehow
    deleteButton.classList.add('hide');
  } else {
    selectMode = true;
    // change style of select link to indicate select mode is ON somehow
    deleteButton.classList.remove('hide');
    emoticonsContainer.addEventListener('click', function(event) {
      if (event.target.matches('.emoticon')) {
        event.stopPropagation();
        event.target.classList.toggle('selected');
        toggleSelectedArrItems(event.target.innerHTML);
      }
    });
  }
});

Create and call toggleSelectedArrItem function


let Quiz;
let currentQuizWord = {};
let currentArray = 0;
let test = 0;

async function startQuiz(folderKey) {
await fetch(`/study?folderKey=${folderKey}`)
     .then(res => res.json())
     .then(result => {
         Quiz = result;
         console.log(Quiz[0].length);
         return Quiz.length;
    }).catch("Could not find any cards");
}

function nextQuizWord() {
  let nextWord = {};
  if (Quiz[currentArray].length != 0) {
    nextWord = Quiz[currentArray].shift();
  } else {
    currentArray++;
    if (currentArray >= Quiz.length) {
      return "!@end";
    } else {
      nextWord = Quiz[currentArray].shift();
    }
  }
  currentQuizWord = nextWord;
  return nextWord;
}

function updateWordQueues(correct, cardKey) {
  if (correct == "false" && currentArray < Quiz.length - 1) {
    Quiz[currentArray + 1].push(currentQuizWord);
  }
  // Updates the card's familarity score
  fetch('/study', {
    method: 'POST',
    body: `cardKey=${cardKey}&answeredCorrectly=${correct}`,
    headers: { 'Content-type': 'application/x-www-form-urlencoded' }
  });
}

function getRound() {
  return currentArray;
}

export { startQuiz, updateWordQueues, nextQuizWord, getRound };

let Quiz;
let currentQuizWord = {};
let currentArray;

async function startQuiz(folderKey) {
  currentArray = 0;
  await fetch(`/study?folderKey=${folderKey}`)
     .then(res => res.json())
     .then(result => {
         Quiz = result;
         return Quiz.length;
    }).catch("Could not find any cards");
}

function nextQuizWord() {
  let nextWord = {};
  if (Quiz[currentArray].length != 0) {
    nextWord = Quiz[currentArray].shift();
  } else {
    currentArray++;
    if (currentArray >= Quiz.length) {
      return "!@end";
    } else {
      nextWord = Quiz[currentArray].shift();
    }
  }
  currentQuizWord = nextWord;
  return nextWord;
}

function updateWordQueues(correct, cardKey) {
  if (correct == "false" && currentArray < Quiz.length - 1) {
    Quiz[currentArray + 1].push(currentQuizWord);
  }
  // Updates the card's familarity score
  fetch('/study', {
    method: 'POST',
    body: `cardKey=${cardKey}&answeredCorrectly=${correct}`,
    headers: { 'Content-type': 'application/x-www-form-urlencoded' }
  });
}

function getRound() {
  return currentArray;
}

export { startQuiz, updateWordQueues, nextQuizWord, getRound };

Fix bug with multiple quizes in a row


'use strict';
var _ = require('lodash');
var P = require('bluebird');
var FilterParser = require('./filter-parser');

function ValueStatGetter(model, params, opts) {

  function getAggregateField() {
    // jshint sub: true
    return params['aggregate_field'] || '_id';
  }

  this.perform = function () {
    return new P(function (resolve, reject) {
      var query = model.aggregate();

      if (params.filters) {
        _.each(params.filters, function (filter) {
          query = new FilterParser(model, opts).perform(query, filter.field,
            filter.value, 'match');
        });
      }

      var sum = 1;
      if (params['aggregate_field']) {
        sum = '$' + params['aggregate_field'];
      }

      query
        .group({
          _id: null,
          total: { $sum: sum }
        })
        .exec(function (err, records) {
          if (err) { return reject(err); }
          resolve({ value: records[0].total });
        });
    });
  };
}

module.exports = ValueStatGetter;

'use strict';
var _ = require('lodash');
var P = require('bluebird');
var FilterParser = require('./filter-parser');

function ValueStatGetter(model, params, opts) {

  function getAggregateField() {
    // jshint sub: true
    return params['aggregate_field'] || '_id';
  }

  this.perform = function () {
    return new P(function (resolve, reject) {
      var query = model.aggregate();

      if (params.filters) {
        _.each(params.filters, function (filter) {
          query = new FilterParser(model, opts).perform(query, filter.field,
            filter.value, 'match');
        });
      }

      var sum = 1;
      if (params['aggregate_field']) {
        sum = '$' + params['aggregate_field'];
      }

      query
        .group({
          _id: null,
          total: { $sum: sum }
        })
        .exec(function (err, records) {
          if (err) { return reject(err); }
          if (!records || !records.length) { return resolve({ value: 0 }); }

          resolve({ value: records[0].total });
        });
    });
  };
}

module.exports = ValueStatGetter;

Fix the value stat getter when no records available


// @flow
import * as Constants from '../constants/searchv3'
import {globalColors} from '../styles'

const followingStateToStyle = (followingState: Constants.FollowingState) => {
  return {
    Following: {
      color: globalColors.green2,
    },
    NoState: {
      color: globalColors.black_40,
    },
    NotFollowing: {
      color: globalColors.blue,
    },
    You: {
      fontStyle: 'italic',
      color: globalColors.black,
    },
  }[followingState]
}

export {followingStateToStyle}

// @flow
import * as Constants from '../constants/searchv3'
import {globalColors} from '../styles'

const followingStateToStyle = (followingState: Constants.FollowingState) => {
  return {
    Following: {
      color: globalColors.green2,
    },
    NoState: {
      color: globalColors.black_75,
    },
    NotFollowing: {
      color: globalColors.blue,
    },
    You: {
      fontStyle: 'italic',
      color: globalColors.black_75,
    },
  }[followingState]
}

export {followingStateToStyle}

Fix blacks in following style


CKEDITOR.editorConfig = function( config ) {
  config.allowedContent = true;
  config.removeFormatTags = "";
  config.protectedSource.push(/<r:([\S]+).*<\/r:\1>/g);
  config.protectedSource.push(/<r:[^>/]*\/>/g);

  config.forcePasteAsPlainText = true;
  // if you want to remove clipboard, you have to remove all of these:
  // clipboard, pastetext, pastefromword
  config.removePlugins = "save, newpage, preview, print, templates, forms, flash, smiley, language, pagebreak, iframe, bidi";

  var startupMode = $.cookie('ckeditor.startupMode');
  if (startupMode == 'source' || startupMode == 'wysiwyg' ) {
    config.startupMode = startupMode;
  }

  this.on('mode', function(){
    $.cookie('ckeditor.startupMode', this.mode);
  })

};

CKEDITOR.editorConfig = function( config ) {
  config.allowedContent = true;
  config.removeFormatTags = "";
  config.protectedSource.push(/<r:([\S]+).*<\/r:\1>/g);
  config.protectedSource.push(/<r:[^>/]*\/>/g);
  //let paste from word be available
  // config.forcePasteAsPlainText = false;
  // if you want to remove clipboard, you have to remove all of these:
  // clipboard, pastetext, pastefromword
  config.removePlugins = "save, newpage, preview, print, templates, forms, flash, smiley, language, pagebreak, iframe, bidi";

  var startupMode = $.cookie('ckeditor.startupMode');
  if (startupMode == 'source' || startupMode == 'wysiwyg' ) {
    config.startupMode = startupMode;
  }

  this.on('mode', function(){
    $.cookie('ckeditor.startupMode', this.mode);
  })

};

Comment out paste plain text line and give the option to paste with formatting.


'use strict';

(function() {
  angular.module('ncsaas')
    .service('BodyClassService', [BodyClassService]);

    function BodyClassService() {
      var vm = this;
      vm.getBodyClass = getBodyClass;

      function getBodyClass(name) {
        var stateWithProfile = [
          'profile',
          'profile-edit',
          'project',
          'project-edit',
          'customer',
          'customer-edit',
          'customer-plans',
          'user',
          'home',
          'login',
        ];

        if (stateWithProfile.indexOf(name) > -1 ) {
          if (name === 'login' || name === 'home') {
            vm.bodyClass = 'app-body site-body';
            return vm.bodyClass;
          } else {
            vm.bodyClass = 'app-body obj-view';
            return vm.bodyClass;
          }
        } else {
          vm.bodyClass = 'app-body'
          return vm.bodyClass;
        }
      }
    }

})();

'use strict';

(function() {
  angular.module('ncsaas')
    .service('BodyClassService', [BodyClassService]);

    function BodyClassService() {
      var vm = this;
      vm.getBodyClass = getBodyClass;

      function getBodyClass(name) {
        var bodyClass;

        var stateWithProfile = [
          'profile',
          'profile-edit',
          'project',
          'project-edit',
          'customer',
          'customer-edit',
          'customer-plans',
          'user',
          'home',
          'login',
        ];

        if (stateWithProfile.indexOf(name) > -1 ) {
          if (name === 'login' || name === 'home') {
            bodyClass = 'app-body site-body';
            return bodyClass;
          } else {
            bodyClass = 'app-body obj-view';
            return bodyClass;
          }
        } else {
          bodyClass = 'app-body'
          return bodyClass;
        }
      }
    }

})();

Remove vm. for local variable in function.


/* @flow */

import { isPayPalDomain } from '@paypal/sdk-client/src';
import { PopupOpenError as _PopupOpenError } from 'zoid/src';

import { setupLogger, allowIframe as _allowIframe } from '../lib';
import { getCheckoutComponent } from '../checkout';
import { getButtonsComponent } from '../buttons';

export const Buttons = getButtonsComponent();
export let Checkout;
export let PopupOpenError;
export let allowIframe;

if (isPayPalDomain()) {
    Checkout = getCheckoutComponent();
    PopupOpenError = _PopupOpenError;
    allowIframe = _allowIframe;
}

export function setupButtons() {
    setupLogger();
}

/* @flow */

import { isPayPalDomain } from '@paypal/sdk-client/src';
import { PopupOpenError as _PopupOpenError } from 'zoid/src';

import { setupLogger, allowIframe as _allowIframe } from '../lib';
import { getCheckoutComponent } from '../checkout';
import { getButtonsComponent } from '../buttons';

const CheckoutComponent = getCheckoutComponent();

export const Buttons = getButtonsComponent();
export let Checkout;
export let PopupOpenError;
export let allowIframe;

if (isPayPalDomain()) {
    Checkout = CheckoutComponent;
    PopupOpenError = _PopupOpenError;
    allowIframe = _allowIframe;
}

export function setupButtons() {
    setupLogger();
}

Call getCheckoutComponent to register component in parent window


angular.module("Prometheus.directives").directive('ngChanged', function() {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      element.bind("change", function() {
        scope.$eval(attrs.ngChanged);
      });
    }
  };
});

angular.module("Prometheus.directives").directive('ngChanged', function() {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      element.bind("change", function() {
        scope.$apply(attrs.ngChanged);
      });
    }
  };
});

Use $apply() in ngChanged to immediately propagate model changes.


const BotModule = require('../BotModule');

module.exports = BotModule.extend({
    config: null,
    i18n: null,
    dependencies: {
        'config': 'config',
        'i18n': 'i18n',
    },
    initialize: function (dependencyGraph) {
        this._super(dependencyGraph);
        this.discordClient.on('messageDelete', message => {
            message.guild.channels.find('id', this.config.deletedLogsRoom).send({
                embed: {
                    color: 0xff0000,
                    title: this.i18n.__mf("Deleted message authored by @{username}#{discriminator}", {username: message.author.username, discriminator: message.author.discriminator}),
                    description: message.content,
                    timestamp: new Date(),
                    footer: {
                        icon_url: this.discordClient.user.avatarURL,
                        text: "Shotbow Chat Bot"
                    }
                }
            })
                .catch(error => console.log("Not enough permissions to send a message to the moderation room."));
        });
    }
});

const BotModule = require('../BotModule');

module.exports = BotModule.extend({
    config: null,
    i18n: null,
    dependencies: {
        'config': 'config',
        'i18n': 'i18n',
    },
    initialize: function (dependencyGraph) {
        this._super(dependencyGraph);
        this.discordClient.on('messageDelete', message => {
            if (message.guild == null) return;
            message.guild.channels.find('id', this.config.deletedLogsRoom).send({
                embed: {
                    color: 0xff0000,
                    title: this.i18n.__mf("Deleted message authored by @{username}#{discriminator}", {username: message.author.username, discriminator: message.author.discriminator}),
                    description: message.content,
                    timestamp: new Date(),
                    footer: {
                        icon_url: this.discordClient.user.avatarURL,
                        text: "Shotbow Chat Bot"
                    }
                }
            })
                .catch(error => console.log("Not enough permissions to send a message to the moderation room."));
        });
    }
});

Fix crash on delete in private message


/*
 * grunt-require
 * https://github.com/asciidisco/grunt-requirejs
 *
 * Copyright (c) 2012 asciidisco
 * Licensed under the MIT license.
 */

exports.init = function(grunt) {
  'use strict';

  var fs = require('fs');
  var exports = {};

  // privates
  var isDefaultVersion = true;
  var requirejs = null;

  // Returns a requirejs instance
  exports.getRequirejs = function(config) {
    var defaultRequire = require('requirejs');

    // check if we should load a custom requirejs version
    if (config.rjs) {
      var rjsPathname = config.rjs + '/bin/r.js';

      // check if the custom version is available, then load & return the
      // custom version, else default to the standard bundled requirejs
      if (fs.existsSync(rjsPathname)) {
        requirejs = require(rjsPathname);
        isDefaultVersion = false;
        return requirejs;
      }

    }

    isDefaultVersion = true;
    requirejs = defaultRequire;
    return requirejs;
  };

  // Returns the version number of the currently used requirejs library
  exports.getRequirejsVersionInfo = function() {
    return requirejs.version;
  };

  // Returns a boolean flag that determines if we´re using
  // the default bundled version or a user defined custom requirejs version
  exports.isCustomLibrary = function() {
    return !isDefaultVersion;
  };

  return exports;
};

/*
 * grunt-require
 * https://github.com/asciidisco/grunt-requirejs
 *
 * Copyright (c) 2012 asciidisco
 * Licensed under the MIT license.
 */

exports.init = function(grunt) {
  'use strict';

  var fs = require('fs');
  var exports = {};

  // privates
  var isDefaultVersion = true;
  var requirejs = null;

  // Returns a requirejs instance
  exports.getRequirejs = function(config) {
    var defaultRequire = require('requirejs');

    // check if we should load a custom requirejs version
    if (config.rjs) {
      var rjsPathname = config.rjs + '/bin/r.js';

      // if the custom version is available, then load & return the
      // custom version, else default to the standard bundled requirejs
      try {
        requirejs = require(rjsPathname);
        isDefaultVersion = false;
        return requirejs;
      } catch (e) {}

    }

    isDefaultVersion = true;
    requirejs = defaultRequire;
    return requirejs;
  };

  // Returns the version number of the currently used requirejs library
  exports.getRequirejsVersionInfo = function() {
    return requirejs.version;
  };

  // Returns a boolean flag that determines if we´re using
  // the default bundled version or a user defined custom requirejs version
  exports.isCustomLibrary = function() {
    return !isDefaultVersion;
  };

  return exports;
};

Allow to use custom r.js with relative path


define([
	'models/location'
], function(
		LocationModel
) {

	var baseUrl = 'api/locations';

	var collection = {

		model: LocationModel,

		url: baseUrl,

		/**
		 * Clear any currently applied filters so that future
		 * fetch calls will return ALL locations
		 *
		 * @returns {undefined}
		 */
		clearFilter: function() {
			this.url = baseUrl;
		},

		/**
		 * Apply a filter, causing any future fetch calls to return
		 * only the locations that match the given filter string
		 *
		 * @param {string} filterStr
		 * @returns {undefined}
		 */
		setFilter: function(filterStr) {
			this.url = baseUrl + '/search/' + encodeURIComponent(filterStr);
		}

	};

	return Backbone.Collection.extend(collection);

});

define([
	'models/location'
], function(
		LocationModel
) {

	var baseUrl = 'api/locations';

	var collection = {

		model: LocationModel,

		url: baseUrl,

		/**
		 * Clear any currently applied filters so that future
		 * fetch calls will return ALL locations
		 *
		 * @returns {undefined}
		 */
		clearFilter: function() {
			this.url = baseUrl;
		},

		/**
		 * Apply a filter, causing any future fetch calls to return
		 * only the locations that match the given filter string
		 *
		 * @param {string} filterStr
		 * @returns {undefined}
		 */
		setFilter: function(filterStr) {
			this.url = baseUrl + '?search=' + encodeURIComponent(filterStr);
		}

	};

	return Backbone.Collection.extend(collection);

});

Update location search to match new API


define(['mac/bitpacking'], function(bitpacking) {

  'use strict';

  return function(resource) {
    resource.getUnpackedData = function() {
      return bitpacking.unpackBits(this.data.buffer, this.data.byteOffset, this.data.byteLength);
    };
  };

});

define(['mac/bitpacking'], function(bitpacking) {

  'use strict';

  return function(item) {
    item.getUnpackedData = function() {
      return this.getBytes().then(function(bytes) {
        return bitpacking.unpackBits(bytes.buffer, bytes.byteOffset, bytes.byteLength);
      });
    };
  };

});

Change BITD to new loader format


/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
/*global define*/
define(
    [],
    function () {
        'use strict';

        return {
            getRules: function () {
                return {
                    'firstname': {
                        'required': true
                    },
                    'lastname': {
                        'required': true
                    },
                    'street': {
                        'required': true
                    },
                    'postcode': {
                        'required': true
                    },
                    'city': {
                        'required': true
                    },
                    'country_id': {
                        'required': true
                    }
                };
            }
        };
    }
);

/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
/*global define*/
define(
    [],
    function () {
        'use strict';

        return {
            getRules: function () {
                return {
                    'firstname': {
                        'required': true
                    },
                    'lastname': {
                        'required': true
                    },
                    'postcode': {
                        'required': true
                    },
                    'city': {
                        'required': true
                    },
                    'country_id': {
                        'required': true
                    }
                };
            }
        };
    }
);

Remove streed requirement from validation


import React from 'react';
import { storiesOf } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';

import Modal, { PureModal } from '@ichef/gypcrete/src/Modal';
import { getAddonOptions } from 'utils/getPropTables';

import ContainsColumnView from '../SplitView/ContainsColumnView';
import ClosableModalExample, { MulitpleClosableModalExample } from './ClosableModalExample';

storiesOf('@ichef/gypcrete|Modal', module)
    .addDecorator(withInfo)
    .add(
        'basic modal',
        () => (
            <Modal header="Basic modal">
                Hello World!
            </Modal>
        )
    )
    .add(
        'closable modal',
        () => <ClosableModalExample />
    )
    .add(
        'with <SplitView>',
        () => (
            <Modal header="With <SplitView>" flexBody bodyPadding={{ bottom: 0 }}>
                <ContainsColumnView />
            </Modal>
        )
    )
    .add(
        'centered modal',
        () => (
            <Modal header="Vertically-centered modal">
                Hello World!
            </Modal>
        )
    )
    .add(
        'multiple layer modals',
        () => <MulitpleClosableModalExample depth={10} />,
        {
            info: 'Indented with 32px from each side for each layer. When number of layer > 7 we won\'t indent it',
        }
    )
    // Props table
    .add(
        'props',
        () => <div />,
        { info: getAddonOptions([PureModal, Modal]) }
    );

import React from 'react';

import Modal, { PureModal } from '@ichef/gypcrete/src/Modal';

import ContainsColumnView from '../SplitView/ContainsColumnView';
import ClosableModalExample, { MulitpleClosableModalExample } from './ClosableModalExample';

export default {
    title: '@ichef/gypcrete|Modal',
    component: PureModal,
    subcomponents: {
        'renderToLayer()': Modal
    },
}

export function BasicModal() {
    return (
        <Modal header="Basic modal">
            Hello World!
        </Modal>
    );
}

export function ClosableModal() {
    return <ClosableModalExample />;
}

export function SplitViewModal() {
    return (
        <Modal header="With <SplitView>" flexBody bodyPadding={{ bottom: 0 }}>
            <ContainsColumnView />
        </Modal>
    );
}

SplitViewModal.story = {
    name: 'With <SplitView>',
};

export function CenteredModal() {
    return (
        <Modal header="Vertically-centered modal" centered>
            Hello World!
        </Modal>
    );
}

export function MultilpleLayerModal() {
    return <MulitpleClosableModalExample depth={10} />;
}

MultilpleLayerModal.story = {
    parameters: {
        docs: {
            storyDescription: 'Indented with 32px from each side for each layer. When number of layer > 7 we won\'t indent it',
        },
    },
};

Add new Modal storybook doc


Meteor.methods({
  report: function (url, reports) {
    console.log("reporting to ", url);
    Meteor.http.post(url, {
      data: reports
    });
    return null;
  }
});

Meteor.methods({
  report: function (url, reports) {
    Meteor.http.post(url, {
      data: reports
    });
    return null;
  }
});

Remove console.log on report again


var CHAT_SERVER = "http://localhost:7000"
var DEFAULT_USERNAME = "Guest";
$(document).ready(function(){
  var socket = io.connect(CHAT_SERVER);
  socket.on('welcome', showGreetings);
  socket.on('message', showIncomingMessage);
  socket.on('info', showSystemInfo);

  addWaterMark();
  sendButtonOnClick();
  changeButtonOnClick();

  function showGreetings(msg){
    $("#title").text(msg['greetings']);
  }

  function showIncomingMessage(msg){
    $("#messages").append("
" + msg['msgOwner'] + ": " + msg['msgContent'] + "
");
  }

  function addWaterMark(){
    $("#outgoing-message").watermark("Enter your message here");
  }

  function sendButtonOnClick(){
    $("#send").click(function(){
      var msg = $("#outgoing-message").val();
      showOutgoingMessage(msg);
      socket.emit('message', msg);
    });
  }

  function showOutgoingMessage(msg){
    $("#messages").append("
Me: " + msg + "
");
  }

  function showSystemInfo(msg){
    $("#messages").append("
" + msg['msgOwner'] + ": " + msg['msgContent'] + "
");
  }

  function changeButtonOnClick(){
    $("#change").click(function(){
      var username = $("#username").val();
      if(!username)
        username = DEFAULT_USERNAME;
      registerUsername(username);
    });
  }

  function registerUsername(username){
    socket.emit('user-join', username);
  }
});

var CHAT_SERVER = "http://localhost:7000"
var DEFAULT_USERNAME = "Guest";
$(document).ready(function(){
  var socket = io.connect(CHAT_SERVER);
  socket.on('welcome', showGreetings);
  socket.on('message', showIncomingMessage);
  socket.on('info', showSystemInfo);

  addWaterMark();
  sendButtonOnClick();
  changeButtonOnClick();

  function showGreetings(msg){
    $("#title").text(msg['greetings']);
  }

  function showIncomingMessage(msg){
    $("#messages").append("
" + msg['msgOwner'] + ": " + msg['msgContent'] + "
");
  }

  function addWaterMark(){
    $("#outgoing-message").watermark("Enter your message here");
  }

  function sendButtonOnClick(){
    $("#send").click(function(){
      var msg = $("#outgoing-message").val();
      showOutgoingMessage(msg);
      $("#outgoing-message").val('');
      socket.emit('message', msg);
    });
  }

  function showOutgoingMessage(msg){
    $("#messages").append("
Me: " + msg + "
");
  }

  function showSystemInfo(msg){
    $("#messages").append("
" + msg['msgOwner'] + ": " + msg['msgContent'] + "
");
  }

  function changeButtonOnClick(){
    $("#change").click(function(){
      var username = $("#username").val();
      if(!username)
        username = DEFAULT_USERNAME;
      registerUsername(username);
    });
  }

  function registerUsername(username){
    socket.emit('user-join', username);
  }
});

Clear message textbox after message is sent.


var fastScroll = (function() {

	// Used to track the enabling of hover effects
	var enableTimer = 0;

	/*
	 * Listen for a scroll and use that to remove
	 * the possibility of hover effects
	 */

	window.addEventListener('scroll', function() {
		clearTimeout(enableTimer);
		removeHoverClass();
		enableTimer = setTimeout(addHoverClass, 500);
	}, false);

	/**
	 * Removes the hover class from the body. Hover styles
	 * are reliant on this class being present
	 */
	function removeHoverClass() {
		if ('none' !== document.body.style.pointerEvents) {
			document.body.style.pointerEvents = 'none';
		}
	}

	/**
	 * Adds the hover class to the body. Hover styles
	 * are reliant on this class being present
	 */
	function addHoverClass() {
		document.body.style.pointerEvents = 'auto';
	}
})();

(function() {

  var FastScroll = function(delay) {
    this.delay = delay || 500;
    this.enableTimer = 0;

    var self = this;
    this.scrollCallback = function() {
      self._onScroll();
    };
    window.addEventListener('scroll', this.scrollCallback, false);
  };

  FastScroll.prototype = {
    enableTimer: null,
    delay: null,
    scrollCallback: null,

    removeHoverClass: function() {
      if ('none' !== document.body.style.pointerEvents) {
        document.body.style.pointerEvents = 'none';
      }
    },

    addHoverClass: function() {
      document.body.style.pointerEvents = 'auto';
    },

    destroy: function() {
      window.removeEventListener('scroll', this.scrollCallback, false);
    },

    _onScroll: function() {
      clearTimeout(this.enableTimer);
      this.removeHoverClass();
      this.enableTimer = setTimeout(this.addHoverClass, this.delay);
    }
  };

  window.FastScroll = FastScroll;

})();

Make FastScroll a class, don't register by default


import React from 'react';

class SpellcheckPanel extends React.Component {
    renderSpellcheckCollations(){
        if(this.props.spellcheckData.length === 0)
            return;

        // get the first suggestion
        const suggestion = this.props.spellcheckData[0];

        return
Do you mean {suggestion}?
;
    }
    render() {
        return (

                    {this.renderSpellcheckCollations()}

        );
    }
}

export default SpellcheckPanel;

import React from 'react';

class SpellcheckPanel extends React.Component {
    handleLink(suggestion, event){
        event.preventDefault();
        this.props.handleRedirect({
            keywords: suggestion
        });
    }
    renderSpellcheckCollations(){
        if(this.props.spellcheckData.length === 0)
            return;

        // get the first suggestion
        const suggestion = this.props.spellcheckData[0];

        return
Do you mean {suggestion}?
;
    }
    render() {
        return (

                    {this.renderSpellcheckCollations()}

        );
    }
}

export default SpellcheckPanel;

Fix spellcheck suggestion redirection on firefox


Kwf.FrontendForm.Checkbox = Ext.extend(Kwf.FrontendForm.Field, {
    initField: function() {
        this.el.select('input').each(function(input) {
            input.on('click', function() {
                this.fireEvent('change', this.getValue());
            }, this);
        }, this);
    },
    clearValue: function() {
        var inp = this.el.child('input');
        inp.dom.checked = false;
    },
    setValue: function(value) {
        var inp = this.el.child('input');
        inp.dom.checked = !!value;
    }
});

Kwf.FrontendForm.fields['kwfFormFieldCheckbox'] = Kwf.FrontendForm.Checkbox;

Kwf.FrontendForm.Checkbox = Ext.extend(Kwf.FrontendForm.Field, {
    initField: function() {
        this.el.select('input').each(function(input) {
            input.on('click', function() {
                this.fireEvent('change', this.getValue());
            }, this);
        }, this);
    },
    clearValue: function() {
        var inp = this.el.child('input');
        inp.dom.checked = false;
    },
    setValue: function(value) {
        var inp = this.el.child('input');
        inp.dom.checked = !!value;
    },
    getValue: function(value) {
        var inp = this.el.child('input');
        return inp.dom.checked;
    }
});

Kwf.FrontendForm.fields['kwfFormFieldCheckbox'] = Kwf.FrontendForm.Checkbox;

Add getValue for checkbox-form-field to return the correct value


import React from 'react';
import {findDOMNode} from 'react-dom';

const AUTHOR_REPO = 'ericgio/react-bootstrap-typeahead';

const GitHubStarsButton = React.createClass({
  componentDidMount() {
    const node = findDOMNode(this);
    node.dataset.style = window.innerWidth > 480 ? 'mega': null;
  },

  render() {
    return (
      <a
        aria-label={`Star ${AUTHOR_REPO} on GitHub`}
        className="github-button"
        data-count-api={`/repos/${AUTHOR_REPO}#stargazers_count`}
        data-count-aria-label="# stargazers on GitHub"
        data-count-href={`/${AUTHOR_REPO}/stargazers`}
        href={`https://github.com/${AUTHOR_REPO}`}>
        Star
      </a>
    );
  },
});

export default GitHubStarsButton;

import React from 'react';
import {findDOMNode} from 'react-dom';

const AUTHOR_REPO = 'ericgio/react-bootstrap-typeahead';

const GitHubStarsButton = React.createClass({
  componentDidMount() {
    const node = findDOMNode(this);
    node.dataset.style = window.innerWidth > 480 ? 'mega': null;
  },

  render() {
    return (
      <a
        aria-label={`Star ${AUTHOR_REPO} on GitHub`}
        className="github-button"
        data-count-aria-label="# stargazers on GitHub"
        data-count-href={`/${AUTHOR_REPO}/stargazers`}
        data-show-count={true}
        href={`https://github.com/${AUTHOR_REPO}`}>
        Star
      </a>
    );
  },
});

export default GitHubStarsButton;

Fix deprecation warning for Github button on examples page


"use strict";
const { Event } = require("sosamba");
const { version: sosambaVersion } = require("sosamba/package.json");
const { version } = require("../package.json");

class CommandErrorEvent extends Event {
    constructor(...args) {
        super(...args, {
            name: "commandError"
        });
    }

    async run(e, ctx) {
        if (e.constructor.name !== "ExtensionError") this.log.error(e);
        try {
            await ctx.send({
                embed: {
                    title: ":x: Error running the command",
                    description: `I am unable to run the command because of a coding error:\n\`\`\`js\n${e.stack}\n\`\`\``,
                    color: 0xFF0000,
                    footer: {
                        text: `Please tell the command developers about this. | tt.bot v${version} running on Sosamba v${sosambaVersion}`
                    }
                }
            });
        } catch {}
    }
}

module.exports = CommandErrorEvent;

"use strict";
const { Event } = require("sosamba");
const { version: sosambaVersion } = require("sosamba/package.json");
const { version } = require("../package.json");

class CommandErrorEvent extends Event {
    constructor(...args) {
        super(...args, {
            name: "commandError"
        });
    }

    async run(e, ctx) {
        if (e.constructor.name !== "ExtensionError") this.log.error(e);
        try {
            await ctx.send({
                embed: {
                    title: ":x: Error running the command",
                    description: `I am unable to run the command because of a coding error:\n\`\`\`js\n${e.stack}\n\`\`\``,
                    color: 0xFF0000,
                    footer: {
                        text: `Please report this issue on our support server or on GitHub. | tt.bot v${version} running on Sosamba v${sosambaVersion}`
                    }
                }
            });
        } catch {}
    }
}

module.exports = CommandErrorEvent;

Change a bit of text


'use strict';

module.exports = {
        SERVE_INSECURE: false,
        SENSOR_DATA_PATH: '/var/lib/homecontrol/sensordata/temperatureSensors/TA',
        PROGRAMME_DATA_PATH: '/var/lib/homecontrol/programdata',
        WEBAPP_DATA_PATH: '/var/lib/homecontrol/webapp'
};

'use strict';

module.exports = {
        SERVE_INSECURE: false,
        SENSOR_DATA_PATH: '/var/lib/homecontrol/sensordata',
        PROGRAMME_DATA_PATH: '/var/lib/homecontrol/programdata',
        WEBAPP_DATA_PATH: '/var/lib/homecontrol/webapp'
};

Correct default sensor data path


(function () {
    'use strict';

    define(
        [
            'lodash',
            'jquery'
        ],
        function (_, $) {
            return function (baseUrl, ajaxOptions, noCache, logErrors) {
                var queryString;

                queryString = function (parameters) {
                    return _.map(parameters, function (value, key) {
                        return '(' + key + ':' + value + ')';
                    })
                    .join(' AND ');
                };

                return function (parameters, callback) {
                    $.ajax(_.merge({}, ajaxOptions, {
                        url: baseUrl + '?q=' + queryString(parameters || {}) + (noCache ? '&noCache=1' : '') + '&limit=500',
                        success: function (result) {
                            if (!result.ok) {
                                return callback(new Error('Invalid response received from server'));
                            }
                            delete result.ok;
                            callback(undefined, _.values(result));
                        },
                        error: function (jqXHR, textStatus, err) {
                            if (logErrors && console && typeof console.error === 'function') {
                                console.error(err);
                            }
                            callback(err);
                        }
                    }));
                };
            };
        }
    );
}());

(function () {
    'use strict';

    define(
        [
            'lodash',
            'jquery'
        ],
        function (_, $) {
            return function (baseUrl, ajaxOptions, noCache, logErrors) {
                var queryString;

                queryString = function (parameters) {
                    return _.map(parameters, function (value, key) {
                        return '(' + key + ':' + value + ')';
                    })
                    .join(' AND ');
                };

                return function (parameters, callback) {
                    $.ajax(_.merge({}, ajaxOptions, {
                        url: baseUrl + '?q=' + queryString(parameters || {}) + (noCache ? '&noCache=1' : ''),
                        success: function (result) {
                            if (!result.ok) {
                                return callback(new Error('Invalid response received from server'));
                            }
                            delete result.ok;
                            callback(undefined, _.values(result));
                        },
                        error: function (jqXHR, textStatus, err) {
                            if (logErrors && console && typeof console.error === 'function') {
                                console.error(err);
                            }
                            callback(err);
                        }
                    }));
                };
            };
        }
    );
}());

Remove temporary artificial results limit.


const MaxCallPerMinutes = 30;
/**
 * Limiting the frequency of interface calls
 */
module.exports = function () {
    let callTimes = {};
    setInterval(() => callTimes = {}, 60000); // Emptying every 60 seconds

    return async (ctx, next) => {
        // robot10
        if (ctx.socket.user === '5adad39555703565e7903f79') {
            return next();
        }

        const socketId = ctx.socket.id;
        const count = callTimes[socketId] || 0;
        if (count >= MaxCallPerMinutes) {
            return ctx.res = '接口调用频繁';
        }
        callTimes[socketId] = count + 1;
        await next();
    };
};

const MaxCallPerMinutes = 20;
/**
 * Limiting the frequency of interface calls
 */
module.exports = function () {
    let callTimes = {};
    setInterval(() => callTimes = {}, 60000); // Emptying every 60 seconds

    return async (ctx, next) => {
        // robot10
        if (ctx.socket.user === '5adad39555703565e7903f79') {
            return next();
        }

        const socketId = ctx.socket.id;
        const count = callTimes[socketId] || 0;
        if (count >= MaxCallPerMinutes) {
            return ctx.res = '接口调用频繁';
        }
        callTimes[socketId] = count + 1;
        await next();
    };
};

Reduce user maximum number of interface calls per minute


'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' );

// VARIABLES //

var mpath = './../lib/';

// TESTS //

tape( 'main export is a function', function test( t ) {
	var homedir;
	t.ok( true, __filename );
	homedir = require( mpath );
	t.strictEqual( typeof homedir, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function aliases `os.homedir` if available', function test( t ) {
	var homedir;
	var opts;

	opts = {
		'os': {
			'homedir': mock
		}
	};
	homedir = proxyquire( mpath, opts );

	t.strictEqual( homedir, mock, 'equals `os.homedir`' );
	t.end();

	function mock(){}
});

tape( 'the function supports older Node versions', function test( t ) {
	var homedir;
	var opts;
	var env;

	opts = {
		'os': {
			'homedir': undefined
		}
	};
	homedir = proxyquire( mpath, opts );
	env = process.env;
	process.env = {
		'HOME': '/Users/beep'
	};

	t.strictEqual( homedir(), '/Users/beep', 'returns home directory' );
	process.env = env;
	t.end();
});

'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' );

// VARIABLES //

var mpath = './../lib/';

// TESTS //

tape( 'main export is a function', function test( t ) {
	var homedir;
	t.ok( true, __filename );
	homedir = require( mpath );
	t.strictEqual( typeof homedir, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function aliases `os.homedir` if available', function test( t ) {
	var homedir;
	var opts;

	opts = {
		'os': {
			'homedir': mock
		}
	};
	homedir = proxyquire( mpath, opts );

	t.strictEqual( homedir, mock, 'equals `os.homedir`' );
	t.end();

	function mock(){}
});

tape( 'the function supports older Node versions', function test( t ) {
	var homedir;
	var opts;
	var env;

	opts = {
		'os': {
			'homedir': void 0
		}
	};
	homedir = proxyquire( mpath, opts );
	env = process.env;
	process.env = {
		'HOME': '/Users/beep'
	};

	t.strictEqual( homedir(), '/Users/beep', 'returns home directory' );
	process.env = env;
	t.end();
});

Use void 0 instead of undefined


var ws = new WebSocket('ws://cfc.jmgpena.net/ws');

function renderMsg(message) {
    var div = document.createElement("div");
    var content = document.createTextNode(message);

    div.appendChild(content);

    document.body.appendChild(div);
}

ws.onopen = function(evt) {
    console.log('Websocket connection opened');
};

ws.onclose = function(evt) {
    console.log('Websocket connection closed');
    setTimeout(function() {
        ws = new WebSocket('ws://cfc.jmgpena.net/ws');
    }, 1000);
};

ws.onmessage = function(evt) {
    console.log('Message: ',evt.data);
    renderMsg(evt.data);
};

ws.onerror = function(evt) {
    console.log('Error: ', evt.data);
};

var ws;

function renderMsg(message) {
    var div = document.createElement("div");
    var content = document.createTextNode(message);

    div.appendChild(content);

    document.body.appendChild(div);
}

function onopen(evt) {
    console.log('Websocket connection opened');
}

function onclose(evt) {
    console.log('Websocket connection closed');
    setTimeout(function() {
        createWsConn();
    }, 1000);
}

function onmessage(evt) {
    console.log('Message: ',evt.data);
    renderMsg(evt.data);
}

function onerror(evt) {
        console.log('Error: ', evt.data);
}

function createWsConn() {
    ws = new WebSocket('ws://cfc.jmgpena.net/ws');

    ws.onopen = onopen;
    ws.onclose = onclose;

    ws.onmessage = onmessage;

    ws.onerror = onerror;
}

createWsConn();

Update client script to handle reconnecting better


module.exports = {
    port: 8000,
    tasks: {
        cdnjs: {hour: 1},
        google: {hour: 1},
        jsdelivr: {hour: 1}
    }
};

module.exports = {
    port: 8000,
    tasks: {
        cdnjs: {minute: 1},
        google: {minute: 1},
        jsdelivr: {minute: 1}
    }
};

Change tasks to update once per hour by default