'use strict';

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

class EncryptKeyListItem extends Component {
  classes() {
    return {
      'default': {

      },
    };
  }

  render() {
    return

;
  }
}

export default ReactCSS(EncryptKeyListItem);

'use strict';

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

import { User } from '../common/index';

import colors from '../../styles/variables/colors';
import { spacing, sizing } from '../../styles/variables/utils';

class EncryptKeyListItem extends Component {
  classes() {
    return {
      'default': {
        user: {
          padding: `${spacing.m}px ${spacing.m}px ${spacing.m}px`,
          display: 'flex',
        },
        spaceLine: {
          borderBottom: `solid 1px ${colors.offBgLight}`,
          margin: `0px ${spacing.m}px 0px ${spacing.m + sizing.avatar + spacing.s}px`,
          item: 1,
        },
      },
    };
  }

  render() {
    return

;
  }
}

export default ReactCSS(EncryptKeyListItem);

Add encrypt key list item styles


var _gaq = _gaq || [];
_gaq.push(['_setAccount', '{ANALYTICS_CODE}']);
_gaq.push(['_trackPageview']);

(function() {
	var ga = document.createElement('script');
	ga.type = 'text/javascript';
	ga.async = true;
	ga.src = ('https:' == document.location.protocol
			? 'https://'
			: 'http://')
		+ 'stats.g.doubleclick.net/dc.js';
	var s = document.getElementsByTagName('script')[0];
	s.parentNode.insertBefore(ga, s);
})();

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js',
'__gaTracker');

__gaTracker('create', '{ANALYTICS_CODE}', 'teawars.com');
__gaTracker('send', 'pageview');

Update to use Universal Tracking


import debugModule from 'debug';
import Joi from 'joi';
import xhr from 'xhr';

const debug = debugModule('csra');

const schema = Joi.array().items(
  Joi.object({
    id: Joi.number(),
    nomisId: Joi.string().optional(),
    forename: Joi.string(),
    surname: Joi.string(),
    dateOfBirth: Joi.string(),
    riskAssessmentCompleted: Joi.boolean(),
    healthAssessmentCompleted: Joi.boolean(),
    outcome: Joi.string().optional(),
  }),
);

const validate = (assessment) => {
  const isValid = Joi.validate(assessment, schema, {
    abortEarly: false,
    presence: 'required',
  });

  debug('Validation of get assessments return %j', isValid.error);

  return isValid.error === null;
};

const getAssessments = (callback) => {
  const target = '/api/assessments';

  debug('get assessments');

  const options = {
    timeout: 3500,
  };

  xhr.get(target, options, (error, resp, body) => {
    debug('get assessments returned %j', error || body);

    if (error) {
      callback(null);
    } else {
      callback(validate(body) ? body : null);
    }
  });
};

export default getAssessments;

import debugModule from 'debug';
import Joi from 'joi';
import xhr from 'xhr';

const debug = debugModule('csra');

const schema = Joi.array().items(
  Joi.object({
    id: Joi.number(),
    nomisId: Joi.string().optional(),
    forename: Joi.string(),
    surname: Joi.string(),
    dateOfBirth: Joi.string(),
    riskAssessmentCompleted: Joi.boolean(),
    healthAssessmentCompleted: Joi.boolean(),
    outcome: Joi.string().optional(),
  }),
);

const validate = (assessment) => {
  const isValid = Joi.validate(assessment, schema, {
    abortEarly: false,
    presence: 'required',
  });

  debug('Validation of get assessments return %j', isValid.error);

  return isValid.error === null;
};

const getAssessments = (callback) => {
  const target = '/api/assessments';

  debug('get assessments');

  const options = {
    timeout: 3500,
    json: true,
  };

  xhr.get(target, options, (error, resp, body) => {
    debug('get assessments returned %j', error || body);

    if (error) {
      callback(null);
    } else {
      callback(validate(body) ? body : null);
    }
  });
};

export default getAssessments;

Add JSON option to automatically parse to JSON from request


'use strict';
var angular = require('angular');

var traefikCoreProvider = 'traefik.core.provider';
module.exports = traefikCoreProvider;

angular
  .module(traefikCoreProvider, ['ngResource'])
  .factory('Providers', Providers);

/** @ngInject */
function Providers($resource, $q) {
  const resourceProvider = $resource('../api/providers');
  return {
    get: function () {
      return $q((resolve, reject) => {
        resourceProvider.get()
          .$promise
          .then((rawProviders) => {
            for (let providerName in rawProviders) {
              if (rawProviders.hasOwnProperty(providerName)) {
                if (!providerName.startsWith('$')) {
                  // BackEnds mapping
                  let bckends = rawProviders[providerName].backends || {};
                  rawProviders[providerName].backends = Object.keys(bckends)
                    .map(key => {
                      const goodBackend = bckends[key];
                      goodBackend.backendId = key;
                      return goodBackend;
                    });

                  // FrontEnds mapping
                  let frtends = rawProviders[providerName].frontends || {};
                  rawProviders[providerName].frontends = Object.keys(frtends)
                    .map(key => {
                      const goodFrontend = frtends[key];
                      goodFrontend.frontendId = key;
                      return goodFrontend;
                    });
                }
              }
            }
            resolve(rawProviders);
          })
          .catch(reject);
      });
    }
  };
}

'use strict';
var angular = require('angular');

var traefikCoreProvider = 'traefik.core.provider';
module.exports = traefikCoreProvider;

angular
  .module(traefikCoreProvider, ['ngResource'])
  .factory('Providers', Providers);

/** @ngInject */
function Providers($resource, $q) {
  const resourceProvider = $resource('../api/providers');
  return {
    get: function () {
      return $q((resolve, reject) => {
        resourceProvider.get()
          .$promise
          .then((rawProviders) => {
            delete rawProviders.acme;
            delete rawProviders.ACME;

            for (let providerName in rawProviders) {
              if (rawProviders.hasOwnProperty(providerName)) {
                if (!providerName.startsWith('$')) {
                  // BackEnds mapping
                  let bckends = rawProviders[providerName].backends || {};
                  rawProviders[providerName].backends = Object.keys(bckends)
                    .map(key => {
                      const goodBackend = bckends[key];
                      goodBackend.backendId = key;
                      return goodBackend;
                    });

                  // FrontEnds mapping
                  let frtends = rawProviders[providerName].frontends || {};
                  rawProviders[providerName].frontends = Object.keys(frtends)
                    .map(key => {
                      const goodFrontend = frtends[key];
                      goodFrontend.frontendId = key;
                      return goodFrontend;
                    });
                }
              }
            }
            resolve(rawProviders);
          })
          .catch(reject);
      });
    }
  };
}

Remove useless ACME tab from UI.


#!/usr/bin/env node

/*
 * Copyright 2013-2015, All Rights Reserved.
 *
 * Code licensed under the BSD License:
 * https://github.com/node-gh/gh/blob/master/LICENSE.md
 *
 * @author Eduardo Lundgren <edu@rdo.io>
 */

'use strict';

var path = require('path'),
    fs = require('fs'),
    logger = require('../lib/logger'),
    pkg = require('../package.json'),
    semver = require('semver'),
    tracker = require('../lib/tracker'),
    configs = require('../lib/configs');

// Check node version
if (!isCompatibleNodeVersion()) {
    logger.error('Please update your NodeJS version: http://nodejs.org/download');
}

if (!fs.existsSync(configs.getUserHomePath())) {
    configs.createGlobalConfig();
}

// If configs.PLUGINS_PATH_KEY is undefined, try to cache it before proceeding.
if (configs.getConfig()[configs.PLUGINS_PATH_KEY] === undefined) {
    configs.getNodeModulesGlobalPath();
}

// -- Env ------------------------------------------------------------------------------------------
try {
    process.env.GH_PATH = path.join(__dirname, '../');

    require('../lib/cmd.js').run();
} catch (e) {
    tracker.track('error');
    throw e;
}

function isCompatibleNodeVersion() {
    return semver.satisfies(process.version, pkg.engines.node);
}

#!/usr/bin/env node

/*
 * Copyright 2013-2015, All Rights Reserved.
 *
 * Code licensed under the BSD License:
 * https://github.com/node-gh/gh/blob/master/LICENSE.md
 *
 * @author Eduardo Lundgren <edu@rdo.io>
 */

'use strict';

var path = require('path'),
    fs = require('fs'),
    logger = require('../lib/logger'),
    pkg = require('../package.json'),
    semver = require('semver'),
    tracker = require('../lib/tracker'),
    configs = require('../lib/configs');

// Check node version
function isCompatibleNodeVersion() {
    return semver.satisfies(process.version, pkg.engines.node);
}

if (!isCompatibleNodeVersion()) {
    logger.error('Please update your NodeJS version: http://nodejs.org/download');
}

if (!fs.existsSync(configs.getUserHomePath())) {
    configs.createGlobalConfig();
}

// If configs.PLUGINS_PATH_KEY is undefined, try to cache it before proceeding.
if (configs.getConfig()[configs.PLUGINS_PATH_KEY] === undefined) {
    configs.getNodeModulesGlobalPath();
}

// -- Env ------------------------------------------------------------------------------------------
try {
    process.env.GH_PATH = path.join(__dirname, '../');

    require('../lib/cmd.js').run();
} catch (e) {
    tracker.track('error');
    throw e;
}

Fix linting issue. Source formatting.


$( function() {
	if ( !mw.pageTriage ) {
		mw.pageTriage = {};
	}
	mw.pageTriage.viewUtil = {
		// fetch and compile a template, then return it.
		// args: view, template
		template: function( arg ) {
			apiRequest = {
				'action': 'pagetriagetemplate',
				'view': arg.view,
				'format': 'json'
			};

			var templateText;

			if( arg.template instanceof Array ) {
				apiRequest.template = arg.template.join('|');
			} else {
				apiRequest.template = arg.template;
			}

			$.ajax( {
				type: 'post',
				url: mw.util.wikiScript( 'api' ),
				data: apiRequest,
				dataType: 'json',
				async: false,
				success: function( result ) {
					if( result.pagetriagetemplate.result == 'success' ) {
						templateText = result.pagetriagetemplate.template;
					}
				}
			} );

			return _.template( templateText );
		}
	};
} );

$( function() {
	if ( !mw.pageTriage ) {
		mw.pageTriage = {};
	}
	mw.pageTriage.viewUtil = {
		// fetch and compile a template, then return it.
		// args: view, template
		template: function( arg ) {
			apiRequest = {
				'action': 'pagetriagetemplate',
				'view': arg.view,
				'format': 'json'
			};

			var templateText;

			if( arg.template instanceof Array ) {
				apiRequest.template = arg.template.join('|');
			} else {
				apiRequest.template = arg.template;
			}

			$.ajax( {
				type: 'post',
				url: mw.util.wikiScript( 'api' ),
				data: apiRequest,
				dataType: 'json',
				async: false,
				success: function( result ) {
					if ( result.pagetriagetemplate !== undefined && result.pagetriagetemplate.result === 'success' ) {
						templateText = result.pagetriagetemplate.template;
					}
				}
			} );

			return _.template( templateText );
		}
	};
} );

Make sure some results were returned to avoid error.


var AppRouter = Backbone.Router.extend({
  routes: {
    'topics/:topicId': 'showResults',

    '*actions': 'defaultAction'
  },

  showResults: function(topicId) {
    if ($('#topics-container').length === 0) {
      this.defaultAction();
    }
    var resultsView = new ResultsView();
    resultsView.render();
    var topicCharts = new TopicCharts([], { topicId: topicId });
    topicCharts.fetch({
      success: function(response) {
        var topicChartsView = new TopicChartsView({ collection: response.models });
        topicChartsView.render();
        // Ensure that the correct option is displayed as 'selected' in the dropdown.
        $('option:nth-child(' + (parseInt(topicId)+1) + ')').attr('selected', true);
      }
    });
  },

  defaultAction: function() {
    var homeView = new HomeView();
    homeView.render();
  }

});

var AppRouter = Backbone.Router.extend({
  routes: {
    'topics/:topicId': 'showResults',

    '*actions': 'defaultAction'
  },

  showResults: function(topicId) {
    if ($('#topics-container').length === 0) {
      this.defaultAction();
    }
    var resultsView = new ResultsView();
    resultsView.render();
    var topicCharts = new TopicCharts([], { topicId: topicId });
    topicCharts.fetch({
      success: function(response) {
        $('option:nth-child(' + (parseInt(topicId)+1) + ')').attr('selected', true);
        var topicChartsView = new TopicChartsView({ collection: response.models });
        topicChartsView.render();
        // Ensure that the correct option is displayed as 'selected' in the dropdown.
      }
    });
  },

  defaultAction: function() {
    var homeView = new HomeView();
    homeView.render();
  }

});

Fix refresh bug by ensuring the correct dropdown choice is selected


$(function () {
    $('#spending-averages').highcharts({
        chart: {
            type: 'bar'
        },
        title: {
            text: 'Historic World Population by Region'
        },
        subtitle: {
            text: 'Source: Wikipedia.org'
        },
        yAxis: {
            categories: ['Housing', 'Transportation', 'Food', 'Phone', 'Misc'],
            title: {
                text: null
            }
        },
        xAxis: {
            min: 0,
            title: {
                text: 'Population (millions)',
                align: 'high'
            },
            labels: {
                overflow: 'justify'
            }
        },
        tooltip: {
            valueSuffix: ' millions'
        },
        plotOptions: {
            bar: {
                dataLabels: {
                    enabled: true
                }
            }
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'top',
            x: -40,
            y: 80,
            floating: true,
            borderWidth: 1,
            backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'),
            shadow: true
        },
        credits: {
            enabled: false
        },
        series: [{
            name: 'Your spending',
            data: [107, 31, 635, 203, 2]
        }, {
            name: 'Average Spending',
            data: [133, 156, 947, 408, 6]
        }]
    });
});

$(function () {
    $('#spending-averages').highcharts({
        chart: {
            type: 'bar'
        },
        title: {
            text: 'Historic World Population by Region'
        },
        subtitle: {
            text: 'Source: Wikipedia.org'
        },
        yAxis: {
            categories: ['Housing', 'Transportation', 'Food', 'Phone', 'Misc'],
            title: {
                text: null
            }
        },
        xAxis: {
            min: 0,
            title: {
                text: 'Population (millions)',
                align: 'high'
            },
            labels: {
                overflow: 'justify'
            }
        },
        tooltip: {
            valueSuffix: ' millions'
        },
        plotOptions: {
            bar: {
                dataLabels: {
                    enabled: true
                }
            }
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'top',
            x: -40,
            y: 80,
            floating: true,
            borderWidth: 1,
            backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'),
            shadow: true
        },
        credits: {
            enabled: false
        },
        series: [{
            name: 'Your spending',
            data: [107, 31, 635, 203, 5]
        }, {
            name: 'Average Spending',
            data: [35, 15, 7, 3, 30, 10]
        }]
    });
});

Add data for national avrages


/**
 * Helper functions that are used in the other modules to reduce the number of times
 * that code for common tasks is rewritten
 *
 * (c) 2013, Greg Malysa <gmalysa@stanford.edu>
 * Permission to use granted under the terms of the MIT License. See LICENSE for details.
 */

/**
 * Retrieves the name for a function, using fn.name to determine what it is, or if no
 * name is given (i.e. an anonymous function), returns altname. If altname is ALSO not
 * given, returns (anonymous), as a final default value.
 * @param fn Function whose name we want to find
 * @param altname Optional string, name to use if the function was anonymous
 * @return String name of the function
 */
module.exports.fname = function(fn, altname) {
	if (fn.name)
		return fn.name;
	if (altname)
		return altname;
	return '(anonymous)';
}

/**
 * Checks if a function name should be hidden from the call graph because it is an
 * internal function. This is a small hack, but it helps remove internals from the
 * call graph, which simplifies the view for the end user working with his code, all
 * of which exists outsie the library.
 * @param name The function name to test
 * @return bool True if this function name should not be pushed
 */
module.exports.hide_function = function(name) {
	if (name == '__after_glue' || name == '__chain_inner')
		return true;
	return false;
}

/**
 * Helper functions that are used in the other modules to reduce the number of times
 * that code for common tasks is rewritten
 *
 * (c) 2013, Greg Malysa <gmalysa@stanford.edu>
 * Permission to use granted under the terms of the MIT License. See LICENSE for details.
 */

/**
 * Retrieves the name for a function, using fn.name to determine what it is, or if no
 * name is given (i.e. an anonymous function), returns altname. If altname is ALSO not
 * given, returns (anonymous), as a final default value.
 * @param fn Function whose name we want to find
 * @param altname Optional string, name to use if the function was anonymous
 * @return String name of the function
 */
module.exports.fname = function(fn, altname) {
	if (fn.name)
		return fn.name;
	if (altname)
		return altname;
	return '<anonymous>';
}

/**
 * Checks if a function name should be hidden from the call graph because it is an
 * internal function. This is a small hack, but it helps remove internals from the
 * call graph, which simplifies the view for the end user working with his code, all
 * of which exists outsie the library.
 * @param name The function name to test
 * @return bool True if this function name should not be pushed
 */
module.exports.hide_function = function(name) {
	if (name == '__after_glue' || name == '__chain_inner')
		return true;
	return false;
}

Rename anonymous to make the styling more like others


module.exports = {
  // Don't try to find .babelrc because we want to force this configuration.
  babelrc: false,
  presets: [
    [
      require.resolve('babel-preset-env'),
      {
        targets: {
          browsers: ['last 2 versions', 'safari >= 7'],
        },
        modules: false,
      },
    ],
    require.resolve('babel-preset-stage-0'),
    require.resolve('babel-preset-react'),
    require.resolve('babel-preset-minify'),
  ],
  plugins: [
    require.resolve('babel-plugin-transform-regenerator'),
    [
      require.resolve('babel-plugin-transform-runtime'),
      {
        helpers: true,
        polyfill: true,
        regenerator: true,
      },
    ],
  ],
};

module.exports = {
  // Don't try to find .babelrc because we want to force this configuration.
  babelrc: false,
  presets: [
    [
      require.resolve('babel-preset-env'),
      {
        targets: {
          browsers: ['last 2 versions', 'safari >= 7'],
        },
        modules: false,
      },
    ],
    require.resolve('babel-preset-stage-0'),
    require.resolve('babel-preset-react'),
    [
      require.resolve('babel-preset-minify'),
      {
        mangle: false,
      },
    ],
  ],
  plugins: [
    require.resolve('babel-plugin-transform-regenerator'),
    [
      require.resolve('babel-plugin-transform-runtime'),
      {
        helpers: true,
        polyfill: true,
        regenerator: true,
      },
    ],
  ],
};

Set mangle to false in babel-preset-minify for polymer to fix static build


jQuery(function($) {

   /* tab insertion handling */
   $('#code').keydown(function(e) {
      if (e.keyCode == 9 && !e.ctrlKey && !e.altKey) {
         if (this.setSelectionRange) {
            var start = this.selectionStart;
            var end = this.selectionEnd;
            var top = this.scrollTop;
            this.value = this.value.slice(0, start) + '\t' + this.value.slice(end);
            this.setSelectionRange(start + 1, start + 1);
            this.scrollTop = top;
            e.preventDefault();
         }
         else if (document.selection.createRange) {
            this.selection = document.selection.createRange();
            this.selection.text = '\t';
            e.returnValue = false;
         }
      }
   })

   $('#paste').click(function(e) {
      var doc = {};
      doc.title = $('#title').val().trim();
      doc.content = $('#code').val().trim();
      var tags = $('#tags').val().split(',');
      doc.tags = tags.map(function(t) {return t.trim()});
      $Couch.create(doc, './ddoc/_update/create').done(function (data) {
            window.location.pathname += data._id;
      })
      return false;
      //e.preventDefault();
   })

})

jQuery(function($) {

   /* tab handling - gemo style */
   $('#code').keydown(function(e) {
      if (e.keyCode == 9 && !e.ctrlKey && !e.altKey) {
         if (this.setSelectionRange) {
            var start = this.selectionStart;
            var end = this.selectionEnd;
            var top = this.scrollTop;
            var selected = this.value.slice(start, end);
            if (e.shiftKey) {
               // deindent
               var replacement = selected.replace(/^\t/gm, '');
            } else {
               // indent
               var replacement = selected.replace(/^/gm, '\t');
            }
            this.value = this.value.slice(0, start) + replacement + this.value.slice(end);
            this.setSelectionRange(start, end + replacement.length - selected.length );
            this.scrollTop = top;
            e.preventDefault();
         }
         else if (document.selection.createRange) {
            this.selection = document.selection.createRange();
            this.selection.text = '\t';
            e.returnValue = false;
         }
      }
   })

   $('#paste').click(function(e) {
      var doc = {};
      doc.title = $('#title').val().trim();
      doc.content = $('#code').val().trim();
      var tags = $('#tags').val().split(',');
      doc.tags = tags.map(function(t) {return t.trim()});
      $Couch.create(doc, './ddoc/_update/create').done(function (data) {
            window.location.pathname += data._id;
      })
      return false;
      //e.preventDefault();
   })

})

Indent and deindent selected block of text - gemo style


// Program that identifies common element(s) that exist within both two arrays

function intersection(firstArray, secondArray) {
	var hashMap = {};
	var commonElements = [];

	// create hashmap with elements of first array as keys
	arrOne.forEach(function(element) {
		hashMap[element] = 1;
	})
}

// Program that identifies common element(s) that exist within both two arrays

function intersection(firstArray, secondArray) {
	var hashMap = {};
	var commonElements = [];

	// create hashmap with elements of first array as keys
	arrOne.forEach(function(element) {
		hashMap[element] = 1;
	})

	// use hashmap's O(1) look up time to check if an element in second array exists in the hash (i.e. first array)
	secondArray.forEach(function(element) { // iterate through entire second array
		if (hashMap[element] === 1) { // if element in second array exists in hashmap
			commonElements.push(element); // add matching element into output array
		}
	});
}

Use hashmap's O(1) look up time to check if an element in second array exists in the hash (i.e. first array), iterating through entire second array


module.exports = {
  resolve: {
    alias: {
      // Use non-compiled version of the following libraries
      'reselect': 'reselect/src/index.js',

      // Use non-compiled version of the following react libraries
      'react-icon-base': 'react-icon-base/index.js',
      'react-collapse': 'react-collapse/src/index.js',
      'react-height': 'react-height/src/index.js',
      'react-i18next': 'react-i18next/src/index.js',
      'react-sortable-hoc': 'react-sortable-hoc/dist/es6'
    }
  }
}

module.exports = {
  resolve: {
    alias: {
      // Use non-compiled version of the following libraries
      'reselect': 'reselect/src/index.js',
      'react-redux-firebase': 'react-redux-firebase/es'
    }
  }
}

Use ES module of react-redux-firebase


requirejs.config({
	paths: {
		'jquery': './lib/components/jquery/dist/jquery.min'
	}
});

require( [ 'src/graph' ] , function( Graph ) {

	var functions = [

function( domGraph, domSource ) {

	var g1 = new Graph( domGraph );

	var serie = g1.newSerie("serieTest")
					.setLabel( "My serie" )
					.autoAxis()
					.setData( [ [1, 2], [2, 5], [3, 10] ] )
					.showMarkers( true )
					.setMarkerType( 1 );

	var serie = g1.newSerie("serieTest")
					.setLabel( "My serie 2" )
					.autoAxis()
					.setData( [ [2, 4], [3, 1], [5, 20] ] )
					.setLineColor('red');

	var legend = g1.makeLegend({
		frame: true,
		frameWidth: 1,
		frameColor: "green",
		backgroundColor: "blue"
	});

	g1.redraw( );
	g1.drawSeries();
}

	]

	for( var i = 0, l = functions.length ; i < l ; i ++ ) {

		functions[ i ]("example-1-graph");
		$("#example-1-source").html( functions[ i ].toString() );

	}

} );

requirejs.config({
	paths: {
		'jquery': './lib/components/jquery/dist/jquery.min'
	}
});

require( [ 'src/graph' ] , function( Graph ) {

	var functions = [

function( domGraph ) {

	var graph = new Graph( domGraph );

	graph.newSerie("serieTest")
		.setLabel( "My serie" )
		.autoAxis()
		.setData( [ [1, 2], [2, 5], [3, 10] ] )
		.showMarkers( true )
		.setMarkerType( 1 );

	graph.newSerie("serieTest")
		.setLabel( "My serie 2" )
		.autoAxis()
		.setData( [ [2, 4], [3, 1], [5, 20] ] )
		.setLineColor('red');

	graph.makeLegend({
		frame: true,
		frameWidth: 1,
		frameColor: "green",
		backgroundColor: "blue"
	});

	graph.redraw( );
	graph.drawSeries();
}

	]

	for( var i = 0, l = functions.length ; i < l ; i ++ ) {

		functions[ i ]("example-1-graph");
		$("#example-1-source").html( functions[ i ].toString() );

	}

} );

Update script for the beauty of it


$(function(){
  $(".tablesorter").tablesorter();
  $("tr[data-link]").click(function() {
    window.location = $(this).data("link")
  });
  console.log('Scripts loaded.');
});

var tablesort = function() {
  $(".tablesorter").tablesorter();
  console.log('Tablesorter loaded.');
};

$(document).on('turbolinks:load', tablesort);

Load js on turbolink refresh


import DS from 'ember-data';

import OsfModel from './osf-model';

/**
 * @module ember-osf
 * @submodule models
 */

/**
 * Model for OSF APIv2 file versions. Primarily used in relationship fields.
 * This model is used for basic file version metadata. To interact with file contents directly, see the `file-manager` service.
 * For field and usage information, see:
 * * https://api.osf.io/v2/docs/#!/v2/File_Versions_List_GET
 * * https://api.osf.io/v2/docs/#!/v2/File_Version_Detail_GET
 * @class FileVersion
*/
export default OsfModel.extend({
    size: DS.attr('number'),
    contentType: DS.attr('fixstring')
});

import DS from 'ember-data';

import OsfModel from './osf-model';

/**
 * @module ember-osf
 * @submodule models
 */

/**
 * Model for OSF APIv2 file versions. Primarily used in relationship fields.
 * This model is used for basic file version metadata. To interact with file contents directly, see the `file-manager` service.
 * For field and usage information, see:
 * * https://api.osf.io/v2/docs/#!/v2/File_Versions_List_GET
 * * https://api.osf.io/v2/docs/#!/v2/File_Version_Detail_GET
 * @class FileVersion
*/
export default OsfModel.extend({
    size: DS.attr('number'),
    dateCreated: DS.attr('date'),
    contentType: DS.attr('fixstring')
});

Add dateCreated to file version model


angular
  .module('app')
  .factory('MetaMachine', function($rootScope) {
    var MetaMachine = {
      title: function(pageTitle, baseTitle) {
        baseTitle = typeof baseTitle != 'undefined' ? baseTitle : "Rootstrikers";
        $rootScope.title = typeof pageTitle != 'undefined' ? pageTitle + " | " + baseTitle : baseTitle;
      },
      description: function(description) {
        $rootScope.metaDescription = description || "We fight the corrupting influence of money in politics";
      }
    };
    return MetaMachine;
  });

angular
  .module('app')
  .factory('MetaMachine', function($rootScope) {

    var metaDefaults = {
      metaTitle: "Home | Rootstrikers",
      metaDescription: "We fight the corrupting influence of money in politics",
      metaImage: "http://facultycreative.com/img/icons/facultyicon114.png",
      metaUrl: "http://rs002dev.herokuapp.com/"
    };

    (function setDefaults() {
      _.each(metaDefaults, function(val, key) { $rootScope[key] = val; });
    })();

    var MetaMachine = {
      title: function(pageTitle, baseTitle) {
        baseTitle = typeof baseTitle != 'undefined' ? baseTitle : "Rootstrikers";
        $rootScope.metaTitle = typeof pageTitle != 'undefined' ? pageTitle + " | " + baseTitle : baseTitle;
      },
      description: function(description) {
        $rootScope.metaDescription = description || "We fight the corrupting influence of money in politics";
      },
      image: function(url) {
        $rootScope.metaImage = url || "http://facultycreative.com/img/icons/facultyicon114.png";
      },
      url: function(url) {
        $rootScope.metaUrl = url || "http://rs002dev.herokuapp.com/";
      }
    };
    return MetaMachine;
  });

Update MetaMachine directive to add a metaImage tag and metaUrl tag (OG tags for Facebook). Directive now also sets page defaults.


// @flow

import type { SectionType } from "../enums/Section.js";

import { ReduceStore } from "flux/utils";
import UniversalDispatcher from "./UniversalDispatcher.js";
import { Record } from "immutable";
import Section from "../enums/Section.js";
import url from "../utils/url.js";

export type NavigationActionType = {
  type: "SET_SECTION",
  section: SectionType,
  url: string,
  fromUrl: ?boolean,
};
// TODO: Remove showsplash argument
const DEFAULT_STATE = {
  section: Section.FindProjects,
  url: url.section(Section.FindProjects, { showSplash: 1 }),
};

class State extends Record(DEFAULT_STATE) {
  section: SectionType;
  url: string;
}

class NavigationStore extends ReduceStore<State> {
  constructor(): void {
    super(UniversalDispatcher);
  }

  getInitialState(): State {
    const state = new State();
    return state;
  }

  reduce(state: State, action: NavigationActionType): State {
    switch (action.type) {
      case "SET_SECTION":
        if (action.fromUrl) {
          history.replaceState({}, "", action.url);
        } else {
          history.pushState({}, "", action.url);
        }
        return state.set("section", action.section);
      default:
        (action: empty);
        return state;
    }
  }

  getSection(): SectionType {
    return this.getState().section;
  }
}

export default new NavigationStore();

// @flow

import type { SectionType } from "../enums/Section.js";

import { ReduceStore } from "flux/utils";
import UniversalDispatcher from "./UniversalDispatcher.js";
import { Record } from "immutable";
import Section from "../enums/Section.js";
import url from "../utils/url.js";

export type NavigationActionType = {
  type: "SET_SECTION",
  section: SectionType,
  url: string,
  fromUrl: ?boolean,
};
// TODO: Remove showsplash argument
const DEFAULT_STATE = {
  section: Section.Home,
  url: url.section(Section.Home),
};

class State extends Record(DEFAULT_STATE) {
  section: SectionType;
  url: string;
}

class NavigationStore extends ReduceStore<State> {
  constructor(): void {
    super(UniversalDispatcher);
  }

  getInitialState(): State {
    const state = new State();
    return state;
  }

  reduce(state: State, action: NavigationActionType): State {
    switch (action.type) {
      case "SET_SECTION":
        if (action.fromUrl) {
          history.replaceState({}, "", action.url);
        } else {
          history.pushState({}, "", action.url);
        }
        return state.set("section", action.section);
      default:
        (action: empty);
        return state;
    }
  }

  getSection(): SectionType {
    return this.getState().section;
  }
}

export default new NavigationStore();

Change default section to Home


// Based on "Continous Redrawing of Objects"
// http://emberjs.com/guides/cookbook/working_with_objects/continuous_redrawing_of_views/
//
// #pulse is updated every ~15-seconds
//
var ClockService = Ember.Object.extend({
  pulse: Ember.computed.oneWay('_minutes').readOnly(),
  tick: function () {
    var clock = this;
    Ember.run.later(function () {
      var minutes = clock.get('_minutes');
      if (typeof minutes === 'number') {
        clock.set('_minutes', minutes + (1/4));
      }
    }, 15000);
  }.observes('_minutes').on('init'),
  _minutes: 0
});

var ClockServiceInitializer = {
  name: "clock-service",

  initialize: function(container, application) {
    container.register('clock:service', ClockService, { singleton: true });
    application.inject('view', 'clock', 'clock:service');
  }
};

export default ClockServiceInitializer;

// Based on "Continous Redrawing of Objects"
// http://emberjs.com/guides/cookbook/working_with_objects/continuous_redrawing_of_views/
//
// #pulse is updated every ~15-seconds
//
var ClockService = Ember.Object.extend({
  pulse: Ember.computed.oneWay('_minutes').readOnly(),
  tick: function () {
    var clock = this;
    // This should be the idiomatic `Ember.run.later` but that
    // blocks acceptance tests. This is a workaround from
    // https://github.com/emberjs/ember.js/issues/3008
    setTimeout(function() {
      Em.run(function() {
        var minutes = clock.get('_minutes');
        if (typeof minutes === 'number') {
          clock.set('_minutes', minutes + (1/4));
        }
      })
    }, 15000);
  }.observes('_minutes').on('init'),
  _minutes: 0
});

var ClockServiceInitializer = {
  name: "clock-service",

  initialize: function(container, application) {
    container.register('clock:service', ClockService, { singleton: true });
    application.inject('view', 'clock', 'clock:service');
  }
};

export default ClockServiceInitializer;

Fix for stalling acceptance tests.


import _ from 'lodash'
import postcss from 'postcss'

function buildMediaQuery(breakpoint) {
  if (_.isString(breakpoint)) {
    breakpoint = {min: breakpoint}
  }
  return _(breakpoint).map((value, feature) => {
      feature = _.get(
        {
          min: 'min-width',
          max: 'max-width',
        },
        feature,
        feature
      )
      return `(${feature}: ${value})`
    }).join(' and ')
}

export default function(options) {
  let breakpoints = options.breakpoints

  return function(css) {
    Object.keys(breakpoints).forEach(breakpoint => {
      const variableName = `--breakpoint-${breakpoint}`
      const mediaQuery = buildMediaQuery(breakpoints[breakpoint])
      const rule = postcss.atRule({
        name: 'custom-media',
        params: `${variableName} ${mediaQuery}`,
      })
      css.prepend(rule)
    })
  }
}

import _ from 'lodash'
import postcss from 'postcss'

function buildMediaQuery(breakpoints) {
  if (_.isString(breakpoints)) {
    breakpoints = {min: breakpoints}
  }
  if (!_.isArray(breakpoints)) {
    breakpoints = [breakpoints]
  }
  return _(breakpoints).map((breakpoint) => {
    return _(breakpoint).map((value, feature) => {
        feature = _.get(
          {
            min: 'min-width',
            max: 'max-width',
          },
          feature,
          feature
        )
        return `(${feature}: ${value})`
      }).join(' and ')
  }).join(', ')
}

export default function(options) {
  let breakpoints = options.breakpoints

  return function(css) {
    Object.keys(breakpoints).forEach(breakpoint => {
      const variableName = `--breakpoint-${breakpoint}`
      const mediaQuery = buildMediaQuery(breakpoints[breakpoint])
      const rule = postcss.atRule({
        name: 'custom-media',
        params: `${variableName} ${mediaQuery}`,
      })
      css.prepend(rule)
    })
  }
}

Add ability to define more complex breakpoints.


/* eslint-disable import/prefer-default-export */
import React from 'react';

/**
 * Hook to simplify the use of the native date picker component by unwrapping
 * the callback event and firing the callback only when the date is changing,
 * providing a value to conditionally render the native picker and a callback
 * to set the render value.
 *
 * Pass an onChange callback which will be called when a new date is selected
 * from the datepicker and not when cancelled or dismissed, with a JS date object
 * rather than a nativeEvent.
 *
 * @param  {Func}  callback callback
 * @return {Array} [
 * datePickerIsOpen: boolean indicator whether the date picker is open.
 * openDatePicker: Callback function to set the datePickerIsOpen to true.
 * datePickerCallback: Wrapped callback, triggered on changing the date in the picker,
 * returning a JS date object.
 * ]
 */
export const useDatePicker = onChangeCallback => {
  const [datePickerIsOpen, setDatePickerIsOpen] = React.useState(false);

  const datePickerCallback = React.useCallback(
    event => {
      setDatePickerIsOpen(false);
      const { type, nativeEvent } = event;
      if (type === 'set' && onChangeCallback) {
        const { timestamp } = nativeEvent;
        onChangeCallback(new Date(timestamp));
      }
    },
    [onChangeCallback]
  );

  const openDatePicker = React.useCallback(() => {
    setDatePickerIsOpen(true);
  }, []);

  return [datePickerIsOpen, openDatePicker, datePickerCallback];
};

/* eslint-disable import/prefer-default-export */
import React from 'react';

/**
 * Hook to simplify the use of the native date picker component by unwrapping
 * the callback event and firing the callback only when the date is changing,
 * providing a value to conditionally render the native picker and a callback
 * to set the render value.
 *
 * Pass an onChange callback which will be called when a new date is selected
 * from the datepicker and not when cancelled or dismissed, with a JS date object
 * rather than a nativeEvent.
 *
 * @param  {Func}  callback callback
 * @return {Array} [
 * datePickerIsOpen: boolean indicator whether the date picker is open.
 * openDatePicker: Callback function to set the datePickerIsOpen to true.
 * datePickerCallback: Wrapped callback, triggered on changing the date in the picker,
 * returning a JS date object.
 * ]
 */
export const useDatePicker = onChangeCallback => {
  const [datePickerIsOpen, setDatePickerIsOpen] = React.useState(false);

  const datePickerCallback = React.useCallback(
    event => {
      setDatePickerIsOpen(false);
      const { type, nativeEvent } = event;
      if (type === 'set' && onChangeCallback) {
        const { timestamp } = nativeEvent;

        onChangeCallback(timestamp);
      }
    },
    [onChangeCallback]
  );

  const openDatePicker = React.useCallback(() => {
    setDatePickerIsOpen(true);
  }, []);

  return [datePickerIsOpen, openDatePicker, datePickerCallback];
};

Add pass timestamp rather than date object


import { createSelector } from 'reselect';
import { denormalize } from 'normalizr';
import mapValues from 'lodash/mapValues';

import teamSchema from './schema';

const selectPlayers = state => state.data.players;

export const selectTeam = (state, props) => state.data.teams.byId[props.teamId];
export const selectTeams = state => state.data.teams;
export const selectTeamPlayerItems = (state, props) => state.data.teams.byId[props.teamId].players;

export const selectDenormalizedTeams = createSelector(
  [selectTeams, selectPlayers],
  (teams, players) => {
    const data = { teams, players };
    return denormalize(
      Object.keys(teams.byId),
      [teamSchema],
      { ...mapValues(data, value => value.byId) },
    );
  },
);

import { createSelector } from 'reselect';
import { denormalize } from 'normalizr';
import mapValues from 'lodash/mapValues';

import teamSchema from './schema';

const selectPlayers = state => state.data.players;

export const selectTeam = (state, props) => state.data.teams.byId[props.teamId];
export const selectTeams = state => state.data.teams;

export const selectTeamPlayerItems = (state, props) => {
  const team = selectTeam(state, props);
  return team ? team.players : [];
};

export const selectDenormalizedTeams = createSelector(
  [selectTeams, selectPlayers],
  (teams, players) => {
    const data = { teams, players };
    return denormalize(
      Object.keys(teams.byId),
      [teamSchema],
      { ...mapValues(data, value => value.byId) },
    );
  },
);

Reset response errors when a new tactic is created


// Download the helper library from https://www.twilio.com/docs/python/install

// Your Account Sid and Auth Token from twilio.com/console
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = require('twilio')(accountSid, authToken);

// Replace 'UAXXX...' with your Assistant's unique SID https://www.twilio.com/console/autopilot/list
query = client.preview.understand.assistants('UAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
                                 .queries
                                 .create({
                                   language: 'en-US',
                                   query: 'Tell me a joke',
                                 })
                                 .then(query => console.log(query.results.task))
                                 .done();

// Download the helper library https://www.twilio.com/docs/libraries/node#install

// Your Account Sid and Auth Token from twilio.com/console
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = require('twilio')(accountSid, authToken);

// Replace 'UAXXX...' with your Assistant's unique SID https://www.twilio.com/console/autopilot/list
query = client.preview.understand.assistants('UAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
                                 .queries
                                 .create({
                                   language: 'en-US',
                                   query: 'Tell me a joke',
                                 })
                                 .then(query => console.log(query.results.task))
                                 .done();

Update comment to point to node library install


var log4js = require('log4js');
var logger = log4js.getLogger();
var express = require('express');
var favicon = require('serve-favicon');
var bodyParser = require('body-parser');
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
var ipaddress = process.env.OPENSHIFT_NODEJS_IP;
var loglevel = process.env.LOGLEVEL || 'DEBUG';

var app = express();
app.use(favicon(__dirname + '/public/favicon.ico'));

logger.setLevel(loglevel);
app.use(express.static('public'));

app.use(log4js.connectLogger(log4js.getLogger('http'), { level: 'auto' }));
app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.raw({limit: '10mb', type: 'image/jpeg'}));

app.use('/api/', require('./routes/').router);

/* app.use(function(error, req, res, next) {
	if (error) {
		logger.error('InvalidInput', error.message);
		res.status(error.status).send({error: 'InvalidInput', description: error.message});
	} else {
		next();
	}
}); */

app.listen(port, ipaddress, function () {
	logger.info('starting rikitrakiws', this.address());
});

var log4js = require('log4js');
var logger = log4js.getLogger();
var express = require('express');
var favicon = require('serve-favicon');
var bodyParser = require('body-parser');
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
var ipaddress = process.env.OPENSHIFT_NODEJS_IP;
var loglevel = process.env.LOGLEVEL || 'DEBUG';

var app = express();
app.use(favicon(__dirname + '/public/favicon.ico'));

logger.setLevel(loglevel);
app.use(express.static('public'));

app.use(log4js.connectLogger(log4js.getLogger('http'), { level: 'auto' }));
app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.raw({limit: '10mb', type: 'image/jpeg'}));

app.use('/api/', require('./routes/').router);

app.use(function (req, res, next) {
	res.removeHeader("WWW-Authenticate");
	next();
});

/* app.use(function(error, req, res, next) {
	if (error) {
		logger.error('InvalidInput', error.message);
		res.status(error.status).send({error: 'InvalidInput', description: error.message});
	} else {
		next();
	}
}); */

app.listen(port, ipaddress, function () {
	logger.info('starting rikitrakiws', this.address());
});

Drop header to avoid auth browser popup


module.exports = {
  rules: {
    // require trailing comma in multilines
    'comma-dangle': [2, 'always-multiline'],
    // require function expressions to have a name
    'func-names': 0,
    // require or disallow use of semicolons instead of ASI
    'semi': [2, 'never'],
    // require or disallow space before function opening parenthesis
    'space-before-function-paren': [2, 'never'],
    // require or disallow Yoda conditions
    'yoda': [2, 'never']
  }
}

module.exports = {
  rules: {
    // disallow trailing commas in object literals
    'comma-dangle': [2, 'never'],
    // require function expressions to have a name
    'func-names': 0,
    // require or disallow use of semicolons instead of ASI
    'semi': [2, 'never'],
    // require or disallow space before function opening parenthesis
    'space-before-function-paren': [2, 'never'],
    // require or disallow Yoda conditions
    'yoda': [2, 'never']
  }
}

Revert "[WV][000000] Allow trailing comma"


function sortIconsBySize(icons) {
    return icons.sort((a, b) => {
        if (a.data.size < b.data.size) {
            return 1;
        } else {
            return -1;
        }
    });
}

function findBestIcon(icons) {
    return sortIconsBySize(icons)[0];
}

module.exports = findBestIcon;

function sortIconsBySize(icons) {
    return icons.sort((a, b) => {
        if (a.size < b.size) {
            return 1;
        } else {
            return -1;
        }
    });
}

function findBestIcon(icons) {
    return sortIconsBySize(icons)[0];
}

module.exports = findBestIcon;

Fix bug where icons are not sorted properly


browser.storage.local.get( [ 'bgcolor', 'textcolor', 'messages' ] ).then( function ( r ) {
	var  m = r.messages.split( '\n' );
	m = m[ Math.floor( Math.random() * m.length ) ];

	document.querySelector( 'h1' ).textContent = m;
	document.body.style.backgroundColor = r.bgcolor;
	document.body.style.color = r.textcolor;
	console.log( r );
} );

browser.storage.local.get( [ 'bgcolor', 'textcolor', 'messages' ] ).then( function ( r ) {
	var  m = r.messages || 'Breathe';

	m = m.split( '\n' );
	m = m[ Math.floor( Math.random() * m.length ) ];

	document.querySelector( 'h1' ).textContent = m;
	document.body.style.backgroundColor = r.bgcolor || '#fff';
	document.body.style.color = r.textcolor || '#b3b3b3';
	console.log( r );
} );

Load sane settings if there are none


// @flow

import { connect } from 'lib/utils/redux-utils';
import * as React from 'react';
import { ActivityIndicator } from 'react-native';

import type { AppState } from '../redux/redux-setup';
import type { Colors } from '../themes/colors';
import { colorsSelector, styleSelector } from '../themes/colors';

type Props = {|
  // Redux state
  colors: Colors,
  styles: typeof styles,
|};
function ListLoadingIndicator(props: Props) {
  const { listBackgroundLabel } = props.colors;
  return (
    <ActivityIndicator
      color={listBackgroundLabel}
      size="large"
      style={props.styles.loadingIndicator}
    />
  );
}

const styles = {
  loadingIndicator: {
    backgroundColor: 'listBackground',
    flex: 1,
    padding: 10,
  },
};
const stylesSelector = styleSelector(styles);

export default connect((state: AppState) => ({
  colors: colorsSelector(state),
  styles: stylesSelector(state),
}))(ListLoadingIndicator);

// @flow

import * as React from 'react';
import { ActivityIndicator } from 'react-native';

import { useStyles, useColors } from '../themes/colors';

function ListLoadingIndicator() {
  const styles = useStyles(unboundStyles);
  const colors = useColors();
  const { listBackgroundLabel } = colors;
  return (
    <ActivityIndicator
      color={listBackgroundLabel}
      size="large"
      style={styles.loadingIndicator}
    />
  );
}

const unboundStyles = {
  loadingIndicator: {
    backgroundColor: 'listBackground',
    flex: 1,
    padding: 10,
  },
};

export default ListLoadingIndicator;

Use hook instead of connect functions and HOC in ListLoadingIndicator


function Population(size) {
	var agents = new Array(size);
	var genomes = new Array(size);
	for (i = 0; i < size; i++) {
		var prob = Math.random();
		if (prob <= 0.33) {
			genomes[i] = new Genome(1,0,0);
		}
		elseif (prob > 0.33 && prob <= 0.67) {
			genomes[i] = new Genome(0,1,0);
		}
		else genomes[i] = new Genome(0,0,1);
		agents[i] = new Agent(genomes[i]);
	}
	this.pop = agents;
}

// "T" for tournament, "R" for roulette wheel
var parentmethod = "T";

Population.prototype.parentselection = function() {
	// Get all fitness functions from parents
	if (parentmethod == "T") {

		// Choose parents

		// return parents
	}
	else if (parentmethod == "R") {

	}
}

function Population(size) {
	var agents = new Array(size);
	var genomes = new Array(size);
	for (i = 0; i < size; i++) {
		var prob = Math.random();
		if (prob < 0.33) {
			genomes[i] = new Genome(1,0,0);
		}
		else if (prob >= 0.33 && prob < 0.67) {
			genomes[i] = new Genome(0,1,0);
		}
		else genomes[i] = new Genome(0,0,1);
		agents[i] = new Agent(genomes[i]);
	}
	this.pop = agents;
}

// "T" for tournament, "R" for roulette wheel
var parentmethod = "T";

Population.prototype.parentselection = function() {
	// Get all fitness functions from parents
	var fitness = new Array(this.pop.length);
	for (i = 0; i < this.pop.length; i++) {
		fitness[i] = this.pop[i].getFitness();
	}
	// Tournament selection
	if (parentmethod == "T") {
		// Choose k individuals from population at random
		for (p = 0; p < 4; p++) {
			var k = 3;
			var parents = new Array(k);
			for (i = 0; i < tournament; i ++) {
				parents[i] = Math.round(Math.random() * this.pop.length);
			}

		}
		// return parents
	}

	// Roulette wheel selection
	else if (parentmethod == "R") {

	}
}

Population.prototype.update = function() {

}

Edit parent selection, update gamemanager to Senna's version


import Ember from 'ember';
import jquiWidget from 'ember-cli-jquery-ui/mixins/jqui-widget';

export default Ember.TextField.extend(jquiWidget, {
  uiType: 'datepicker',
  uiOptions: ["altField", "altFormat", "appendText", "autoSize",
    "beforeShow", "beforeShowDay", "buttonImage", "buttonImageOnly",
    "buttonText", "calculateWeek", "changeMonth", "changeYear", "closeText",
    "constrainInput", "currentText", "dateFormat", "dayNames", "dayNamesMin",
    "dayNamesShort", "defaultDate", "duration", "firstDay", "gotoCurrent",
    "hideIfNoPrevNext", "isRTL", "maxDate", "minDate", "monthNames",
    "monthNamesShort", "navigationAsDateFormat", "nextText", "numberOfMonths",
    "onChangeMonthYear", "onClose", "onSelect", "prevText",
    "selectOtherMonths", "shortYearCutoff", "showAnim", "showButtonPanel",
    "showCurrentAtPos", "showMonthAfterYear", "showOn", "showOptions",
    "showOtherMonths", "showWeek", "stepMonths", "weekHeader", "yearRange",
    "yearSuffix"],
  uiEvents: ['onChangeMonthYear', 'onClose', 'onSelect']
});

import Ember from 'ember';
import jquiWidget from 'ember-cli-jquery-ui/mixins/jqui-widget';

export default Ember.TextField.extend(jquiWidget, {
  uiType: 'datepicker',
  uiOptions: ["altField", "altFormat", "appendText", "autoSize",
    "beforeShow", "beforeShowDay", "buttonImage", "buttonImageOnly",
    "buttonText", "calculateWeek", "changeMonth", "changeYear", "closeText",
    "constrainInput", "currentText", "dateFormat", "dayNames", "dayNamesMin",
    "dayNamesShort", "defaultDate", "duration", "firstDay", "gotoCurrent",
    "hideIfNoPrevNext", "isRTL", "maxDate", "minDate", "monthNames",
    "monthNamesShort", "navigationAsDateFormat", "nextText", "numberOfMonths",
    "onChangeMonthYear", "onClose", "onSelect", "prevText",
    "selectOtherMonths", "shortYearCutoff", "showAnim", "showButtonPanel",
    "showCurrentAtPos", "showMonthAfterYear", "showOn", "showOptions",
    "showOtherMonths", "showWeek", "stepMonths", "weekHeader", "yearRange",
    "yearSuffix"]
});

Remove useless events that don't exist


Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() {
    return Meteor.subscribe('notifications');
  }
});

Router.route('/posts/:_id', {
  name: 'postPage',

  waitOn: function() {
    return Meteor.subscribe('comments', this.params._id);
  },

  data: function() {
    return Posts.findOne(this.params._id);
  }
});

Router.route('posts/:_id/edit', {
  name: 'postEdit',
  data: function() {
    return Posts.findOne(this.params._id);
  }
});

Router.route('/submit', { name: 'postSubmit' });

Router.route('/:postsLimit?', {
  name: 'postsList',
  waitOn: function() {
    var limit = parseInt(this.params.postsLimit) || 5;
    return Meteor.subscribe('posts', { sort: { submitted: -1 }, limit: limit });
  }
});

var requireLogin = function() {
  if (!Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render(this.loadingTemplate);
    } else {
      this.render('accessDenied');
    }
  } else {
    this.next();
  }
}

Router.onBeforeAction('dataNotFound', { only: 'postPage' });
Router.onBeforeAction(requireLogin, { only: 'postSubmit' });

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() {
    return Meteor.subscribe('notifications');
  }
});

Router.route('/posts/:_id', {
  name: 'postPage',

  waitOn: function() {
    return Meteor.subscribe('comments', this.params._id);
  },

  data: function() {
    return Posts.findOne(this.params._id);
  }
});

Router.route('posts/:_id/edit', {
  name: 'postEdit',
  data: function() {
    return Posts.findOne(this.params._id);
  }
});

Router.route('/submit', { name: 'postSubmit' });

Router.route('/:postsLimit?', {
  name: 'postsList',
  waitOn: function() {
    var limit = parseInt(this.params.postsLimit) || 5;
    return Meteor.subscribe('posts', { sort: { submitted: -1 }, limit: limit });
  },
  data: function() {
    var limit = parseInt(this.params.postsLimit) || 5;

    return {
      posts: Posts.find({}, { sort: { submitted: -1 }, limit: limit });
    }
  }
});

var requireLogin = function() {
  if (!Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render(this.loadingTemplate);
    } else {
      this.render('accessDenied');
    }
  } else {
    this.next();
  }
}

Router.onBeforeAction('dataNotFound', { only: 'postPage' });
Router.onBeforeAction(requireLogin, { only: 'postSubmit' });

Add dataContext to postsLimit route


var subscriptions = new SubsManager();

Router.configure({
	layoutTemplate: 'layout',
	loadingTemplate: 'loading',
	notFoundTemplate: 'notFound'
});

Router.route('/', {
	name: 'home',
	waitOn: function() {
		return [subscriptions.subscribe('lastGames'), subscriptions.subscribe('allUsers')];
	},
	fastRender: true
});

Router.route('/ranking', {
	name: 'rankingWrapper',
	/*waitOn: function() {
		return subscriptions.subscribe('');
	},*/
	fastRender: true
});

Router.route('/championship', {
	name: 'ChampionshipWrapper',
	/*waitOn: function() {
		return subscriptions.subscribe('');
	},*/
	fastRender: true
});

Router.route('/search', {
	name: 'search',
	/*waitOn: function() {
		return subscriptions.subscribe('');
	},*/
	fastRender: true
});

Router.route('/account', {
	name: 'accountWrapper',
	fastRender: true
});

var subscriptions = new SubsManager();

Router.configure({
	layoutTemplate: 'layout',
	loadingTemplate: 'loading',
	notFoundTemplate: 'notFound'
});

Router.route('/', {
	name: 'home',
	waitOn: function() {
		return [subscriptions.subscribe('lastGames'), subscriptions.subscribe('allUsers')];
	},
	fastRender: true
});

Router.route('/ranking', {
	name: 'rankingWrapper',
	waitOn: function() {
		return subscriptions.subscribe('allUsers');
	},
	data: function() {
		return Meteor.users.find({}, {
			fields: {
				'profile.firstName': 1,
				'profile.lastName': 1,
				'profile.points': 1
			}
		});
	},
	fastRender: true
});

Router.route('/championship', {
	name: 'ChampionshipWrapper',
	/*waitOn: function() {
		return subscriptions.subscribe('');
	},*/
	fastRender: true
});

Router.route('/search', {
	name: 'search',
	/*waitOn: function() {
		return subscriptions.subscribe('');
	},*/
	fastRender: true
});

Router.route('/account', {
	name: 'accountWrapper',
	fastRender: true
});

Add data for ranking route


/*
 * Copyright (c) 2014-2020 Bjoern Kimminich.
 * SPDX-License-Identifier: MIT
 */

const chai = require('chai')
const expect = chai.expect

describe('webhook', () => {
  const webhook = require('../../lib/webhook')

  const challenge = {
    key: 'key',
    name: 'name'
  }

  describe('notify', () => {
    it('fails when no webhook URL is provided via environment variable', () => {
      expect(() => webhook.notify(challenge)).to.throw('options.uri is a required argument')
    })

    it('fails when supplied webhook is not a valid URL', () => {
      expect(() => webhook.notify(challenge, 'localhorst')).to.throw('Invalid URI "localhorst"')
    })

    it('submits POST with payload to existing URL', () => {
      expect(() => webhook.notify(challenge, 'https://webhook.site/46beb3e9-df8f-495b-98b9-abf0d4ae38a0')).to.not.throw()
    })
  })
})

/*
 * Copyright (c) 2014-2020 Bjoern Kimminich.
 * SPDX-License-Identifier: MIT
 */

const chai = require('chai')
const expect = chai.expect

describe('webhook', () => {
  const webhook = require('../../lib/webhook')

  const challenge = {
    key: 'key',
    name: 'name'
  }

  describe('notify', () => {
    it('fails when no webhook URL is provided via environment variable', () => {
      expect(() => webhook.notify(challenge)).to.throw('options.uri is a required argument')
    })

    it('fails when supplied webhook is not a valid URL', () => {
      expect(() => webhook.notify(challenge, 'localhorst')).to.throw('Invalid URI "localhorst"')
    })

    it('submits POST with payload to existing URL', () => {
      expect(() => webhook.notify(challenge, 'https://webhook.site/#!/e3b07c99-fd53-4799-aa18-984f71009f8c')).to.not.throw()
    })
  })
})

Update to new (unburned) webhook.site URL


/*
    Copyright 2015 Leafbird

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

describe('configure', function() {
  it('Confugure changes on original config.', function() {
    var leafbrd = Leafbird({});
    leafbrd.configure({});
    expect(leafbrd.config).toEqual(undefined);
  });

  it('verify if a leafbird global object has defined', function(){
    expect(leafbird).toBeDefined();
  });
});

/*
    Copyright 2015 Leafbird

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

describe('configure', function() {
  it('Confugure changes on original config.', function() {
    var leafbrd = Leafbird({});
    leafbrd.configure({});
    expect(leafbrd.config).toEqual(undefined);
  });

  it('verify if a leafbird global object has defined', function() {
    expect(leafbird).toBeDefined();
  });

  it('verify if leafbird global variable has a Leafbird object instance',
    function() {
      if(!(leafbird instanceof Leafbird)) {
        fail('leafbird global variable is not a Leafbird instance.');
      }
    });
});

Verify if leafbird global variable has a Leafbird object instance.


import * as effects from 'src/effects'
/**
 * @jest-environment jsdom
 */
jest.useFakeTimers()

describe('Effects', () => {
  let element
  beforeEach(() => {
    element = document.createElement('div')
    document.body.appendChild(element)
  })
  afterEach(() => {
    document.body.innerHTML = ''
  })
  test('Fade in', () => {
    element.style.opacity = 1
    effects.fadeIn(element, 100)
    expect(Number(element.style.opacity)).toBeGreaterThanOrEqual(0)
    jest.runAllTimers()
    expect(Number(element.style.opacity)).toBeGreaterThanOrEqual(1)
  })
  test('RAF fade in', () => {
    window.requestAnimationFrame = jest.fn(fn => setTimeout(fn, 1))
    effects.fadeIn(element, 1)
    jest.runAllTimers()
    expect(window.requestAnimationFrame).toBeCalled()
    effects.fadeIn(element)
    jest.runAllTimers()
    expect(window.requestAnimationFrame).toBeCalled()
    delete window.requestAnimationFrame
  })
  test('Fade out', () => {
    element.style.opacity = 0
    effects.fadeOut(element, 100)
    expect(Number(element.style.opacity)).toBeLessThanOrEqual(1)
    jest.runAllTimers()
    expect(Number(element.style.opacity)).toBeLessThanOrEqual(0)
  })
  test('Hide', () => {
    effects.hide(element)
    expect(element.style.display).toBe('none')
  })
  test('Show', () => {
    effects.show(element)
    expect(element.style.display).toBe('')
  })
})

import * as effects from 'src/effects'
/**
 * @jest-environment jsdom
 */
jest.useFakeTimers()

describe('Effects', () => {
  let element
  beforeEach(() => {
    element = document.createElement('div')
    document.body.appendChild(element)
  })
  afterEach(() => {
    document.body.innerHTML = ''
  })
  test('Fade in', () => {
    element.style.opacity = 1
    effects.fadeIn(element, 100)
    expect(Number(element.style.opacity)).toBeGreaterThanOrEqual(0)
    jest.runAllTimers()
    expect(Number(element.style.opacity)).toBeGreaterThanOrEqual(1)
  })
  test('RAF fade in', () => {
    global.requestAnimationFrame = jest.fn()
    effects.fadeIn(element, 1)
    jest.runAllTimers()
    expect(global.requestAnimationFrame).toBeCalled()
    effects.fadeIn(element)
    jest.runAllTimers()
    expect(global.requestAnimationFrame).toBeCalled()
    delete global.requestAnimationFrame
  })
  test('Fade out', () => {
    element.style.opacity = 0
    effects.fadeOut(element, 100)
    expect(Number(element.style.opacity)).toBeLessThanOrEqual(1)
    jest.runAllTimers()
    expect(Number(element.style.opacity)).toBeLessThanOrEqual(0)
  })
  test('Hide', () => {
    effects.hide(element)
    expect(element.style.display).toBe('none')
  })
  test('Show', () => {
    effects.show(element)
    expect(element.style.display).toBe('')
  })
})

Fix fade test with RAF


/*!
 * parse-comments <https://github.com/jonschlinkert/parse-comments>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var utils = module.exports = {};

utils.trimRight = function(str) {
  return str.replace(/\s+$/, '');
};

utils.stripStars = function (line) {
  var re = /^(?:\s*[\*]{1,2}\s)/;
  return utils.trimRight(line.replace(re, ''));
};

let utils = module.exports = {};

utils.trimRight = function(str) {
  return str.replace(/\s+$/, '');
};

utils.stripStars = function (line) {
  let re = /^(?:\s*[\*]{1,2}\s)/;
  return utils.trimRight(line.replace(re, ''));
};

Clean up parse-comments utilis file


var questions = [
  Q1 = {
    question: "What do HTML means?",
    answer: "HyperText Markup Language"
  },
  Q2 = {
    question: "What do CSS means?",
    answer: "Cascading Style Sheet"
  }
];

var question = document.getElementById('question');

var questionNum = 0;

function createNum() {
  questionNum = Math.floor(Math.random() * 2);
}

createNum();
question.innerHTML = questions[questionNum].question;

var questions = [
  Q1 = {
    question: "What does HTML means?",
    answer: "HyperText Markup Language"
  },
  Q2 = {
    question: "What does CSS means?",
    answer: "Cascading Style Sheet"
  },
  Q3 = {
    question: "Why the \"C\" in CSS, is called Cascading?",
    answer: "When CSS rules are duplicated, the rule to be use is chosen by cascading down from more general rules to the specific rule required"
  }
];

var question = document.getElementById('question');

var questionNum = 0;

function createNum() {
  questionNum = Math.floor(Math.random() * 3);
}

createNum();
question.innerHTML = questions[questionNum].question;

Modify and add another question


var i = (function() {
  'use strict';
  return {
    c: function(obj, args) {
      if (arguments.length > 0) {
        var newObj = Object.create(arguments[0]);
        if ('init' in newObj) {
          if (arguments.length > 1) {
            var args = [];
            for (var i = 1; i < arguments.length; i++) {
              args.push(arguments[i]);
            }
            newObj.init.apply(newObj, args);
          }
        }
        return newObj;
      }
    }
  };
})();

var i = (function() {
  'use strict';
  return {
    c: function(obj, args) {
      if (arguments.length > 0) {
        var newObj = Object.create(arguments[0]);
        if ('init' in newObj && typeof newObj.init === 'function') {
          if (arguments.length > 1) {
            var args = [];
            for (var i = 1; i < arguments.length; i++) {
              args.push(arguments[i]);
            }
            newObj.init.apply(newObj, args);
          }
        }
        return newObj;
      }
    }
  };
})();

Check that init is a function


module.exports = function(sequelize, DataTypes) {

	var UserDevice = sequelize.define('UserDevice', {
			type: {
				type: DataTypes.ENUM('IOS', 'ANDROID'),
				defaultValue: 'IOS'
			},
			token: {
				type: DataTypes.STRING,
				allowNull: false
			}
		},
		{
			classMethods: {
				addDevice: function(deviceInfo) {
					UserDevice.find({where: deviceInfo})
						.success(function(device) {
							if(device) {

							}
							else {
								UserDevice.create(deviceInfo);
							}
						});
				}
			},
			associate: function(models){
				UserDevice.belongsTo(models.User);
			}
		}
	);

	return UserDevice;
};

module.exports = function(sequelize, DataTypes) {

	var UserDevice = sequelize.define('UserDevice', {
			type: {
				type: DataTypes.ENUM('IOS', 'ANDROID'),
				defaultValue: 'IOS'
			},
			token: {
				type: DataTypes.STRING,
				allowNull: false
			}
		},
		{
			classMethods: {
				addDevice: function(deviceInfo) {
					var search = {
						type: deviceInfo.type,
          				token: deviceInfo.token,
					};
					UserDevice.find({where: search})
						.success(function(device) {
							if(device) {
								device.destroy();
							}
							UserDevice.create(deviceInfo);
						});
				}
			},
			associate: function(models){
				UserDevice.belongsTo(models.User);
			}
		}
	);

	return UserDevice;
};

Remove duplicated device token for multiple users


var ArgumentError = require('./ArgumentError');
var topiarist = require('topiarist');

function verifierMethod(verifier, methodName) {
  return function() {
    if(!this.skipVerification) {
      if(this.argValue === undefined) throw new ArgumentError(this.argName + ' argument must be provided.');

      verifier[methodName].apply(this, arguments);
    }

    if(this.argsVerifier.argIndex < this.argsVerifier.arguments.length) {
      this.argsVerifier.constructor.pendingVerifier = this.argsVerifier;
    }

    return this.argsVerifier;
  };
}

function ArgVerifier(argsVerifier, argName, argValue) {
  this.argsVerifier = argsVerifier;
  this.argName = argName;
  this.argValue = argValue;
}

ArgVerifier.addVerifier = function(verifier) {
  for(var methodName in verifier) {
    ArgVerifier.prototype[methodName] = verifierMethod(verifier, methodName);
  }
};

Object.defineProperty(ArgVerifier.prototype, 'optionally', {
  get: function optionally() {
    if((this.argValue === undefined) || (this.argValue === null)) {
      this.skipVerification = true;
    }

    return this;
  }
});

module.exports = ArgVerifier;

var ArgumentError = require('./ArgumentError');
var topiarist = require('topiarist');

function verifierMethod(verifierMethod) {
  return function(arg) {
    if(!this.skipVerification) {
      if(this.argValue === undefined) throw new ArgumentError(this.argName + ' argument must be provided.');

      verifierMethod.call(this, arg);
    }

    if(this.argsVerifier.argIndex < this.argsVerifier.arguments.length) {
      this.argsVerifier.constructor.pendingVerifier = this.argsVerifier;
    }

    return this.argsVerifier;
  };
}

function ArgVerifier(argsVerifier, argName, argValue) {
  this.argsVerifier = argsVerifier;
  this.argName = argName;
  this.argValue = argValue;
}

ArgVerifier.addVerifier = function(verifier) {
  for(var methodName in verifier) {
    ArgVerifier.prototype[methodName] = verifierMethod(verifier[methodName]);
  }
};

Object.defineProperty(ArgVerifier.prototype, 'optionally', {
  get: function optionally() {
    if((this.argValue === undefined) || (this.argValue === null)) {
      this.skipVerification = true;
    }

    return this;
  }
});

module.exports = ArgVerifier;

Use call() rather than apply() to improve performance.


/* global describe, beforeEach, afterEach, it */
const knex_config = require('../../knexfile');
const knex = require('knex')(knex_config['test']);

const chai = require('chai');
const should = chai.should();

describe('Handle ads', function() {

  beforeEach(function(done) {
    knex.migrate.rollback()
      .then(function() {
        knex.migrate.latest()
          .then(function() {
            return knex.seed.run()
              .then(function() {
                done();
              });
          });
      });
  });

  afterEach(function(done) {
    knex.migrate.rollback()
      .then(function() {
        done();
      });
  });

  it('should list ads in order', (done) => {
    done();
  })
});

/* global describe, beforeEach, afterEach, it */

const chai = require('chai');
const should = chai.should();

const knex_config = require('../../knexfile');
const knex = require('knex')(knex_config['test']);

const util = require('../util')({ knex });
const service = require('./ads')({ knex, util });

describe('Handle ads', function() {

  beforeEach(function(done) {
    knex.migrate.rollback()
      .then(function() {
        knex.migrate.latest()
          .then(function() {
            return knex.seed.run()
              .then(function() {
                done();
              });
          });
      });
  });

  afterEach(function(done) {
    knex.migrate.rollback()
      .then(function() {
        done();
      });
  });

  it('should list ads in order', (done) => {
    service.listAds(false).then((ads) => {
      ads.map(ad => ad.id).should.eql([2, 3, 1]);
      done();
    })
  })
});

Test that ads appear in date order latest first


import queryString from 'query-string';

function transitionToParams(params) {
  const location = this.props.location;
  let query = location.query;
  if (query === undefined)
    query = queryString.parse(location.search);

  const allParams = Object.assign({}, query, params);
  const keys = Object.keys(allParams);

  let url = location.pathname;
  if (keys.length) {
    url += `?${keys.map(key => `${key}=${encodeURIComponent(allParams[key])}`).join('&')}`;
  }

  this.props.history.push(url);
}

export default transitionToParams;

import queryString from 'query-string';

function transitionToParams(params) {
  const location = this.props.location;
  let query = location.query;
  if (query === undefined)
    query = queryString.parse(location.search);

  const allParams = Object.assign({}, query, params);
  const keys = Object.keys(allParams);

  let url = location.pathname;
  if (keys.length) {
    url += `?${queryString.stringify(allParams)}`;
  }

  this.props.history.push(url);
}

export default transitionToParams;

Use queryString.stringify instead of by-hand gluing


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

Remove superfluous and redundant code


import { h, Component } from 'preact'
import { bind } from './util'

export default class extends Component {
  constructor() {
    super()
    this.state.show = false
  }
  linkState(key) {
    return e => this.setState({
      [key]: e.target.value
    })
  }
  @bind
  toggleShow() {
    this.setState({
      show: !this.state.show
    })
  }
  clearState() {
    this.setState({
      appName: '',
      username: '',
      password: '',
      show: false
    })
  }
  @bind
  handleSubmit(e) {
    e.preventDefault()

    this.props.add(this.state.appName, this.state.username, this.state.password)
    this.clearState()
  }
  render(_, { show, appName, username, password }) {
    return (

          <form onSubmit={this.handleSubmit}>
            <input name='appName' placeholder='Enter app name' value={appName} onInput={this.linkState('appName')} />
            <input name='username' placeholder='Enter app username' value={username} onInput={this.linkState('username')} />
            <input name='password' placeholder='Enter app password' value={password} onInput={this.linkState('password')} />
            <button type='submit'>Save</button>
          </form>

        <button onClick={this.toggleShow}>Add new app</button>

    )
  }
}

import { h, Component } from 'preact'
import { bind } from './util'

export default class extends Component {
  constructor() {
    super()
    this.state.show = false
  }
  linkState(key) {
    return e => this.setState({
      [key]: e.target.value
    })
  }
  @bind
  toggleShow() {
    this.setState({
      show: !this.state.show
    })
  }
  clearState() {
    this.setState({
      appName: '',
      username: '',
      password: '',
      show: false
    })
  }
  @bind
  handleSubmit(e) {
    const { appName, username, password } = this.state

    e.preventDefault()
    this.props.add(appName, username, password)
    this.clearState()
  }
  render(_, { show, appName, username, password }) {
    return (

          <form onSubmit={this.handleSubmit}>
            <input name='appName' placeholder='Enter app name' value={appName} onInput={this.linkState('appName')} />
            <input name='username' placeholder='Enter app username' value={username} onInput={this.linkState('username')} />
            <input name='password' placeholder='Enter app password' value={password} onInput={this.linkState('password')} />
            <button type='submit'>Save</button>
          </form>

        <button onClick={this.toggleShow}>Add new app</button>

    )
  }
}

Use destructuring to remove noise


import React, { Component } from 'react';
import './Loading.css';

class Loading extends Component {
	render() {
		return
Loading timetable data.
;
	}
}

export default Loading;

import React, { Component } from 'react';
import './Loading.css';

class Loading extends Component {
	render() {
		return (

Loading

{this.props.name}

{this.props.message}

		);
	}
}

Loading.defaultProps = {
	name: 'Loading name',
	message: 'Loading something. This is the default message. Blame the lazy developer for not giving you any more info and copy-pasting this text from Error screen.'
};

Loading.propTypes = {
	name: React.PropTypes.string,
	message: React.PropTypes.string
};

export default Loading;

Add error style message and name.


import React from 'react';

import Temperature from './Temperature.js';

class Weather extends React.Component {
    render = () => {
        // FIXME: After rendering, send stats to Google Analytics

        // FIXME: Add the actual temperatures
        return (
            <Temperature degreesCelsius={25} hour={12}></Temperature>
        );
    }
}

export default Weather;

import React from 'react';

import Temperature from './Temperature.js';

class Weather extends React.Component {
    renderTemperatures = (renderUs) => {
        // FIXME: Add the actual temperatures

        console.log(renderUs);

        return (
            <Temperature degreesCelsius={25} hour={1} />
        );
    }

    getForecastsToRender = () => {
        const renderUs = [];

        const now_ms = (new Date()).getTime();
        const start = new Date(now_ms + 0.75 * 3600 * 1000);
        const end = new Date(now_ms + 11.75 * 3600 * 1000);

        // eslint-disable-next-line
        for (const [timestamp_ms, forecast] of Object.entries(this.props.forecast)) {
            const timestamp_date = new Date(timestamp_ms);

            if (timestamp_date < start) {
                continue;
            }

            if (timestamp_date > end) {
                continue;
            }

            renderUs.push(forecast);
        }

        console.log(renderUs);
        return renderUs;
    }

    render = () => {
        // FIXME: After rendering, send stats to Google Analytics

        const renderUs = this.getForecastsToRender()
        return (
            <React.Fragment>
                {this.renderTemperatures(renderUs)}
            </React.Fragment>
        );
    }
}

export default Weather;

Add logic for choosing which forecasts to show


/**
 * Find indices of all occurance of elem in arr. Uses 'indexOf'.
 * @param {array} arr - Array-like element (works with strings too!).
 * @param {array_element} elem - Element to search for in arr.
 * @return {array} indices - Array of indices where elem occurs in arr.
 */
var findAllIndices = function(arr, elem) {
  var indices = [];
  var i = arr.indexOf(elem);
  while (i != -1) {
    indices.push(i);
    i = arr.indexOf(elem, i + 1);
  }
  return indices;
};

/**
 * Find indices of all matches of Regex pattern in str.
 * @param {string} str - string to find Regex patterns in.
 * @param {RegExp} re - Regex patterns
 * @return {array} Array of indices where Regex pattern occurs in str.
 */
var findAllIndicesRegex = function(str, re) {
  var indices = [];
  var m = re.exec(str);
  while (m) {
    indices.push(m.index);
    m = re.exec(str);
  }
  return indices;
};

module.exports.findAllIndices = findAllIndices;
module.exports.findAllIndicesRegex = findAllIndicesRegex;

/**
 * Find indices of all occurance of elem in arr. Uses 'indexOf'.
 * @param {array} arr - Array-like element (works with strings too!).
 * @param {array_element} elem - Element to search for in arr.
 * @return {array} indices - Array of indices where elem occurs in arr.
 */
var findAllIndices = function(arr, elem) {
  var indices = [];
  var i = arr.indexOf(elem);
  while (i != -1) {
    indices.push(i);
    i = arr.indexOf(elem, i + 1);
  }
  return indices;
};

/**
 * Find indices of all matches of Regex pattern in str.
 * @param {string} str - string to find Regex patterns in.
 * @param {RegExp} re - Regex patterns
 * @return {array} Array of indices where Regex pattern occurs in str.
 */
var findAllIndicesRegex = function(str, re) {
  var indices = [];
  var m = re.exec(str);
  while (m) {
    indices.push(m.index);
    m = re.exec(str);
  }
  return indices;
};

var nullOutChars = function(str, start, end, nullChar) {
  return str.slice(0, start) + nullChar.repeat(end - start) + str.slice(end);
}

module.exports.findAllIndices = findAllIndices;
module.exports.findAllIndicesRegex = findAllIndicesRegex;
module.exports.nullOutChars = nullOutChars;

Add new fxn to null out chars in str range


'use strict';

var extendPrototypeWithThese = function (prototype, extendThese) {
    /*
        Helper method to implement a simple inheritance model for object prototypes.
    */

    var outp = prototype;

    if (extendThese) {

        for (var i = extendThese.length - 1; i >= 0; i--) {
            // I need to create the object in order to copy the prototype functions
            var tmpObj = new extendThese[i]();
            for (var key in tmpObj) {
                if (key == '_implements') {
                    // Implements should be extended with later coming before earlier
                    // TODO: Filer so we remove duplicates from existing list (order makes difference)
                    outp.prototype._implements = tmpObj._implements.concat(outp.prototype._implements);
                } else {
                    // All others added and lower indexes override higher
                   outp.prototype[key] = tmpObj[key];
                }
            }
        }

    }

    return outp;
}
module.exports.extendPrototypeWithThese = extendPrototypeWithThese;

var addMembers = function (outp, params) {
    /*
        Helper method to add each item in params dictionary to the prototype of outp.
    */

    for (var key in params) {
        if (params.hasOwnProperty(key)) {
            outp.prototype[key] = params[key];
        }
    }

    return outp;
}
module.exports.addMembers = addMembers;

'use strict';

var extendPrototypeWithThese = function (prototype, extendThese) {
    /*
        Helper method to implement a simple inheritance model for object prototypes.
    */

    var outp = prototype;

    if (extendThese) {

        for (var i = extendThese.length - 1; i >= 0; i--) {
            // I need to create the object in order to copy the prototype functions
            var tmpObj = extendThese[i].prototype;
            for (var key in tmpObj) {
                if (key == '_implements') {
                    // Implements should be extended with later coming before earlier
                    // TODO: Filer so we remove duplicates from existing list (order makes difference)
                    outp.prototype._implements = tmpObj._implements.concat(outp.prototype._implements);
                } else {
                    // All others added and lower indexes override higher
                   outp.prototype[key] = tmpObj[key];
                }
            }
        }

    }

    return outp;
}
module.exports.extendPrototypeWithThese = extendPrototypeWithThese;

var addMembers = function (outp, params) {
    /*
        Helper method to add each item in params dictionary to the prototype of outp.
    */

    for (var key in params) {
        if (params.hasOwnProperty(key)) {
            outp.prototype[key] = params[key];
        }
    }

    return outp;
}
module.exports.addMembers = addMembers;

Copy prototype memebers on extend


/* eslint-env mocha */
const InsertionSort = require('../../../src').Algorithms.Sorting.InsertionSort;
const assert = require('assert');

describe('Insertion Sort', () => {
  it('should have no data when empty initialization', () => {
    const inst = new InsertionSort();
    assert.equal(inst.size, 0);
    assert.deepEqual(inst.unsortedList, []);
    assert.deepEqual(inst.sortedList, []);
  });
});

/* eslint-env mocha */
const InsertionSort = require('../../../src').Algorithms.Sorting.InsertionSort;
const assert = require('assert');

describe('Insertion Sort', () => {
  it('should have no data when empty initialization', () => {
    const inst = new InsertionSort();
    assert.equal(inst.size, 0);
    assert.deepEqual(inst.unsortedList, []);
    assert.deepEqual(inst.sortedList, []);
  });

  it('should sort the array', () => {
    const inst = new InsertionSort([2, 1, 3, 4]);
    assert.equal(inst.size, 4);

    assert.deepEqual(inst.unsortedList, [2, 1, 3, 4]);
    assert.deepEqual(inst.sortedList, [1, 2, 3, 4]);
    assert.equal(inst.toString(), '1, 2, 3, 4');
  });

});

Test Insertion Sort: Test for sorting the array


/**
 * ES6 not supported here
 */
import Ember from "ember";
import config from 'ember-get-config';

export default Ember.Mixin.create({

    bundleLoader: Ember.inject.service("bundle-loader"),

    findBundleNameByRoute: function(routeName){
        //Find bundle for route
        var foundBundleName  = Object.keys(config.bundles)
            .find((name)=> {
                let bundle = config.bundles[name];
                return bundle.routes.indexOf(routeName)>-1;
            });
        return foundBundleName;

    },
    beforeModel: function(transition, queryParams){
        this._super(transition,queryParams);
        let service = this.get("bundleLoader");
        let bundleName = this.findBundleNameByRoute(transition.targetName);

        return service.loadBundle(bundleName);
    }

});

/**
 * ES6 not supported here
 */
import Ember from "ember";
import config from 'ember-get-config';

export default Ember.Mixin.create({
    bundleLoader: Ember.inject.service("bundle-loader"),

    findBundleNameByRoute: function(routeName){
        //Find bundle for route
        var bundleName = null;
        var bundleNames = Object.keys(config.bundles);
        bundleNames.forEach(function(name) {
          var bundle = config.bundles[name];
          if(bundle.routes.indexOf(routeName) >= 0) {
            bundleName = name;
          }
        });

        return bundleName;

    },
    beforeModel: function(transition, queryParams){
        this._super(transition,queryParams);
        let service = this.get("bundleLoader");
        let bundleName = this.findBundleNameByRoute(transition.targetName);

        return service.loadBundle(bundleName);
    }

});

Fix tests by switching to es5 syntax in finding bundles


/*! Animate.js | The MIT License (MIT) | Copyright (c) 2017 GibboK */
; (function (animate) {
    'use strict';
    animate.zoomOutUp = function (selector, options) {
        var keyframeset = [
            {
                opacity: 1,
                transform: 'none',
                transformOrigin: 'left center',
                offset: 0
            },
            {
                opacity: 1,
                transform: 'scale3d(.475, .475, .475) translate3d(0, 60px, 0)',
                animationTimingFunction: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)',
                offset: 0.4
            },
            {
                opacity: 0,
                transform: 'scale3d(.1, .1, .1) translate3d(0, -2000px, 0)',
                transformOrigin: 'center bottom',
                animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.320, 1)',
                offset: 1
            }
        ];
        return animate._animate(selector, keyframeset, options);
    }
})(window.animate = window.animate || {});

/*! Animate.js | The MIT License (MIT) | Copyright (c) 2017 GibboK */
; (function (animate) {
    'use strict';
    animate.zoomOutUp = function (selector, options) {
        var keyframeset = [
            {
                opacity: 1,
                transform: 'none',
                transformOrigin: 'center bottom',
                offset: 0
            },
            {
                opacity: 1,
                transform: 'scale3d(.475, .475, .475) translate3d(0, 60px, 0)',
                animationTimingFunction: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)',
                offset: 0.4
            },
            {
                opacity: 0,
                transform: 'scale3d(.1, .1, .1) translate3d(0, -2000px, 0)',
                transformOrigin: 'center bottom',
                animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.320, 1)',
                offset: 1
            }
        ];
        return animate._animate(selector, keyframeset, options);
    }
})(window.animate = window.animate || {});

Add fix bug in animation


// extend the bibliographic entries
var localBibliography = {
  "HYDRA-CORE": {
    authors: [ "Markus Lanthaler" ],
    href: "http://www.hydra-cg.com/spec/latest/core/",
    title: "Hydra Core Vocabulary",
    status: "unofficial",
    publisher: "W3C"
  },
    "PAV": "Paolo Ciccarese, Stian Soiland-Reyes, Khalid Belhajjame, Alasdair JG Gray, Carole Goble, Tim Clark (2013): PAV ontology: provenance, authoring and versioning. Journal of biomedical semantics 4:37. doi:10.1186/2041-1480-4-37"
};

// extend the bibliographic entries
var localBibliography = {
  "HYDRA-CORE": {
    authors: [ "Markus Lanthaler" ],
    href: "http://www.hydra-cg.com/spec/latest/core/",
    title: "Hydra Core Vocabulary",
    status: "Unofficial Draft",
    publisher: "W3C"
  },
  "PAV": {
    authors: [
      "Paolo Ciccarese",
      "Stian Soiland-Reyes",
      "Khalid Belhajjame",
      "Alasdair JG Gray",
      "Carole Goble",
      "Tim Clark"
    ],
    href: "http://purl.org/pav/",
    title: "PAV ontology: provenance, authoring and versioning",
    publisher: "Journal of biomedical semantics",
    status: "Published"
  }
};

Set up localBiblio according to ReSpec's documentation:


import React, {Component} from 'react';
import {Button, Card, CardSection, Input} from './common';

class LoginForm extends Component {
  constructor(props) {
    super(props);
    this.state = {email: "", password: ''};
  }

  render() {
    return <Card>
      <CardSection>
        <Input label="Email"
               placeholder="user@gmail.com"
               onChangeText={email => this.setState({email})}
               value={this.state.email}/>
      </CardSection>

      <CardSection>
        <Input secureTextEntry
               label="Password"
               placeholder = "password"
               onChangeText={password => this.setState({password})}
               value = {this.state.password}
        />
      </CardSection>

      <CardSection>
        <Button>
          Log in
        </Button>
      </CardSection>
    </Card>
  }
}

export default LoginForm;

import React, {Component} from 'react';
import {Button, Card, CardSection, Input} from './common';
import firebase from 'firebase';
import {Text} from 'react-native';

class LoginForm extends Component {
  constructor(props) {
    super(props);
    this.state = {email: '', password: '', error: ''};
  }

  async onButtonPress() {
    const {email, password} = this.state;
    this.setState({error: ''});
    try {
      await firebase.auth().signInWithEmailAndPassword(email, password);
    }
    catch (err) {
      try {
        await firebase.auth().createUserWithEmailAndPassword(email, password);
      }
      catch (err) {
        console.log("error", err);
        this.setState({error: "Login Failed"});
      }
    }
  }

  render() {
    return <Card>
      <CardSection>
        <Input label="Email"
               placeholder="user@gmail.com"
               onChangeText={email => this.setState({email})}
               value={this.state.email}/>
      </CardSection>

      <CardSection>
        <Input secureTextEntry
               label="Password"
               placeholder="password"
               onChangeText={password => this.setState({password})}
               value={this.state.password}
        />
      </CardSection>

      <Text style={styles.errorTextStyle}>
        {this.state.error}
      </Text>

      <CardSection>
        <Button onPress={()=>this.onButtonPress()}>
          Log in
        </Button>
      </CardSection>
    </Card>
  }
}

const styles = {
  errorTextStyle: {
    fontSize: 20,
    alignSelf: 'center',
    color: 'red'
  }
};

export default LoginForm;

Use firebase to authenticate users


/**
 * Author: Josh Adam <josh.adam@phac-aspc.gc.ca>
 * Date:   2013-04-17
 * Time:   9:41 AM
 */

var username = $('#username').text();

function Project (data) {
  "use strict";
   this.name = data.name;
}

function UserViewModel () {
  "use strict";
  self.projects = ko.observableArray([]);

  function getUserProjects () {
    "use strict";

    $.getJSON('/users/' + username + '/projects', function (allData) {
      var mappedProjects = $.map(allData.projectList, function (item) {
        return new Project(item)
      });
      self.projects(mappedProjects);
    });
  }

  getUserProjects();
}

$.ajaxSetup({ cache: false });
ko.applyBindings(new UserViewModel());

/**
 * Author: Josh Adam <josh.adam@phac-aspc.gc.ca>
 * Date:   2013-04-17
 * Time:   9:41 AM
 */

var username = $('#username').text();

function Project (data) {
  "use strict";
   this.name = data.name;
}

function UserViewModel () {
  "use strict";
  self.projects = ko.observableArray([]);

  function getUserProjects () {
    "use strict";

    $.getJSON('/users/' + username + '/projects', function (allData) {
      var mappedProjects = $.map(allData.projectResources.projects, function (item) {
        return new Project(item)
      });
      self.projects(mappedProjects);
    });
  }

  getUserProjects();
}

$.ajaxSetup({ cache: false });
ko.applyBindings(new UserViewModel());

Change the expected JSON format for user projects.


var ContactView = require('../view/Contact');

/**
 * Creates a new Contact
 * @constructor
 * @arg {Object} options - Object hash used to populate instance
 * @arg {string} options.firstName - First name of the contact
 * @arg {string} options.firstName - Last name of the contact
 * @arg {string} options.tel -  name of the contact
 */
var Contact = function(options) {
  if (typeof options !== 'object') {
    throw console.error('`options` is not properly defined');
  }
  this.init(options);
};

Contact.prototype = {
  firstName: '',
  lastName: '',
  tel: '',

  /**
   * @description Creates a new instance of Contact
   */
  init: function(options) {
    var opts = Object.keys(options);
    opts.forEach(function(currentValue){
      this[currentValue] = options[currentValue];
    }, this);

    console.log(this);
    this.save();
  },

  save: function() {
    var key = localStorage.length;
    var contact = {
      firstName: this.firstName,
      lastName: this.lastName,
      tel: this.tel
    };

    localStorage.setItem(key, JSON.stringify(contact));
    var contactView = new ContactView(key, contact);
  }
};

Contact.remove = function(id) {
  localStorage.removeItem(id);
};

module.exports = Contact;

var ContactView = require('../view/Contact');

/**
 * Creates a new Contact.
 * @constructor
 * @arg {Object} options - Object hash used to populate instance.
 * @arg {string} options.firstName - First name of the contact.
 * @arg {string} options.firstName - Last name of the contact.
 * @arg {string} options.tel - Telephone number of the contact.
 */
var Contact = function(options) {
  if (typeof options !== 'object') {
    throw console.error('`options` is not properly defined');
  }
  this.init(options);
};

Contact.prototype = {
  firstName: '',
  lastName: '',
  tel: '',

  /**
   * @description Creates a new instance of Contact.
   */
  init: function(options) {
    var opts = Object.keys(options);
    opts.forEach(function(currentValue){
      this[currentValue] = options[currentValue];
    }, this);

    console.log(this);
    this.save();
  },

  save: function() {
    var key = localStorage.length;
    var contact = {
      firstName: this.firstName,
      lastName: this.lastName,
      tel: this.tel
    };

    localStorage.setItem(key, JSON.stringify(contact));
    var contactView = new ContactView(key, contact);
  }
};

Contact.remove = function(id) {
  localStorage.removeItem(id);
};

module.exports = Contact;

Use periods on senteces in docs