/*! resol-vbus | Copyright (c) 2013-2019, Daniel Wippermann | MIT license */
'use strict';

const fs = require('fs');

let useDevelopmentSource;
try {
    fs.accessSync('src/index.js');
    useDevelopmentSource = true;
} catch (ex) {
    useDevelopmentSource = false;
}

let vbus;
if (useDevelopmentSource) {
    vbus = require('./src/index.js');
} else {
    vbus = require('./dist/index.js');
}

module.exports = vbus;

/*! resol-vbus | Copyright (c) 2013-2019, Daniel Wippermann | MIT license */
'use strict';

const fs = require('fs');
const path = require('path');

let useDevelopmentSource;
try {
    fs.accessSync(path.join(__dirname, 'src/index.js'));
    useDevelopmentSource = true;
} catch (ex) {
    useDevelopmentSource = false;
}

let vbus;
if (useDevelopmentSource) {
    vbus = require('./src/index.js');
} else {
    vbus = require('./dist/index.js');
}

module.exports = vbus;

Fix development / production loader script.


/*
 * index.js: Top-level include for the pkgcloud common module.
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

exports.auth = require('./auth');

Add top-level include for `pkgcloud.common`


"use babel";

import async from "async";
import GitHubClient from "node-github";
import package from "../../../package.json";

import Fork from "../../models/fork";

var github = new GitHubClient({
  version: "3.0.0",
  debug: true,
  headers: {
    "user-agent": `atom-pull-request/${package.version}` // GitHub is happy with a unique user agent
  }
});)

module.exports = {
  getImportantForks: function (repository, callback) {
    let makeFork = function (repo) {
      return new Fork(repository, repo.full_name, repo.default_branch);
    };

    async.waterfall([
      (cb) => repository.originID(cb),
      (repoID, cb) => github.repos.get(repoID, cb)
    ], (err, repo) => {
      if (err) return callback(err);

      callback(null, {
        current: makeFork(repo),
        source: makeFork(repo.source)
      });
    });
  },

  getAvailableForks: function (repository, callback) {
  },

  getAvailableBranches: function (fork, callback) {
  }
};

"use babel";

import async from "async";
import GitHubClient from "node-github";
import package from "../../../package.json";

import Fork from "../../models/fork";

var github = new GitHubClient({
  version: "3.0.0",
  debug: true,
  headers: {
    "user-agent": `atom-pull-request/${package.version}` // GitHub is happy with a unique user agent
  }
});

module.exports = {
  getImportantForks: function (repository, callback) {
    let makeFork = function (repo) {
      return new Fork(repository, repo.full_name, repo.default_branch);
    };

    async.waterfall([
      (cb) => repository.originID(cb),
      (repoID, cb) => github.repos.get(repoID, cb)
    ], (err, repo) => {
      if (err) return callback(err);

      callback(null, {
        current: makeFork(repo),
        source: makeFork(repo.source || repo)
      });
    });
  },

  getAvailableForks: function (repository, callback) {
  },

  getAvailableBranches: function (fork, callback) {
  }
};

Test out the live transport.


$(function(){
	$("#slideshow").slidesjs({
		width: 960,
		height: 312,
		navigation: {
			active: true,
			effect: 'slide'
		},
		pagination: {
			active: true,
			effect: 'slide'
		}
	});
});

$(function(){
	$("#slideshow").slidesjs({
		width: 960,
		height: 312,
		navigation: {
			active: true,
			effect: 'slide'
		},
		pagination: {
			active: true,
			effect: 'slide'
		}
	});
  $(".top").on("click", "a", function(e){
    window.scrollTo(0, 0);
    return false;
  });
});

Update burnstudio: add go-to-top feature


'use strict'

const Router = require('express').Router
const passport = require('passport')
var GoogleStrategy = require('passport-google-oauth20').Strategy
const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')

let googleAuth = module.exports = Router()

passport.use(new GoogleStrategy({
  clientID: config.google.clientID,
  clientSecret: config.google.clientSecret,
  callbackURL: config.serverURL + '/auth/google/callback'
}, passportGeneralCallback))

googleAuth.get('/auth/google', function (req, res, next) {
  setReturnToFromReferer(req)
  passport.authenticate('google', { scope: ['profile'] })(req, res, next)
})
  // google auth callback
googleAuth.get('/auth/google/callback',
  passport.authenticate('google', {
    successReturnToOrRedirect: config.serverURL + '/',
    failureRedirect: config.serverURL + '/'
  })
)

'use strict'

const Router = require('express').Router
const passport = require('passport')
var GoogleStrategy = require('passport-google-oauth20').Strategy
const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')

let googleAuth = module.exports = Router()

passport.use(new GoogleStrategy({
  clientID: config.google.clientID,
  clientSecret: config.google.clientSecret,
  callbackURL: config.serverURL + '/auth/google/callback',
  userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
}, passportGeneralCallback))

googleAuth.get('/auth/google', function (req, res, next) {
  setReturnToFromReferer(req)
  passport.authenticate('google', { scope: ['profile'] })(req, res, next)
})
  // google auth callback
googleAuth.get('/auth/google/callback',
  passport.authenticate('google', {
    successReturnToOrRedirect: config.serverURL + '/',
    failureRedirect: config.serverURL + '/'
  })
)

Add required change for Google+ API deprecation


import { resolve } from 'path';
import { removeStartSlash } from './common';

export const rootDirectory = resolve(__dirname, '../../..');

/**
 * Resolves a file in the root directory of the project using the framework.
 *
 * @param fileName - The name of the file to resolve.
 * @returns The path of the file.
 */
export function resolveProject(fileName: string): string {
  return resolve(process.cwd(), removeStartSlash(fileName));
}

/**
 * Resolves a file in the root directory of the framework.
 *
 * @param fileName - The name of the file to resolve.
 * @returns The path of the file.
 */
export function resolveRoot(fileName: string = ''): string {
  return resolve(rootDirectory, removeStartSlash(fileName));
}

/**
 * Resolves a file in the root directory of source of the framework (.build or framework).
 *
 * @param fileName - The name of the file to resolve.
 * @returns The path of the file.
 */
export function resolveFrameworkSource(fileName: string): string {
  return resolve(rootDirectory, 'src/framework', removeStartSlash(fileName));
}

import { resolve } from 'path';
import { removeStartSlash } from './common';

export const rootDirectory = resolve(__dirname, '../../..');

/**
 * Resolves a file in the root directory of the project using the framework.
 *
 * @param fileName - The name of the file to resolve.
 * @returns The path of the file.
 */
export function resolveProject(fileName: string): string {
  return resolve(process.cwd(), removeStartSlash(fileName));
}

/**
 * Resolves a file in the root directory of the framework.
 *
 * @param fileName - The name of the file to resolve.
 * @returns The path of the file.
 */
export function resolveRoot(fileName: string = ''): string {
  return resolve(rootDirectory, removeStartSlash(fileName));
}

/**
 * Resolves a file in the root directory of source of the framework (.build or framework).
 *
 * @param fileName - The name of the file to resolve.
 * @returns The path of the file.
 */
export function resolveFrameworkSource(fileName: string): string {
  return resolve(rootDirectory, 'es/framework', removeStartSlash(fileName));
}

Resolve files from the /es folder instead of /src


/**
 * @class CM_FormField_Text
 * @extends CM_FormField_Abstract
 */
var CM_FormField_Text = CM_FormField_Abstract.extend({
	_class: 'CM_FormField_Text',

	events: {
		'blur input': function() {
			this.trigger('blur');
		},
		'focus input': function() {
			this.trigger('focus');
		}
	},

	/**
	 * @param {String} value
	 */
	setValue: function(value) {
		this.$('input').val(value);
	},

	setFocus: function() {
		this.$('input').focus();
	},

	enableTriggerChange: function() {
		var self = this;
		var $input = this.$('input');
		var valueLast = $input.val();
		var callback = function() {
			var value = this.value;
			if (value != valueLast) {
				valueLast = value;
				self.trigger('change');
			}
		};
		// IE9: `propertychange` and `keyup` needed additionally
		$input.on('input propertychange keyup', callback);
	}
});

/**
 * @class CM_FormField_Text
 * @extends CM_FormField_Abstract
 */
var CM_FormField_Text = CM_FormField_Abstract.extend({
	_class: 'CM_FormField_Text',

	/** @type Boolean */
	_skipTriggerChange: false,

	events: {
		'blur input': function() {
			this.trigger('blur');
		},
		'focus input': function() {
			this.trigger('focus');
		}
	},

	/**
	 * @param {String} value
	 * @param {Boolean} [skipTriggerChange]
	 */
	setValue: function(value, skipTriggerChange) {
		this._skipTriggerChange = skipTriggerChange;
		this.$('input').val(value);
		this._skipTriggerChange = false;
	},

	setFocus: function() {
		this.$('input').focus();
	},

	enableTriggerChange: function() {
		var self = this;
		var $input = this.$('input');
		var valueLast = $input.val();
		var callback = function() {
			var value = this.value;
			if (value != valueLast) {
				valueLast = value;
				if (!self._skipTriggerChange) {
					self.trigger('change');
				}
			}
		};
		// `propertychange` and `keyup` needed for IE9
		$input.on('input propertychange keyup', callback);
	}
});

Introduce option to set text formField's value without triggering `change`


// @flow

import { connect } from 'lib/utils/redux-utils';
import * as React from 'react';
import { TouchableOpacity, StyleSheet, Platform } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';

import type { AppState } from '../redux/redux-setup';
import type { Colors } from '../themes/colors';
import { colorsSelector } from '../themes/colors';
import type { TextStyle } from '../types/styles';

type Props = {|
  onPress: () => void,
  canChangeSettings: boolean,
  style?: TextStyle,
  // Redux state
  colors: Colors,
|};
function EditSettingButton(props: Props) {
  if (!props.canChangeSettings) {
    return null;
  }
  const appliedStyles = [styles.editIcon];
  if (props.style) {
    appliedStyles.push(props.style);
  }
  const { link: linkColor } = props.colors;
  return (
    <TouchableOpacity onPress={props.onPress}>
      <Icon name="pencil" size={16} style={appliedStyles} color={linkColor} />
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  editIcon: {
    paddingLeft: 10,
    paddingTop: Platform.select({ android: 1, default: 0 }),
    textAlign: 'right',
  },
});

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

// @flow

import * as React from 'react';
import { TouchableOpacity, StyleSheet, Platform } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';

import { useColors } from '../themes/colors';
import type { TextStyle } from '../types/styles';

type Props = {|
  +onPress: () => void,
  +canChangeSettings: boolean,
  +style?: TextStyle,
|};
function EditSettingButton(props: Props) {
  const colors = useColors();
  if (!props.canChangeSettings) {
    return null;
  }
  const appliedStyles = [styles.editIcon];
  if (props.style) {
    appliedStyles.push(props.style);
  }
  const { link: linkColor } = colors;
  return (
    <TouchableOpacity onPress={props.onPress}>
      <Icon name="pencil" size={16} style={appliedStyles} color={linkColor} />
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  editIcon: {
    paddingLeft: 10,
    paddingTop: Platform.select({ android: 1, default: 0 }),
    textAlign: 'right',
  },
});

export default EditSettingButton;

Use hook instead of connect functions and HOC in EditSettingButton


  // Don't commit this file to your public repos. This config is for first-run
  //
 exports.creds = {
 	returnURL: 'https://proseware.skwantoso.com/auth/openid/return',
 	identityMetadata: 'https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration', // For using Microsoft you should never need to change this.
 	clientID: '9bdade37-a70b-4eee-ae7a-b38e2c8a1416',
 	clientSecret: '8s<Xb3</AVX)(I**',
	tenantName: 'prosewareb2c.onmicrosoft.com',
 	skipUserProfile: true, // for OpenID only flows this should be set to true
 	responseType: 'id_token', // for login only flows
 	responseMode: 'form_post', // As per the OAuth 2.0 standard.

 };

  // Don't commit this file to your public repos. This config is for first-run
  //
 exports.creds = {
 	returnURL: 'https://proseware.skwantoso.com/auth/openid/return',
 	identityMetadata: 'https://login.microsoftonline.com/prosewareb2c.onmicrosoft.com/v2.0/.well-known/openid-configuration', // For using Microsoft you should never need to change this.
 	clientID: '9bdade37-a70b-4eee-ae7a-b38e2c8a1416',
 	clientSecret: '8s<Xb3</AVX)(I**',
	tenantName: 'prosewareb2c.onmicrosoft.com',
 	skipUserProfile: true, // for OpenID only flows this should be set to true
 	responseType: 'id_token', // for login only flows
 	responseMode: 'form_post', // As per the OAuth 2.0 standard.

 };

Switch to tenant specific endpoint


var ABTestHelper = require('../ABTestHelper.js');
module.exports['Test Input'] = {
  setUp: function(callback) {
    // Put test setup here

    // Test wildly varying input on existing functions and see if
    // the expected result is obtained.

    // Get Results - no data, lots of data,

    // initialize vars and stuff

    this.abTestHelper = new ABTestHelper();
    this.abTestHelper.addVersion('A', { name: 'Original', eventCount: 1356, totalCount: 3150 });
    this.abTestHelper.addVersion('B', { name: 'Original', eventCount: 1356, totalCount: 0 });

    callback();
  },
  'Has Enough Data - Test existence of version': function(test) {
    test.ok(this.abTestHelper);
    var that = this;

    test.throws(function() {
        that.abTestHelper.hasEnoughData('F');
    }, Error, 'Version F should not have existed.');

    test.doesNotThrow(function() {
        that.abTestHelper.hasEnoughData('A');
    }, Error, 'Version A should have existed.');

    test.done();
  },
    'Get Rate - Divide by zero': function(test) {
    test.ok(this.abTestHelper);
    var that = this;

    test.throws(function() {
        that.abTestHelper.getRate('B');
    }, Error, 'Total is zero: cannot divide by zero to produce rate.');

    test.done();
  },
};

var ABTestHelper = require('../ABTestHelper.js');
module.exports['Test Input'] = {
  setUp: function(callback) {
    this.abTestHelper = new ABTestHelper();
    this.abTestHelper.addVersion('A', { name: 'Original', eventCount: 1356, totalCount: 3150 });
    this.abTestHelper.addVersion('B', { name: 'Original', eventCount: 1356, totalCount: 0 });

    callback();
  },
  'Has Enough Data - Test existence of version': function(test) {
    test.ok(this.abTestHelper);
    var that = this;

    test.throws(function() {
        that.abTestHelper.hasEnoughData('F');
    }, Error, 'Version F should not have existed.');

    test.doesNotThrow(function() {
        that.abTestHelper.hasEnoughData('A');
    }, Error, 'Version A should have existed.');

    test.done();
  },
  'Get Rate - Divide by zero': function(test) {
    test.ok(this.abTestHelper);
    var that = this;

    test.throws(function() {
        that.abTestHelper.getRate('B');
    }, Error, 'Total is zero: cannot divide by zero to produce rate.');

    test.done();
  },
};

Remove some extraneous comments and fix a spacing problem.


/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * ScaleBar
 * Creates a ScaleBar component in the framework
 * of the MapComponent
 * @author Roy Braam
 */
Ext.define ("viewer.components.ScaleBar",{
    extend: "viewer.components.Component",
    constructor: function (conf){
        viewer.components.ScaleBar.superclass.constructor.call(this, conf);
        this.initConfig(conf);

        conf.id=conf.name;
        conf.type=viewer.viewercontroller.controller.Component.SCALEBAR;

        var comp = viewerController.mapComponent.createComponent(conf);
        viewerController.mapComponent.addComponent(comp);

        return this;
    },
    getExtComponents: function() {
        return [];
    }
});

/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * ScaleBar
 * Creates a ScaleBar component in the framework
 * of the MapComponent
 * @author Roy Braam
 */
Ext.define ("viewer.components.ScaleBar",{
    extend: "viewer.components.Component",
    constructor: function (conf){
        viewer.components.ScaleBar.superclass.constructor.call(this, conf);
        this.initConfig(conf);

        conf.id=conf.name;
        conf.type=viewer.viewercontroller.controller.Component.SCALEBAR;

        var comp = this.viewerController.mapComponent.createComponent(conf);
        this.viewerController.mapComponent.addComponent(comp);

        return this;
    },
    getExtComponents: function() {
        return [];
    }
});

Make use of this.viewerController for scalebar object.


var f = function(x) { return function() {return x}; ; };
var lambdaRegex = /\((.*)\)[\s]*=>[\s]*(.+)/;
f.property = function(propertyName) {
	if(propertyName[0] === '!')
		return function(obj) { return !obj[propertyName.substring(1)]; };
	else
		return function(obj) { return obj[propertyName]; };
}
f.method = function(methodName) {
	if(methodName[0] === '!')
		return function(obj) { return !obj[methodName.substring(1)](); };
	else
		return function(obj) { return obj[methodName](); };
}
f.n = function() {
	var args = arguments;
	if(args.length) args[args.length - 1] = "return " + args[args.length - 1];
	return Function.apply({}, args);
}
f.y = function(expression){
	var match = lambdaRegex.exec(expression);
	var argsString = match[1];
	var body = match[2];
	var args = argsString.split(',').map(f.method('trim'));
	return f.n.apply(f, args.concat(body));
}

(function (root, factory) {
    if (typeof exports === 'object') {
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define(factory);
    } else {
        root.f = factory();
    }
})(this, function () {
	var lambdaRegex = /\((.*)\)[\s]*=>[\s]*(.+)/;
	function f(x) { return function() { return x; } };
	f.property = function(propertyName) {
		if(propertyName[0] === '!')
			return function(obj) { return !obj[propertyName.substring(1)]; };
		else
			return function(obj) { return obj[propertyName]; };
	}
	f.method = function(methodName) {
		if(methodName[0] === '!')
			return function(obj) { return !obj[methodName.substring(1)](); };
		else
			return function(obj) { return obj[methodName](); };
	}
	f.n = function() {
		var args = arguments;
		if(args.length) args[args.length - 1] = "return " + args[args.length - 1];
		return Function.apply({}, args);
	}
	f.y = function(expression){
		var match = lambdaRegex.exec(expression);
		var argsString = match[1];
		var body = match[2];
		var args = argsString.split(',').map(f.method('trim'));
		return f.n.apply(f, args.concat(body));
	}
	return f;
});

Make it module loaders compatible


var throng = require('throng');
var donateServer = require('./server');
var workers = process.env.WEB_CONCURRENCY || 1;

function start() {
  var server = donateServer();

  server.start(function() {
    server.log('info', 'Running server at: ' + server.info.uri);
  });

  var shutdown = () => {
    server.stop({
      timeout: 15000 // wait fifteen seconds before forcefully terminating existing connections
    },() => {
      setTimeout(() => {
        process.exit(0);
      }, 15000);
    });
  };

  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);
}

// lol @ Infinity actually being used for something meaningful
throng(start, {
  workers,
  lifetime: Infinity
});

var throng = require('throng');
var donateServer = require('./server');
var workers = process.env.WEB_CONCURRENCY || 1;

function start() {
  var server = donateServer();

  server.start(function() {
    server.log('info', 'Running server at: ' + server.info.uri);
  });

  var shutdown = () => {
    // instruct hapi to stop accepting incoming requests, and to
    // wait fifteen seconds before forcefully terminating existing connections.
    // We do this so that we don't interrupt in-flight and queued requests
    server.stop({
      timeout: 15000
    },() => {
      // wait fifteen seconds before terminating the process (to allow for the existing request timeout to run it's course)
      setTimeout(() => {
        process.exit(0);
      }, 15000);
    });
  };

  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);
}

// lol @ Infinity actually being used for something meaningful
throng(start, {
  workers,
  lifetime: Infinity
});

Document the change to un-confuse future us


function ScrollSyncer (vertical, horizontal, usePassive) {
  this._from = null
  this._to = []
  this._bindOptions = usePassive
    ? { passive: true }
    : undefined

  this._sync = (function (e) {
    var target = e.target
    this._to.forEach(function (el) {
      if (vertical) el.scrollTop = target.scrollTop
      if (horizontal) el.scrollLeft = target.scrollLeft
    }, this)
  }).bind(this)
}

ScrollSyncer.prototype.from = function (target) {
  if (!target || !target.addEventListener) return
  this._from = target
  this._from.addEventListener('scroll', this._sync, this._bindOptions)
}

ScrollSyncer.prototype.to = function (target) {
  if (!target) return
  this._to.push(target)
}

ScrollSyncer.prototype.sync = function () {
  if (this._from) {
    this._sync({ target: this._from })
  }
}

ScrollSyncer.prototype.off = function (target) {
  if (target === undefined || target === this._from) {
    // remove event listener and release element reference
    if (this._from.removeEventListener) {
      this._from.removeEventListener('scroll', this._scrollHandler)
    }
    this._from = null
  }

  if (target === undefined) {
    this._to = []
  } else {
    var index = this._to.indexOf(target)
    if (index >= 0) {
      this._to.splice(index, 1)
    }
  }
}

module.exports = ScrollSyncer

function ScrollSyncer (vertical, horizontal) {
  this._from = null
  this._to = []

  this._sync = (function (e) {
    var target = e.target
    for (var i = 0; i < this._to.length; i++) {
      if (vertical) this._to[i].scrollTop = target.scrollTop
      if (horizontal) this._to[i].scrollTop = target.scrollLeft
    }
  }).bind(this)
}

ScrollSyncer.prototype.from = function (target) {
  if (!target || !target.addEventListener) return
  this._from = target
  this._from.addEventListener('scroll', this._sync)
}

ScrollSyncer.prototype.to = function (target) {
  if (!target) return
  this._to.push(target)
}

ScrollSyncer.prototype.sync = function () {
  if (this._from) {
    this._sync({ target: this._from })
  }
}

ScrollSyncer.prototype.off = function (target) {
  if (target === undefined || target === this._from) {
    // remove event listener and release element reference
    if (this._from.removeEventListener) {
      this._from.removeEventListener('scroll', this._scrollHandler)
    }
    this._from = null
  }

  if (target === undefined) {
    this._to = []
  } else {
    var index = this._to.indexOf(target)
    if (index >= 0) {
      this._to.splice(index, 1)
    }
  }
}

module.exports = ScrollSyncer

Remove passive option & improve performance


'use strict';

var fs = require('fs');
var path = require('path');
var dir = require('node-dir');
var q = require('q');

var findLicenses = function () {
    var deferred = q.defer();

    var modulesDir = path.join(process.cwd(), 'node_modules');

    dir.files(modulesDir, function (err, files) {
        var licenses = [];

        files.forEach(function (file) {
            if (/license/gi.test(file)) {
                var currPath = file.split(path.sep);
                var currModule = currPath[currPath.lastIndexOf('node_modules') + 1];

                licenses.push({
                    'module': currModule,
                    'license': file
                });
            }
        });

        deferred.resolve(licenses);
    });

    return deferred.promise;
};

findLicenses().then(function (data) {
    console.log(data);
});

'use strict';

var fs = require('fs');
var path = require('path');
var dir = require('node-dir');
var q = require('q');

var getLicenseType = function (info) {
    if (info.licenses) {
        return info.licenses[0];
    }

    if (info.license) {
        return info.license;
    }

    return '';
};

var findLicenses = function () {
    var deferred = q.defer();

    var modulesDir = path.join(process.cwd(), 'node_modules');

    dir.files(modulesDir, function (err, files) {
        var licenses = [];

        files.forEach(function (file) {
            if (/license/gi.test(file)) {
                var currPath = file.split(path.sep);
                var currModule = currPath[currPath.lastIndexOf('node_modules') + 1];

                var moduleInfo = {};

                try {
                    moduleInfo = require(path.join(path.dirname(file), 'package.json'));
                } catch (e) {
                    console.log('could not find package.json');
                }

                var licenseText = fs.readFileSync(file, 'utf8');

                licenses.push({
                    'module': currModule,
                    'license': getLicenseType(moduleInfo),
                    'license_file': file,
                    'content': licenseText
                });
            }
        });

        deferred.resolve(licenses);
    });

    return deferred.promise;
};

findLicenses().then(function (data) {
    fs.writeFile(path.join(process.cwd(), 'licensure.json'), JSON.stringify(data, null, 4), function (err) {
        if (err) {
            throw err;
        }

        console.log('done');
    });
});

Write license information to file


/**
 * @param {number} n
 * @param {number} k
 * @return {string}
 */
var getPermutation = function(n, k) {
    const nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    const totalNums = [1];
    let index = 1;
    let result = '';
    while (index <= n) {
        totalNums[index] = totalNums[totalNums.length - 1] * index;
        index += 1;
    }
    index = n;
    while (index > 1) {
        const seqInOneSection = totalNums[index] / index;
        const sectionKIsIn = Math.ceil(k / seqInOneSection);
        result += nums[sectionKIsIn];
        nums.splice(sectionKIsIn, 1);
        k = (k % seqInOneSection === 0) ? (k / sectionKIsIn) : k % seqInOneSection;
        index -= 1;
    }
    return result + nums[1];
};

/**
 * @param {number} n
 * @param {number} k
 * @return {string}
 */
var getPermutation = function(n, k) {
    const nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    const totalNums = [1];
    let index = 1;
    let result = '';
    while (index <= n) {
        totalNums[index] = totalNums[totalNums.length - 1] * index;
        index += 1;
    }
    index = n;
    while (index > 1) {
        const seqInOneSection = totalNums[index] / index;
        const sectionKIsIn = Math.ceil(k / seqInOneSection);
        result += nums[sectionKIsIn];
        nums.splice(sectionKIsIn, 1);
        k = (k % seqInOneSection === 0) ? seqInOneSection : k % seqInOneSection;
        index -= 1;
    }
    return result + nums[1];
};

Fix solution of leetcode question 60


import React, { Component } from 'react'
import PropTypes from 'prop-types'
import copy from 'copy-to-clipboard'

export default class CopyToClipboard extends Component {
  static propTypes = {
    value: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    copiedLabel: PropTypes.string,
    onClick: PropTypes.func,
  }

  static defaultProps = {
    onClick: () => {},
    copiedLabel: 'Copied!',
  }

  constructor(props) {
    super(props)

    this.state = {
      currentLabel: props.label,
    }
  }

  copyToClipboard = () => {
    const { value, onClick, label, copiedLabel } = this.props

    copy(value)

    this.setState({
      currentLabel: copiedLabel,
    })

    setTimeout(() => {
      this.setState({
        currentLabel: label,
      })
    }, 2000)

    return onClick()
  }

  render() {
    const { currentLabel } = this.state

    return (
      <a role="button" tabIndex={0} onClick={this.copyToClipboard}>
        {currentLabel}
      </a>
    )
  }
}

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import copy from 'copy-to-clipboard'

import Text from 'v2/components/UI/Text'

export default class CopyToClipboard extends Component {
  static propTypes = {
    value: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    copiedLabel: PropTypes.string,
    onClick: PropTypes.func,
  }

  static defaultProps = {
    onClick: () => {},
    copiedLabel: 'Copied!',
  }

  constructor(props) {
    super(props)

    this.state = {
      currentLabel: props.label,
    }
  }

  copyToClipboard = () => {
    const { value, onClick, label, copiedLabel } = this.props

    copy(value)

    this.setState({
      currentLabel: copiedLabel,
    })

    setTimeout(() => {
      this.setState({
        currentLabel: label,
      })
    }, 2000)

    return onClick()
  }

  render() {
    const { currentLabel } = this.state

    return (
      <a
        role="button"
        tabIndex={0}
        onClick={this.copyToClipboard}
        style={{ cursor: 'pointer' }}
      >
        <Text {...this.props}>{currentLabel}</Text>
      </a>
    )
  }
}

Update copy to clipboard style


import test from 'ava'
import Onionoo from '../'

test('Onionoo is a function', t => {
  t.is(typeof Onionoo, 'function')
})

test('Onionoo cannot be invoked without \'new\'', t => {
  t.throws(() => Onionoo())
  t.notThrows(() => new Onionoo())
})

test('Onionoo instance is an object', t => {
  t.is(typeof new Onionoo(), 'object')
})

Test Onionoo instance is an object


import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import 'raf/polyfill';

configure({ adapter: new Adapter() });

jest.mock('webAudioWrapper');

// noop console.log when WebAudioFont calls it because it's annoying
const originalLog = console.log

window.console.log = function(msg) {
  if (msg.includes('WebAudioFont')) {
    return null;
  }
  return originalLog(msg);
}

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import 'raf/polyfill';

configure({ adapter: new Adapter() });

jest.mock('webAudioWrapper');

// noop console.log when WebAudioFont calls it because it's annoying
const originalLog = console.log

window.console.log = function(msg) {
  if (typeof(msg) === 'string' && msg.includes('WebAudioFont')) {
    return null;
  }
  return originalLog(msg);
}

Fix error with console.log override


// Modules
const resolveDependencies = require('./resolveDependencies');

module.exports = (context, options = {}) => { // eslint-disable-line
  const {target, import: {static: useStaticImport = false} = {}} = options;

  // These are the plugins that are shared with all targets.
  const plugins = [
    // NOTE(mark): Decorators MUST come before class properties.
    'decorators-legacy',

    ['builtin-extend', {globals: ['Array', 'Error']}],
    'class-properties',
    'export-extensions',
    'object-rest-spread',
  ];

  return {
    // Remove comments and compact the code.
    comments: false,
    compact: true,

    presets: resolveDependencies('babel-preset', [
      target === 'node' && ['env', {
        targets: {node: 4},
      }],
      target === 'web' && ['env', {
        targets: {browsers: ['last 2 versions', 'safari >= 7']},
      }],
      target === 'react-native' && 'react-native',
    ]),
    plugins: [
      // Built-in babel plugin transforms.
      ...resolveDependencies('babel-plugin-transform', [
        target === 'node' && 'runtime',
        ...plugins,
      ]),

      // Custom babel plugin transforms.
      ...[
        useStaticImport && require('./transforms/static-import'),
      ].filter(Boolean),
    ],
  };
};

// Modules
const resolveDependencies = require('./resolveDependencies');

const getPresets = (target) => {
  switch (target) {
    case 'node':
      return [['env', {targets: {node: 4}}]];
    case 'react-native':
      return ['react-native'];
    case 'web':
      return [
        ['env', {targets: {browsers: ['last 2 versions', 'safari >= 7']}}],

        // NOTE(mark): This is included for now because it's compatible with
        // react + webpack which is the usecase for 'web' right now.
        'react-native',
      ];
    default:
      return [];
  }
};

const getPlugins = (target) => {
  switch (target) {
    case 'node':
      return ['runtime'];
    default:
      return [];
  }
};

// These are the plugins that are shared with all targets.
// NOTE(mark): Decorators MUST come before class properties.
const sharedPlugins = [
  'decorators-legacy',

  ['builtin-extend', {globals: ['Array', 'Error']}],
  'class-properties',
  'export-extensions',
  'object-rest-spread',
];

const getCustomPlugins = ({useStaticImport}) => {
  return [
    useStaticImport && require('./transforms/static-import'),
  ].filter(Boolean);
};

module.exports = (context, options = {}) => { // eslint-disable-line
  const {target, import: {static: useStaticImport = false} = {}} = options;

  return {
    // Remove comments and compact the code.
    comments: false,
    compact: true,

    presets: resolveDependencies('babel-preset', getPresets(target)),
    plugins: [
      // Built-in babel plugin transforms.
      ...resolveDependencies('babel-plugin-transform', sharedPlugins),
      ...resolveDependencies('babel-plugin-transform', getPlugins(target)),

      // Custom babel plugin transforms.
      ...getCustomPlugins({useStaticImport}),
    ],
  };
};

Split the babel-preset-jolt into helper functions and add react-native to web platform for now


var overload = require('../src/overload');
var should = require('should');

describe('overload', function() {
    describe('inherit', function() {
        it('it should exist', function() {
            overload.should.have.property('inherit');
        });
    });
});

var overload = require('../src/overload');
var should = require('should');

describe('overload', function() {
    describe('inherit', function() {
        it('should exist', function() {
            overload.should.have.property('inherit');
        });
    });
});

Remove "it" from test name


var Stirrup = function(library) {
  if(typeof library !== 'object' && typeof library !== 'function') {
    throw 'You must provide Stirrup with a promise library';
  }
  this.library = library;
  this.isNative = (typeof Promise === 'function' && Promise.toString().indexOf('[native code]') > -1);

  this.buildDefer();
  this.buildStaticFunctions();
  return this.getConstructor();
};

Stirrup.prototype.getConfig = function() {
  //@@config
  return config;
};

Stirrup.prototype.getConstructor = function() {
  if(!this.isNative) {
    return this.getConfig().constructor ? this.library[this.getConfig().constructor] : this.library;
  } else {
    return this.library;
  }
};

Stirrup.prototype.buildDefer = function() {
  if(this.isNative) {
    //TODO: Promise inspection capability
    //https://github.com/petkaantonov/bluebird/blob/master/API.md#inspect---promiseinspection
    this.defer = function() {
      var fulfill, reject;
      var promise = new Promise(function(f, r) {
        fulfill = f;
        reject = r;
      });
      return {
        fulfill: fulfill,
        reject: reject,
        promise: promise
      }
    }
  } else {
    this.defer = this.library.defer;
  }
};

var Stirrup = function(library) {
  if(typeof library !== 'object' && typeof library !== 'function') {
    throw 'You must provide Stirrup with a promise library';
  }
  this.library = library;
  this.isNative = (typeof Promise === 'function' && Promise.toString().indexOf('[native code]') > -1);

  var constructor = this.getConstructor();
  this.buildDefer(constructor);
  this.buildStaticFunctions();
  return constructor;
};

Stirrup.prototype.getConfig = function() {
  //@@config
  return config;
};

Stirrup.prototype.getConstructor = function() {
  if(!this.isNative) {
    return this.getConfig().constructor ? this.library[this.getConfig().constructor] : this.library;
  } else {
    return this.library;
  }
};

Stirrup.prototype.buildDefer = function(constructor) {
  var config = this.getConfig();
  if(!this.isNative && config.defer) {
    this.defer = this.library[config.defer];
  } else {
    //TODO: Promise inspection capability
    //https://github.com/petkaantonov/bluebird/blob/master/API.md#inspect---promiseinspection
    this.defer = function() {
      var fulfill, reject;
      var promise = new constuctor(function(f, r) {
        fulfill = f;
        reject = r;
      });
      return {
        fulfill: fulfill,
        reject: reject,
        promise: promise
      }
    }
  }
};

Refactor how defer is constructed


/**
 * default options
 */
const defaultOptions = {
  requestTimeout: 10 * 1000, //request timeout, default is 10s
  requestTimeoutCallback: () => {}, //request timeout callback
  sendPowerBy: true,
  sendExecTime: true
}

/**
 * send meta middleware
 */
module.exports = (options, app) => {
  options = Object.assign({}, defaultOptions, options);
  return (ctx, next) => {
    //set request timeout
    ctx.res.setTimeout(options.requestTimeout, options.requestTimeoutCallback);
    //send power by header
    if(options.sendPowerBy){
      const version = app.think.version;
      ctx.res.setHeader('X-Powered-By', `thinkjs-${version}`);
    }
    //send exec time header
    if(options.sendExecTime){
      const startTime = Date.now();
      let err;
      return next().catch(e => {
        err = e;
      }).then(() => {
        const endTime = Date.now();
        ctx.res.setHeader('X-Exec-Time', `${endTime - startTime}ms`);
        if(err) return Promise.reject(err);
      })
    }else{
      return next();
    }
  }
}

/**
 * default options
 */
const defaultOptions = {
  requestTimeout: 10 * 1000, //request timeout, default is 10s
  requestTimeoutCallback: () => {}, //request timeout callback
  sendPowerBy: true,  //send power by
  sendResponseTime: true //send response time
}

/**
 * send meta middleware
 */
module.exports = (options, app) => {
  options = Object.assign({}, defaultOptions, options);
  return (ctx, next) => {
    //set request timeout
    ctx.res.setTimeout(options.requestTimeout, options.requestTimeoutCallback);
    //send power by header
    if(options.sendPowerBy){
      const version = app.think.version;
      ctx.res.setHeader('X-Powered-By', `thinkjs-${version}`);
    }
    //send response time header
    if(options.sendResponseTime){
      const startTime = Date.now();
      let err;
      return next().catch(e => {
        err = e;
      }).then(() => {
        const endTime = Date.now();
        ctx.res.setHeader('X-Response-Time', `${endTime - startTime}ms`);
        if(err) return Promise.reject(err);
      })
    }else{
      return next();
    }
  }
}

Change exec time to response time


function removeItemsWithoutPriceDrops() {
  var lowPrice = 999999;
  var anyRemoved = false;
  var listItems = document.getElementsByClassName('a-section g-item-sortable');

  for (var i = 0; i < listItems.length; i++) {
    var priceDrop = listItems[i].querySelectorAll('.itemPriceDrop');
    var price = listItems[i].querySelectorAll('span.a-offscreen');
    if (price.length) {
      price = price[0].innerHTML;
      price = price.replace('$', '');
    } else {
      price = 0;
    }
    if (priceDrop.length == 0 || price > lowPrice) {
      listItems[i].parentElement.removeChild(listItems[i]);
      anyRemoved = true;
    }
  }

  if (anyRemoved) {
    removeItemsWithoutPriceDrops();
  }
}

removeItemsWithoutPriceDrops();

function removeItemsWithoutPriceDrops() {
  var lowPrice = 999999;
  var anyRemoved = false;
  var listItems = document.getElementsByClassName('a-spacing-none g-item-sortable');

  for (var i = 0; i < listItems.length; i++) {
    var priceDrop = listItems[i].querySelectorAll('.itemPriceDrop');
    var price = listItems[i].querySelectorAll('span.a-offscreen');
    if (price.length) {
      price = price[0].innerHTML;
      price = price.replace('$', '');
    } else {
      price = 0;
    }
    if (priceDrop.length == 0 || price > lowPrice) {
      listItems[i].parentElement.removeChild(listItems[i]);
      anyRemoved = true;
    }
  }

  if (anyRemoved) {
    removeItemsWithoutPriceDrops();
  }
}

removeItemsWithoutPriceDrops();

Update for new class selector


/* jshint expr:true */
import {
  describe,
  it,
  beforeEach,
  afterEach
} from 'mocha';
import { expect } from 'chai';
import Ember from 'ember';
import startApp from '../helpers/start-app';

describe('Acceptance: <%= classifiedModuleName %>', function() {
  var application;

  beforeEach(function() {
    application = startApp();
  });

  afterEach(function() {
    Ember.run(application, 'destroy');
  });

  it('can visit /<%= dasherizedModuleName %>', function() {
    visit('/<%= dasherizedModuleName %>');

    andThen(function() {
      expect(currentPath()).to.equal('<%= dasherizedModuleName %>');
    });
  });
});

Remove trailing whitespace from blueprint


import React from 'react';
import { Button, ScrollView, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';

import Home from '../components/Home';
import Page from '../components/Page';
import {nav} from '../stores/navigator';

Home.navigationOptions = {
  title: 'Home',
};
Page.navigationOptions = {
  title: 'Page',
};

const StackNavigation = StackNavigator({
  home: {
    screen: Home,
  },
  page: {
    path: 'page',
    screen: Page,
  },
});
debugger;
nav.setNavigator(StackNavigation);
export default StackNavigation;

import React from 'react';
import { Button, ScrollView, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';

import Home from '../shared/Home';
import Page from '../shared/Page';
import {nav} from '../../stores/navigator';

Home.navigationOptions = {
  title: 'Home',
};
Page.navigationOptions = {
  title: 'Page',
};

const StackNavigation = StackNavigator({
  home: {
    screen: Home,
  },
  page: {
    path: 'page',
    screen: Page,
  },
});
debugger;
nav.setNavigator(StackNavigation);
export default StackNavigation;

Fix missing paths in native from last commit


import Entity from 'mostly-entity';
import fp from 'mostly-func';

// 返回值定制
export default function responder () {
  return function (hook) {
    // If it was an internal call then skip this hook
    if (!hook.params.provider) {
      return hook;
    }

    let metadata = {};
    let data = hook.result;
    let message = '';

    if (hook.result && hook.result.data) {
      metadata = hook.result.metadata || fp.omit(['data'], hook.result);
      data = hook.result.data;
      message = hook.result.message || '';
    }

    hook.result = {
      status: 0,
      message: message,
      metadata: metadata,
      errors: [],
      data: data
    };
    return hook;
  };
}

Remove useless import of Entity


import React, { Component } from 'react';
import { Link } from 'react-router';
import map from 'lodash/map';
import classNames from 'classnames';

const ColorPicker = ({ colors, current, urlPrefix, onClick }) => {
  return (
    <div className="colorPicker">
      {map(colors, color => {
        const className = classNames('color', color.id, {
          active: current === color.id
        });

        return (
          <Link key={color.id}
            to={`${urlPrefix}${color.id}`}
            className={className} activeClassName="active"
            onClick={() => onClick(color.id)}
          >
          </Link>
        );
      })}
    </div>
  );
}

export default ColorPicker;

import React, { Component } from 'react';
import { Link } from 'react-router';
import map from 'lodash/map';
import classNames from 'classnames';

const ColorPicker = ({ colors, current, urlPrefix, onClick }) => {
  return (
    Object.keys(colors).length > 1
    ?

      {map(colors, color => {
        const className = classNames('color', color.id, {
          active: current === color.id
        });

        return (
          <Link key={color.id}
            to={`${urlPrefix}${color.id}`}
            className={className} activeClassName="active"
            onClick={() => onClick(color.id)}
          >
          </Link>
        );
      })}

    :

  );
}

export default ColorPicker;

Hide color picker if there is only one available


document.addEventListener("DOMContentLoaded", function() {
  document.getElementById("load-comments").addEventListener("click",function(e) {
    this.parentNode.removeChild(this);
    load_disqus();
  });
});

Comment stuff on document ready


import AuthenticateRoute from 'wholetale/routes/authenticate';
import { inject as service } from '@ember/service';
import RSVP from 'rsvp';

export default AuthenticateRoute.extend({
  internalState: service(),
  model(params) {
    this._super(params);
    this.get('internalState').set('currentInstanceId', params.instance_id);
    return RSVP.hash({
      instances: this.get('store').findAll('instance', {
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }),
      selected: this.get('store').findRecord('instance', params.instance_id, { reload: true })
    });
  }
});

import AuthenticateRoute from 'wholetale/routes/authenticate';
import { inject as service } from '@ember/service';
import RSVP from 'rsvp';

export default AuthenticateRoute.extend({
  internalState: service(),
  model(params) {
    this._super(params);
    this.get('internalState').set('currentInstanceId', params.instance_id);
    return RSVP.hash({
      instances: this.get('store').findAll('instance', {
        reload: true,
        adapterOptions: {
          queryParams: {
            limit: "0"
          }
        }
      }),
      selected: this.get('store').findRecord('instance', params.instance_id, { reload: true })
    });
  },
  actions: {
    error(error, transition) {
      // The docs led me to believe that the 'error' object would have a different format...
      // See https://guides.emberjs.com/v3.1.0/routing/loading-and-error-substates/#toc_the-error-event
      for (let err of error.errors) {

        // If we hit a 400 during transition, it is likely that
        // currentInstanceId is no longer valid.. Redirect to /browse instead
        if (err.status === '400') {
          this.replaceWith('browse');
          return true;
        }
      }
    }
  }
});

Handle 400 errors when transitioning to the /run/:id route


var _ = require('lodash');
var S = require('string');
var nodeMailer = require("nodemailer");
var secrets = require('../config/secrets');

function MailBoss() {
  var transporter = null;

  // Use Mandrill for prod envs.
  if (secrets.env == 'production') {
    console.log('PROD');
  }
  // Use MailDev for dev envs.
  else if (secrets.mailDev === 'MailDev') {
    console.log('MailDev');
    transporter = nodeMailer.createTransport({
      port: 1025,
      host: 'localhost',
      debug: true,
      maxConnections: 5,
      maxMessages: 10
    });
  }
  else if (secrets.mailDev === 'Mandrill') {
    console.log('Mandrill Dev Mode');
    transporter = nodeMailer.createTransport({
      host: 'smtp.mandrillapp.com',
      port: 587,
      debug: true,
      auth: {
        user: secrets.mandrill.user,
        pass: secrets.mandrill.apiKey
      }
    });
  }

  // Use stubmailer for travis envs.
  else {
    console.log('TEST');
  }
  this.transporter = transporter;
  this.defaults = {
    to: secrets.mailFrom,
    from: secrets.mailFrom,
    subject: 'I Should Have Set A Subject',
    text: 'MOO'
  }
}

MailBoss.prototype.send = function(mailOptions, callback) {
  var sendOptions = _.extend(this.defaults, mailOptions);
  this.transporter.sendMail(sendOptions, function(err, info) {
    callback(err, info);
  });
}

module.exports = MailBoss;

var _ = require('lodash');
var S = require('string');
var nodeMailer = require("nodemailer");
var secrets = require('../config/secrets');

function MailBoss() {
  var transporter = null;

  // Use Mandrill for prod envs.
  if (secrets.env == 'production') {
    console.log('PROD');
  }
  // Use MailDev for dev envs.
  else if (secrets.mailDev === 'MailDev') {
    console.log('MailDev');
    // TODO
  }
  else if (secrets.mailDev === 'Mandrill') {
    console.log('Mandrill Dev Mode');
    transporter = nodeMailer.createTransport({
      host: 'smtp.mandrillapp.com',
      port: 587,
      debug: true,
      auth: {
        user: secrets.mandrill.user,
        pass: secrets.mandrill.apiKey
      }
    });
  }

  // Use stubmailer for travis envs.
  else {
    console.log('TEST');
  }
  this.transporter = transporter;
  this.defaults = {
    to: secrets.mailFrom,
    from: secrets.mailFrom,
    subject: 'I Should Have Set A Subject',
    text: 'MOO'
  }
}

MailBoss.prototype.send = function(mailOptions, callback) {
  var sendOptions = _.extend(this.defaults, mailOptions);
  this.transporter.sendMail(sendOptions, function(err, info) {
    callback(err, info);
  });
}

module.exports = MailBoss;

Comment out maildev for now.


(function( $ ) {

  function generateRandomString(length) {
    var CHARS = "abcdefghjkmnpqrstuvwxyz23456789",
        output = "";
    while (output.length < length) {
      output += CHARS[Math.floor(Math.random() * CHARS.length)];
    }
    return output;
  }

  function addGenerateTokenLink() {
    var $token_field = $("#id_bearer_token"),
  $anchor = $('generate token');

    $token_field.after($anchor);

    $anchor.on("click", function(event){
      event.preventDefault();

      var answer = true;
      if ($token_field.val().length > 0) {
        answer = confirm("The bearer token field is not empty, are you sure you want to regenerate it?");
      }
      if (answer) {
  $token_field.val(generateRandomString(64));
      }

    });

  }

  $(addGenerateTokenLink);

})( django.jQuery );

(function( $ ) {

    function generate_data_set_name(data_group_name, data_type_name, $data_set_name_selector) {
      var data_set_name = [data_group_name, data_type_name].join('_').replace('-','_','g');

      if(!$data_set_name_selector.length){
        $('
'+data_set_name+'
').insertAfter('.field-name label');
      }
      $data_set_name_selector.html(data_set_name);
    }

    function generateRandomString(length) {
      var CHARS = "abcdefghjkmnpqrstuvwxyz23456789",
          output = "";
      while (output.length < length) {
        output += CHARS[Math.floor(Math.random() * CHARS.length)];
      }
      return output;
    }

    function addGenerateTokenLink() {
      var $token_field = $("#id_bearer_token"),
          $anchor = $('generate token');

      $token_field.after($anchor);

      $anchor.on("click", function(event){
        event.preventDefault();

        var answer = true;
        if ($token_field.val().length > 0) {
          answer = confirm("The bearer token field is not empty, are you sure you want to regenerate it?");
        }
        if (answer) {
            $token_field.val(generateRandomString(64));
        }

      });

    }

    $(addGenerateTokenLink);

  $(function() {

    $("#id_data_group, #id_data_type").on('change', function(){
        generate_data_set_name(
          $("#id_data_group").find("option:selected").text(),
          $("#id_data_type").find("option:selected").text(),
          $("#id_data_set")
        );
      }
    );
  });

})( django.jQuery );

Add data_set_name preview to data_set admin form


/* eslint-disable object-shorthand */
module.exports = {
  // We need to make sure that the transpiler hit the linoleum source since we are
  // not building to npm or simliar.
  ignore: function(filename) {
    return ((/node_modules/.test(filename))
        && !(/linoleum\/electron/.test(filename))
        && !(/linoleum\/src/.test(filename))
        && !(/linoleum\/tasks/.test(filename)))
        || (/\$.*\$/.test(filename));
  },
  sourceMap: 'inline',
  auxiliaryCommentBefore: 'istanbul ignore start',
  auxiliaryCommentAfter: 'istanbul ignore end',
  presets: [
    require.resolve('babel-preset-react'),
    require.resolve('babel-preset-es2015'),
    require.resolve('babel-preset-stage-0')
  ]
};

/* eslint-disable object-shorthand */
module.exports = {
  // We need to make sure that the transpiler hit the linoleum source since we are
  // not building to npm or simliar.
  ignore: function(filename) {
    return ((/node_modules/.test(filename))
        && !(/linoleum(-[^/]*)?\/electron/.test(filename))
        && !(/linoleum(-[^/]*)?\/src/.test(filename))
        && !(/linoleum(-[^/]*)?\/tasks/.test(filename)))
        || (/\$.*\$/.test(filename));
  },
  sourceMap: 'inline',
  auxiliaryCommentBefore: 'istanbul ignore start',
  auxiliaryCommentAfter: 'istanbul ignore end',
  presets: [
    require.resolve('babel-preset-react'),
    require.resolve('babel-preset-es2015'),
    require.resolve('babel-preset-stage-0')
  ]
};

Add linoleum subprojects to babel defaults


"use strict";

module.exports = function(sequelize, DataTypes) {

  var Client = sequelize.define('Client', {
    id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
    secret: DataTypes.STRING,
    //redirect_uris: DataTypes.STRING,
    name: DataTypes.STRING,

    //logo_uri
    //contacts
    //tos_uri
    //policy_uri
    //token_endpoint_auth_method
    //scope
    //grant_types
    //response_types
    //jwks_uri

    software_id: DataTypes.STRING,
    software_version: DataTypes.STRING,
    ip: DataTypes.STRING

  }, {
    updatedAt: 'last_update',
    createdAt: 'date_of_creation',
    associate: function(models) {
      Client.hasMany(models.AccessToken);
    }
  });

  return Client;
}

"use strict";

module.exports = function(sequelize, DataTypes) {

  var Client = sequelize.define('Client', {
    id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
    secret: DataTypes.STRING,
    //redirect_uris: DataTypes.STRING,
    name: DataTypes.STRING,

    //logo_uri
    //contacts
    //tos_uri
    //policy_uri
    //token_endpoint_auth_method
    //scope
    //grant_types
    //response_types
    //jwks_uri

    software_id: DataTypes.STRING,
    software_version: DataTypes.STRING,
    ip: DataTypes.STRING

  }, {
    associate: function(models) {
      Client.hasMany(models.AccessToken);
    }
  });

  return Client;
}

Change model createdAt and updatedAt fields to default


import { modularScale } from 'polished';

// Generate typography scale
const getTypeScale = (sizes, ratio) => {
	return Object.keys(sizes).reduce((scale, size) => {
		scale[size] = modularScale(sizes[size], 1, ratio).replace('em', 'rem');
		return scale;
	}, {});
};

export default getTypeScale;

import { modularScale } from 'polished';

// Generate typography scale
const getTypeScale = (sizes, ratio) => {
	return Object.keys(sizes).reduce((scale, size) => {
		// Convert to rems and remove unnecessary precision
		const value = parseFloat(modularScale(sizes[size], 1, ratio));
		scale[size] = `${Math.round(value * 1000) / 1000}rem`;
		return scale;
	}, {});
};

export default getTypeScale;

Make typography scale value a bit shorter


// Implement merge sort: "divide and conquer" algorithm using recursion

function mergeSort(arr) {
	if (arr.length < 2) {
		return arr;
	}

	var middle = parseInt(arr.length / 2),
		left = arr.slice(0, middle),
		right = arr.slice(middle, arr.length);

	return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
	var result = [];

	while (left.length && right.length) {
		if (left[0] <= right[0]) {
			result.push(left.shift());
		} else {
			result.push(right.shift());
		}
	}

	while (left.length) {
		result.push(left.shift());
	}

	while (right.length) {
		result.push(right.shift());
	}

	return result;
}

// test case
mergeSort([5, 4, 3, 2, 1]);

Add merge sort test case


function Rye (selector, context) {
    if (!(this instanceof Rye)){
        return new Rye(selector, context)
    }

    if (selector instanceof Rye){
        return selector
    }

    var util = Rye.require('Util')

    if (typeof selector === 'string') {
        this.selector = selector
        this.elements = this.qsa(context, selector)

    } else if (selector instanceof Array) {
        this.elements = util.unique(selector.filter(util.isElement))

    } else if (util.isNodeList(selector)) {
        this.elements = Array.prototype.slice.call(selector).filter(util.isElement)

    } else if (util.isElement(selector)) {
        this.elements = [selector]

    } else {
        this.elements = []
    }

    this._update()
}

Rye.version = '0.1.0'

// Minimalist module system
Rye._modules = {}

Rye.require = function (module) {
    return Rye._modules[module]
}

Rye.define = function (module, fn) {
    Rye._modules[module] = fn.call(Rye.prototype)
}

function Rye (selector, context) {
    if (!(this instanceof Rye)){
        return new Rye(selector, context)
    }

    if (selector instanceof Rye){
        return selector
    }

    var util = Rye.require('Util')

    if (typeof selector === 'string') {
        this.selector = selector
        this.elements = this.qsa(context, selector)

    } else if (selector instanceof Array) {
        this.elements = util.unique(selector.filter(util.isElement))

    } else if (util.isNodeList(selector)) {
        this.elements = Array.prototype.slice.call(selector).filter(util.isElement)

    } else if (util.isElement(selector)) {
        this.elements = [selector]

    } else {
        this.elements = []
    }

    this._update()
}

Rye.version = '0.1.2'

// Minimalist module system
Rye._modules = {}

Rye.require = function (module) {
    return Rye._modules[module]
}

Rye.define = function (module, fn) {
    Rye._modules[module] = fn.call(Rye.prototype)
}

Update internal version variable to 0.1.2


import {
  RepeatWrapping,
  UVMapping,
  NearestFilter,
  LinearMipMapLinearFilter,
  TextureLoader,
  Vector2
} from 'three';

const loader = new TextureLoader();

export class TextureModule {
  static load(url) {
    return new TextureModule({url}).texture;
  }

  textures = [];

  constructor(...textures) {
    textures.forEach(({
      url,
      type = 'map',
      offset = new Vector2(0, 0),
      repeat = new Vector2(1, 1),
      wrap = RepeatWrapping,
      mapping = UVMapping
    }) => {
      const texture = loader.load(url);

      if (wrap.length > 0) {
        texture.wrapS = wrap[0];
        texture.wrapT = wrap[1];
      } else
        texture.wrapS = texture.wrapT = wrap;

      texture.mapping = mapping;

      texture.offset.copy(offset);
      texture.repeat.copy(repeat);

      texture.magFilter = NearestFilter;
      texture.minFilter = LinearMipMapLinearFilter;

      this.textures.push([type, texture]);
    });
  }

  bridge = {
    material(material, self) {
      self.textures.forEach(texture => {
        material[texture[0]] = texture[1];
      });

      return material;
    }
  }
}

import {
  RepeatWrapping,
  UVMapping,
  NearestFilter,
  LinearMipMapLinearFilter,
  TextureLoader,
  Vector2
} from 'three';

const loader = new TextureLoader();

export class TextureModule {
  static load(url) {
    return new TextureModule({url}).texture;
  }

  textures = [];

  constructor(...textures) {
    textures.forEach(({
      url,
      type = 'map',
      offset = new Vector2(0, 0),
      repeat = new Vector2(1, 1),
      wrap = RepeatWrapping,
      mapping = UVMapping,
      fix = tex => tex
    }) => {
      const texture = loader.load(url);

      if (wrap.length > 0) {
        texture.wrapS = wrap[0];
        texture.wrapT = wrap[1];
      } else
        texture.wrapS = texture.wrapT = wrap;

      texture.mapping = mapping;

      texture.offset.copy(offset);
      texture.repeat.copy(repeat);

      texture.magFilter = NearestFilter;
      texture.minFilter = LinearMipMapLinearFilter;

      this.textures.push([type, fix(texture)]);
    });
  }

  bridge = {
    material(material, self) {
      self.textures.forEach(texture => {
        material[texture[0]] = texture[1];
      });

      return material;
    }
  }
}

Add ability to "fix" texture


import config from "config";
import ReactDOMServer from "react-dom/server";
import serialize from "serialize-javascript";
import "cookie-parser";
import Helmet from "react-helmet";

export default function renderPage(element, fetcher, userAgent) {
  const elementRendered = ReactDOMServer.renderToString(element);
  const helmet = Helmet.renderStatic();

  let link = "";
  if (config.get("html.style")) {
    link = helmet.link.toString();
  }

  global.navigator = { userAgent };
  return `
    <!doctype html>

        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <link rel="manifest" href="/manifest.json" />
        <link rel="icon" sizes="192x192" href="/img/logo.blue.transparent.192.png" />
        <link rel="apple-touch-icon" href="/img/logo.blue.white.192.png">
        <meta name="theme-color" content="#1a237e" />
        ${helmet.title.toString()}
        ${helmet.meta.toString()}
        ${link}

${elementRendered}

    `;
}

Hide mobile (also hidden in styles.css) when css is not loaded


'use strict';

var webpack = require('webpack');

module.exports = {
    output: {
        library: 'reactElementPan',
        libraryTarget: 'umd'
    },
    externals: {
        react: 'React'
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
        })
    ]
};

'use strict';

var webpack = require('webpack');

module.exports = {
    output: {
        library: 'reactElementPan',
        libraryTarget: 'umd'
    },
    externals: {
        react: {
            root: 'React',
            commonjs: 'react',
            commonjs2: 'react',
            amd: 'react'
        }
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
        })
    ]
};

Fix issue with react external name


var baseConfig = require('./webpackBaseConfig')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var path = require('path')

module.exports = [Object.assign({}, baseConfig, {
  plugins: baseConfig.plugins.concat([
    new ExtractTextPlugin('[name].css')
  ])
}), {
  entry: {
    htmlExport: path.join(__dirname, 'public/js/htmlExport.js')
  },
  module: {
    loaders: [{
      test: /\.css$/,
      loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
    }, {
      test: /\.scss$/,
      loader: ExtractTextPlugin.extract('style-loader', 'sass-loader')
    }, {
      test: /\.less$/,
      loader: ExtractTextPlugin.extract('style-loader', 'less-loader')
    }]
  },
  output: {
    path: path.join(__dirname, 'public/build'),
    publicPath: '/build/',
    filename: '[name].js'
  },
  plugins: [
    new ExtractTextPlugin('html.min.css')
  ]
}]

var baseConfig = require('./webpackBaseConfig')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var path = require('path')

module.exports = [Object.assign({}, baseConfig, {
  plugins: baseConfig.plugins.concat([
    new ExtractTextPlugin('[name].css')
  ]),
  devtool: 'source-map'
}), {
  devtool: 'source-map',
  entry: {
    htmlExport: path.join(__dirname, 'public/js/htmlExport.js')
  },
  module: {
    loaders: [{
      test: /\.css$/,
      loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
    }, {
      test: /\.scss$/,
      loader: ExtractTextPlugin.extract('style-loader', 'sass-loader')
    }, {
      test: /\.less$/,
      loader: ExtractTextPlugin.extract('style-loader', 'less-loader')
    }]
  },
  output: {
    path: path.join(__dirname, 'public/build'),
    publicPath: '/build/',
    filename: '[name].js'
  },
  plugins: [
    new ExtractTextPlugin('html.min.css')
  ]
}]

Enable source map in development build


var camelCase = require('camelcase');
var path = require('path');
var webpack = require('webpack');
var pkg = require(path.join(process.cwd(), 'package.json'));
var shouldMininimize = process.argv.indexOf('--min') !== -1;
var standardConfig = {
  entry: {
    'dist/bundle.js': './src/index.js'
  },
  output: {
    path: './',
    filename: '[name]',
    libraryTarget: 'umd',
    library: camelCase(pkg.name),
    sourceMapFilename: '[file].map'
  },
  module: {
    loaders: [{
      test: /\.css$/,
      loader: 'style!css'
    }, {
      test: /\.less$/,
      loader: 'style!css!less'
    }, {
      loader: 'babel-loader',
      test: /\.js$/,
      query: {
        presets: ['babel-preset-es2015', 'babel-preset-react']
      }
    }]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      include: /\.min\.js$/,
      minimize: true
    })
  ]
};

if (shouldMininimize) {
  Object.assign(standardConfig.entry, {
    'dist/bundle.min.js': './src/index.js'
  });
}

module.exports = standardConfig;

const camelCase = require('camelcase');
const path = require('path');
const webpack = require('webpack');
const pkg = require(path.join(process.cwd(), 'package.json'));
const shouldMininimize = process.argv.indexOf('--min') !== -1;
const standardConfig = {
  devtool: 'source-map',
  entry: {
    'dist/index-with-deps.js': './src/index.js',
    'dist/index-with-deps.min.js': './src/index.js',
  },
  output: {
    path: './',
    filename: '[name]',
    libraryTarget: 'umd',
    library: pkg['build:global'] || camelCase(pkg.name),
    sourceMapFilename: '[file].map',
  },
  module: {
    loaders: [{
      test: /\.css$/,
      loader: 'style!css',
    }, {
      test: /\.less$/,
      loader: 'style!css!less',
    }, {
      loader: 'babel-loader',
      test: /\.js$/,
      query: {
        presets: ['babel-preset-es2015', 'babel-preset-react'],
      },
    }],
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      include: /\.min\.js$/,
      minimize: true,
    }),
  ],
};

if (shouldMininimize) {
  Object.assign(standardConfig.entry, {
    'dist/bundle.min.js': './src/index.js',
  });
}

module.exports = standardConfig;

Rename bundle to index. Multple entry points for including deps and minifying. Add so


var path = require('path');
var webpack = require('webpack');

module.exports = {
   entry: './src/wordypass.js',
   output: {
       path: './dist/',
       filename: 'bundle.js'
   },
   module: {
       loaders: [
           { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}
       ]
   },
   plugins: [
       new webpack.optimize.UglifyJsPlugin({minimize: true})
   ]
};

var path = require('path');
var webpack = require('webpack');

module.exports = {
   entry: './src/wordypass.js',
   output: {
       path: './dist/',
       filename: 'bundle.js'
   },
   module: {
       loaders: [
           { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}
       ]
   },
   plugins: [
       //new webpack.optimize.UglifyJsPlugin({minimize: true})
   ]
};

Disable minification until we're ready to release


'use strict';

const { promisify } = require('util');
const { realpath, readFile } = require('fs');

const { capitalize } = require('underscore.string');

const { mapValues, mapKeys } = require('./functional');

const promisifyAll = function (obj) {
  const promisedObj = mapValues(obj, func => promisify(func));
  return mapKeys(promisedObj, (func, name) => `p${capitalize(name)}`);
};

const promise = promisifyAll({
  setTimeout,
  realpath,
  readFile,
});

module.exports = promise;

'use strict';

const { promisify } = require('util');
const { stat, realpath, readFile, readdir } = require('fs');

const { capitalize } = require('underscore.string');

const { mapValues, mapKeys } = require('./functional');

const promisifyAll = function (obj) {
  const promisedObj = mapValues(obj, func => promisify(func));
  return mapKeys(promisedObj, (func, name) => `p${capitalize(name)}`);
};

const promise = promisifyAll({
  setTimeout,
  realpath,
  readFile,
  stat,
  readdir,
});

module.exports = promise;

Add pStat and pReaddir utilities


tosMap.controller('MapsController', [
	"$scope", "Location",
	function ($scope, Location) {
		Location.query().$promise.then(function (response) {
			$scope.locations = response;
		});
	}
]);

tosMap.controller('MapsController', [
	"$scope", "Location",
	function ($scope, Location) {
		Location.query().$promise.then(function (response) {
			$scope.locations = response;
		});

		// Create the drag and move behavior
		$(document).ready(function(){
			var wndow, scrolling = false;

			$(window).on('mousedown', function(event) {
				wndow = {x:event.pageX, y: event.pageY};
				scrolling = true;
			});

			$(window).on('mousemove', function(event) {
				if (scrolling) {
					window.scrollBy(wndow.x - event.pageX, wndow.y - event.pageY);
					wndow = {x:event.pageX, y: event.pageY};
				}
			});

			$(window).on('mouseup', function () {
				scrolling = false;
				wndow = {};
			});
		});
	}
]);

Create the drag and drop behavior


 'use strict';

function cdAcceptBadgeCtrl($scope, $state, cdBadgesService, cdUsersService, alertService, $translate) {
  var userId = $state.params.userId;
  var badgeSlug = $state.params.badgeSlug;

  var parent = false;
  if ($scope.user){
    cdUsersService.userProfileData({userId: $scope.user.id}, function(profile){
      _.each(profile.children, function(child){
        if (child === userId) parent = true;
      })
      finish();
    })
  } else finish();

  function finish(){
    var badgeData = {
      userId: userId,
      parent: parent,
      badgeSlug: badgeSlug
    };

    cdBadgesService.acceptBadge(badgeData, function (response) {
      if(response.error) {
        return alertService.showError($translate.instant(response.error), function () {
          goToProfile();
        });
      }
      return alertService.showAlert($translate.instant('Badge Accepted!'), function () {
        goToProfile();
      });
    });
  }

  function goToProfile() {
    $state.go('user-profile', {userId: userId});
  }
}

angular.module('cpZenPlatform')
    .controller('accept-badge-controller', ['$scope', '$state', 'cdBadgesService', 'cdUsersService', 'alertService', '$translate', cdAcceptBadgeCtrl]);

 'use strict';

function cdAcceptBadgeCtrl($scope, $state, cdBadgesService, cdUsersService, alertService, $translate, auth) {
  var userId = $state.params.userId;
  var badgeSlug = $state.params.badgeSlug;

  var parent = false;

  auth.get_loggedin_user(function (user) {
    if (user){
      cdUsersService.userProfileData({userId: user.id}, function(profile){
        _.each(profile.children, function(child){
          if (child === userId) parent = true;
        })
        finish();
      })
    } else finish();
  });

  function finish(){
    var badgeData = {
      userId: userId,
      parent: parent,
      badgeSlug: badgeSlug
    };

    cdBadgesService.acceptBadge(badgeData, function (response) {
      if(response.error) {
        return alertService.showError($translate.instant(response.error), function () {
          goToProfile();
        });
      }
      return alertService.showAlert($translate.instant('Badge Accepted!'), function () {
        goToProfile();
      });
    });
  }

  function goToProfile() {
    $state.go('user-profile', {userId: userId});
  }
}

angular.module('cpZenPlatform')
    .controller('accept-badge-controller', ['$scope', '$state', 'cdBadgesService', 'cdUsersService', 'alertService', '$translate', 'auth', cdAcceptBadgeCtrl]);

Fix issue accepting badge on behalf of ninja


'use strict';

var express = require('express'),
	constants = require('./../config/constants'),
	config = require('./../config/config'),
	repository = require('./../util/repository'),
	router = express.Router();

var auth = require('./../services/auth');

router
	.get(constants.SIGN_OUT_PATH, function(req, res){

		var access_token = req.cookies[constants.AUTH_ACCESS_TOKEN_NAME];

    if (access_token === undefined) {
      res.send(400, {error: 'We need the access token cookie to be set.'});
    }

    repository.get(access_token).then(function(data){

      try {

        data = JSON.parse(data);

        auth.revokeRefreshToken(data.refresh_token).then(function(){

          repository.del(access_token);

          res.clearCookie(constants.AUTH_ACCESS_TOKEN_NAME, { path: '/api' });

          res.send(200, null);

        }, function(e){

          res.send(500, e);

        });

      } catch(e) {

        res.clearCookie(constants.AUTH_ACCESS_TOKEN_NAME, { path: '/api' });

        res.send(200, null);

      }

    }, function(){

      res.send(500);

    });

	})
	.get(constants.CLIENT_CONFIG_PATH, function(req, res){
		res.send(200, config.clientConfig);
		res.end();
	});

module.exports = router;

'use strict';

var express = require('express'),
	constants = require('./../config/constants'),
	config = require('./../config/config'),
	repository = require('./../util/repository'),
	router = express.Router();

var auth = require('./../services/auth');

router
	.get(constants.SIGN_OUT_PATH, function(req, res){

		var access_token = req.cookies[constants.AUTH_ACCESS_TOKEN_NAME];

    if (access_token === undefined) {
	    res.set('www-authenticate', constants.INVALID_TOKEN);
	    res.send(401);
	    return;
    }

    repository.get(access_token).then(function(data){

      try {

        data = JSON.parse(data);

        auth.revokeRefreshToken(data.refresh_token).then(function(){

          repository.del(access_token);

          res.clearCookie(constants.AUTH_ACCESS_TOKEN_NAME, { path: '/api' });

          res.send(200, null);

        }, function(e){

          res.send(500, e);

        });

      } catch(e) {

        res.clearCookie(constants.AUTH_ACCESS_TOKEN_NAME, { path: '/api' });

        res.send(200, null);

      }

    }, function(){

      res.send(500);

    });

	})
	.get(constants.CLIENT_CONFIG_PATH, function(req, res){
		res.send(200, config.clientConfig);
		res.end();
	});

module.exports = router;

Send correct response if logout authentication header is invalid. Fixes SWA-59


// use strict:
"use strict";

// Function gets the location of the user provided the user opts in
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(userPosition, showError);
} else {
        alert('Geolocation is not supported in your browser so cannot display your local weather');
}

// Success callback function
function userPosition(position) {
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
	console.log("User's latitude is " + lat + " User's longitude is " + lon);
    // return lat, lon; // how to return two vars?
}

// Error callback function
function showError(error) {
        switch(error.code) {
                case error.PERMISSION_DENIED:
                        alert("User denied the request for Geolocation.");
                        break;
                case error.POSITION_UNAVAILABLE:
                        alert("Location information is unavailable.");
                        break;
                case error.TIMEOUT:
                        alert("The request to get user location timed out.");
                        break;
                case error.UNKNOWN_ERROR:
                        alert("An unknown error occurred.");
                        break;
        }
}

// use strict:
"use strict";

// Function gets the location of the user provided the user opts in
// function adapted from Sitepoint; https://www.sitepoint.com/html5-geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(userPosition, showError);
} else {
        alert('Geolocation is not supported in your browser so cannot display your local weather');
}

// Success callback function
function userPosition(position) {
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
	console.log("User's latitude is " + lat + " User's longitude is " + lon);
    // return lat, lon; // how to return two vars?
}

// Error callback function
function showError(error) {
        switch(error.code) {
                case error.PERMISSION_DENIED:
                        alert("User denied the request for Geolocation.");
                        break;
                case error.POSITION_UNAVAILABLE:
                        alert("Location information is unavailable.");
                        break;
                case error.TIMEOUT:
                        alert("The request to get user location timed out.");
                        break;
                case error.UNKNOWN_ERROR:
                        alert("An unknown error occurred.");
                        break;
        }
}

Add source for geolocation function


var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;
var config		= require("config");

var ObjectId = mongoose.Schema.Types.ObjectId;

var APIKeySchema   = new Schema({
	user_id: { type: ObjectId, index: true },
	apikey: { type: String, index: true, unique: true },
	created: { type: Date, default: Date.now },
}, {
	timestamps: true
});

APIKeySchema.set("_perms", {
	//We can never change or view this directly
});

module.exports = mongoose.model('APIKey', APIKeySchema);

const mongoose     = require('mongoose');
const Schema       = mongoose.Schema;

const ObjectId = mongoose.Schema.Types.ObjectId;

const APIKeySchema   = new Schema({
	user_id: { type: ObjectId, index: true },
	apikey: { type: String, index: true, unique: true },
	created: { type: Date, default: Date.now },
	primary: { type: Boolean, index: true },
}, {
	timestamps: true
});

APIKeySchema.set("_perms", {
	//We can never change or view this directly
});

module.exports = mongoose.model('APIKey', APIKeySchema);

Mark a key as the primary key


const cp = require('child_process');
const chokidar = require('chokidar');

const exec = (cmd, args) => {
  return () => {
    var child = cp.spawn(cmd, args);

    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);
  };
};

const build = exec('npm', ['run', 'build']);
const buildDoc = exec('npm', ['run', 'build-doc']);
const uglify = exec('npm', ['run', 'uglify']);
const test = exec('npm', ['test']);

build();
buildDoc();
test();

chokidar.watch('src/**/*.js')
  .on('change', build)
  .on('unlink', build);

chokidar.watch('dist/redom.js')
  .on('change', uglify);

chokidar.watch('dist/doc.md')
  .on('change', buildDoc);

chokidar.watch('test/test.js')
  .on('change', test);

const cp = require('child_process');
const chokidar = require('chokidar');

const exec = (cmd, args) => {
  return () => {
    var child = cp.spawn(cmd, args, { shell: true });

    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);
  };
};

const build = exec('npm', ['run', 'build']);
const buildDoc = exec('npm', ['run', 'build-doc']);
const uglify = exec('npm', ['run', 'uglify']);
const test = exec('npm', ['test']);

build();
buildDoc();
test();

chokidar.watch('src/**/*.js')
  .on('change', build)
  .on('unlink', build);

chokidar.watch('dist/redom.js')
  .on('change', uglify);

chokidar.watch('dist/doc.md')
  .on('change', buildDoc);

chokidar.watch('test/test.js')
  .on('change', test);

Fix launching npm under windows (node 6+)


// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

base.require('ui.overlay');

base.unittest.testSuite('ui.overlay', function() {
  test('showHideUnparented', function() {
    var overlay = new ui.Overlay();
    overlay.innerHTML =
        '
Hello
B1:<button>foo</button>
B2:<button>blah</button>';
    overlay.visible = true;
    assertNotEquals(overlay.parentNode, null);

    overlay.visible = false;
    assertEquals(overlay.parentNode, null);
  });

  test('showHideParented', function() {
    var overlay = new ui.Overlay();
    overlay.innerHTML =
        '
Hello
B1:<button>foo</button>
B2:<button>blah</button>';

    document.body.appendChild(overlay);
    overlay.visible = true;
    assertNotEquals(overlay.parentNode, null);

    overlay.visible = false;
    assertEquals(overlay.parentNode, document.body);
    document.body.removeChild(overlay);
  });
});

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

base.require('ui.overlay');

base.unittest.testSuite('ui.overlay', function() {
  test('instantiate', function() {
    var dlg = new ui.Overlay();
    dlg.classList.add('example-overlay');
    dlg.innerHTML = '
ExampleOverlay
hello';

    var btn = document.createElement('button');
    btn.innerText = 'Launch Overlay';
    btn.addEventListener('click', function(e) {
      dlg.visible = true;
      e.stopPropagation();
    });

    this.addHTMLOutput(btn);
  });

  test('showHideUnparented', function() {
    var overlay = new ui.Overlay();
    overlay.innerHTML =
        '
Hello
B1:<button>foo</button>
B2:<button>blah</button>';
    overlay.visible = true;
    assertNotEquals(overlay.parentNode, null);

    overlay.visible = false;
    assertEquals(overlay.parentNode, null);
  });

  test('showHideParented', function() {
    var overlay = new ui.Overlay();
    overlay.innerHTML =
        '
Hello
B1:<button>foo</button>
B2:<button>blah</button>';

    document.body.appendChild(overlay);
    overlay.visible = true;
    assertNotEquals(overlay.parentNode, null);

    overlay.visible = false;
    assertEquals(overlay.parentNode, document.body);
    document.body.removeChild(overlay);
  });
});

Add test to launch an overlay


export default {
  stylePrefix: 'mdl-',

  title: '',

  content: '',

  backdrop: true,

  // Avoid rendering the default modal.
  custom: false,

  /**
   * Extend ModalView object (view/ModalView.js)
   * @example
   * extend: {
   *   template() {
   *     return '<div>...New modal template...</div>';
   *   },
   * },
   */
  extend: {}
};

export default {
  stylePrefix: 'mdl-',

  title: '',

  content: '',

  // Close modal on interact with backdrop
  backdrop: true,

  // Avoid rendering the default modal.
  custom: false,

  /**
   * Extend ModalView object (view/ModalView.js)
   * @example
   * extend: {
   *   template() {
   *     return '<div>...New modal template...</div>';
   *   },
   * },
   */
  extend: {}
};

Comment backdrop attribute of modal


import Ember from 'ember';

const {
  Route,
  getOwner,
  run
} = Ember;

Route.reopen({
  mount(engine, options) {
    console.log('mount', options);

    let owner = getOwner(this);

    let Engine = owner.lookup(`engine:${engine}`);

    let engineInstance = Engine.buildInstance();

    engineInstance.boot({parent: owner});

    let template = engineInstance.lookup('template:application');
    let controller = engineInstance.lookup('controller:application');
    let view = engineInstance.lookup('view:application');

    let renderOptions = {
      owner: engineInstance,
      into: options && options.into && options.into.replace(/\//g, '.'),
      outlet: (options && options.outlet) || 'main',
      template,
      controller,
      view
    };

    this.connections.push(renderOptions);

    run.once(this.router, '_setOutlets');
  }
});

import Ember from 'ember';

const {
  Route,
  getOwner,
  run
} = Ember;

Route.reopen({
  mount(engine, options) {
    console.log('mount', options);

    let owner = getOwner(this);

    let Engine = owner.lookup(`engine:${engine}`);

    let engineInstance = Engine.buildInstance();

    engineInstance.boot({parent: owner});

    let template = engineInstance.lookup('template:application');
    let controller = engineInstance.lookup('controller:application');
    let ViewClass = engineInstance._lookupFactory('view:application');

    let renderOptions = {
      owner: engineInstance,
      into: options && options.into && options.into.replace(/\//g, '.'),
      outlet: (options && options.outlet) || 'main',
      template,
      controller,
      ViewClass
    };

    this.connections.push(renderOptions);

    run.once(this.router, '_setOutlets');
  }
});

Fix teardown of routeless engines mounted from Route.


/*
 * grunt-browser-sync
 * https://github.com/shakyshane/grunt-browser-sync
 *
 * Copyright (c) 2013 Shane Osbourne
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {

    grunt.registerMultiTask("browserSync", "Keep your browsers in sync", function () {

        var done = this.async();

        var options = this.options();

        var patterns;

        if (this.data && this.data.bsFiles && this.data.bsFiles.src) {
            patterns = this.data.bsFiles.src;
            if (typeof patterns === "string") {
                patterns = [patterns];
            }
        }

        if (!patterns) {
            if (this.data.src) {
                patterns = this.data.src;
                if (typeof this.data.src === "string") {
                    patterns = [this.data.src];
                }
            }
        }

        if (!patterns) {
            if (this.filesSrc.length) {
                patterns = this.filesSrc;
            }
        }

        var browserSync  = require("browser-sync");

        browserSync.init(patterns, options);

        //noinspection JSUnresolvedVariable
        if (options.watchTask || options.watchtask || options.background) {
            // Wait until browserSync fully initializes
            browserSync.emitter.on('init', function() {
                done(); // Allow Watch task to run after
            });
        }
    });
};

/*
 * grunt-browser-sync
 * https://github.com/shakyshane/grunt-browser-sync
 *
 * Copyright (c) 2013 Shane Osbourne
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {

    grunt.registerMultiTask("browserSync", "Keep your browsers in sync", function () {

        var done = this.async();

        var options = this.options();

        var patterns;

        if (this.data && this.data.bsFiles && this.data.bsFiles.src) {
            patterns = this.data.bsFiles.src;
            if (typeof patterns === "string") {
                patterns = [patterns];
            }
        }

        if (!patterns) {
            if (this.data.src) {
                patterns = this.data.src;
                if (typeof this.data.src === "string") {
                    patterns = [this.data.src];
                }
            }
        }

        if (!patterns) {
            if (this.filesSrc.length) {
                patterns = this.filesSrc;
            }
        }

        var browserSync  = require("browser-sync");

        browserSync.init(patterns, options);

        //noinspection JSUnresolvedVariable
        if (options.watchTask || options.watchtask || options.background) {

            // Wait until browserSync fully initializes
            browserSync.emitter.on('service:running', function() {
                done(); // Allow Watch task to run after
            });
        }
    });
};

Change init event to service:running


// $(document).ready(function(){
//   // On click of resume link
//   $(".navLinkContainer__resumeLink").on ("click", function(){
//     var iframe = document.createElement('iframe');
//     iframe.setAttribute("src", "https://resume.creddle.io/embed/1rktq4ubpei");
//     iframe.width = 850 + "px";
//     iframe.height = 1100 + "px";
//
//     $("main").prepend("

");
//     $("#iframeContainer").html(iframe).append("
Close
");
//   }); // End of on click of resume link
//
//   //On click of resume Close tab
//   $("#close").on("click", function(){
//     $("#iframeContainer").remove();
//   }); // End of on click of resume Close tab
//
// });

// $(document).ready(function(){
//
// });

Remove resume iframe jQuery. Iframe doesn't bubble up and remove easily with jQuery.


var logEvents = angular.module('logEvents', []);

function mainController($scope, $http) {
	$scope.formData = {};

	// when landing on the page, get all events and show them
	$http.get('/api/events')
		.success(function(data) {
			$scope.events = data;

			var locations = [];

			angular.forEach(data, function(value, key) {
				var location = {
					lat: value.GPSlat,
					log: value.GPSlog,
					alt: value.GPSalt
				}

				this.push(location);
			}, locations);

			$scope.locations = locations;
		})
		.error(function(data) {
			console.log("Error: " + data);
		});
};

function extractPosition(data, callback) {
	var locations = [];

	data.every(function(element){
		locations += extractPosition(element);
	});
}

var logEvents = angular.module('logEvents', []);

function mainController($scope, $http) {
	$scope.formData = {};

	$http.get('/api/events')
		.success(function(data) {
			$scope.events = data;

			var locations = [];

			angular.forEach(data, function(value, key) {
				var location = {
					lat: value.GPSlat,
					log: value.GPSlog,
					alt: value.GPSalt
				};

				this.push(location);
			}, locations);

			$scope.locations = locations;
		})
		.error(function(data) {
			// redirect to 500.html
			$location.url('/500.html');
		});
};

Handle 500 error and removed old unused code


'use strict';

module.exports = class Plugin {

    constructor(name) {
        this._name  = name;
    }

    /**
     * Add this plugin to the configuration object.
     */
    configure(config) {
        throw new Error("Must implement configure function");
    }

    /**
     * Getter for the plugin name
     */
    get name() { return this._name; }

};

'use strict';

const _plugin_name = Symbol('name');

module.exports = class Plugin {

    constructor(name) {
        this[_plugin_name]  = name;
    }

    /**
     * Add this plugin to the configuration object.
     */
    configure(config) {
        throw new Error("Must implement configure function");
    }

    /**
     * Getter for the plugin name
     */
    get name() { return this[_plugin_name]; }

};

Convert to Symbol and getter


export class ExperimentStep {
    constructor(title, _type) {
        this.id = '';
        this.title = title;
        this._type = _type;
        this.steps = [];
        this.description = '';
        this.flags = {
            important: false,
            review: false,
            error: false,
            done: false
        };
        this.displayState = {
            details: {
                showTitle: true,
                showStatus: true,
                showNotes: true,
                showFiles: false,
                showSamples: false,
                currentFilesTab: 0,
                currentSamplesTab: 0
            },
            editTitle: true,
            open: false,
            maximize: false
        };
        this.node = null;
    }

    addStep(step) {
        this.steps.push(step);
    }
}

export class Experiment {
    constructor(name) {
        this.name = name;
        this.goal = '';
        this.description = 'Look at grain size as it relates to hardness';
        this.aim = '';
        this.done = false;
        this.steps = [];
    }

    addStep(title, _type) {
        let s = new ExperimentStep(title, _type);
        this.steps.push(s);
    }
}

export class ExperimentStep {
    constructor(title, _type) {
        this.id = '';
        this.title = title;
        this._type = _type;
        this.steps = [];
        this.description = '';
        this.flags = {
            important: false,
            review: false,
            error: false,
            done: false
        };
        this.displayState = {
            details: {
                showTitle: true,
                showStatus: true,
                showNotes: true,
                showFiles: false,
                showSamples: false,
                currentFilesTab: 0,
                currentSamplesTab: 0
            },
            editTitle: true,
            open: false,
            maximize: false
        };
        this.node = null;
    }

    addStep(step) {
        this.steps.push(step);
    }
}

export class Experiment {
    constructor(name) {
        this.name = name;
        this.goal = '';
        this.description = '';
        this.aim = '';
        this.status = 'in-progress';
        this.steps = [];
    }

    addStep(title, _type) {
        let s = new ExperimentStep(title, _type);
        this.steps.push(s);
    }
}

Remove hard coded experiment description. Remove done field and add status field since that is what we get from the backend.


import 'whatwg-fetch';

var helpers = {
  checkStatus,
  parseJSON,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  }
};

function checkStatus(res) {
  if (res.status >= 200 && res.status < 300) {
    return res;
  } else {
    var error = new Error(res.statusText);
    error.res = res;
    throw error;
  }
}

function parseJSON(res) {
  return res.json();
}

export default helpers;

import 'whatwg-fetch';

var helpers = {
  checkStatus,
  displayPrice,
  parseJSON,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  }
};

function checkStatus(res) {
  if (res.status >= 200 && res.status < 300) {
    return res;
  } else {
    var error = new Error(res.statusText);
    error.res = res;
    throw error;
  }
}

function displayPrice(price) {
  if (typeof price === 'string') {
    price = Number(price);
  }

  if (price % 1 === 0) {
    return '$' + price;
  } else {
    return '$' + price.toFixed(2);
  }
}

function parseJSON(res) {
  return res.json();
}

export default helpers;

Add function that displays prices


/**
 *
 *    Copyright (c) 2020 Silicon Labs
 *
 *    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.
 *
 *
 * @jest-environment node
 */

const electronMain = require('../src-electron/main-process/electron-main.js')
const window = require('../src-electron/main-process/window.js')

test('Make sure electron main process loads', () => {
  expect(electronMain.loaded).toBeTruthy()
})

test('Test constructing queries for the window', () => {
  var query = window.createQueryString(1, 'tuna')
  console.log(query)
  expect(query).toBe(`?sessionId=1&uiMode=tuna`)
  query = window.createQueryString()
  expect(query).toBe(``)
})

require('../src-electron/main-process/preference.js')

/**
 *
 *    Copyright (c) 2020 Silicon Labs
 *
 *    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.
 *
 *
 * @jest-environment node
 */

const electronMain = require('../src-electron/main-process/electron-main.js')
const window = require('../src-electron/main-process/window.js')

test('Make sure electron main process loads', () => {
  expect(electronMain.loaded).toBeTruthy()
})

test('Test constructing queries for the window', () => {
  var query = window.createQueryString(1, 'someUiMode')
  expect(query).toBe(`?sessionId=1&uiMode=someUiMode`)
  query = window.createQueryString()
  expect(query).toBe(``)
})

require('../src-electron/main-process/preference.js')

Remove an annoying log and remove introduction of oceanic fauna namespace, where there is no need for an additional namespace.


(function ( $ ) {
	"use strict";

	$(function () {

		// catch the upvote/downvote action
		$( 'div.comment-weight-container' ).on( 'click', 'span > a', function( e ){
			e.preventDefault();
			var value = 0;
			var comment_id = $(this).data('commentId');
			if ( $(this).hasClass( 'vote-up' ) ) {
				value = 1;
			} else if( $(this).hasClass( 'vote-down' ) ) {
				value = -1;
			}

			var post = $.post( comment_popularity.ajaxurl, {action: 'comment_vote', vote: value, comment_id: comment_id, hmn_vote_nonce: comment_popularity.hmn_vote_nonce} );

			post.done( function( data ) {

				if ( data.success === false ) {
					alert( data.data.error_message );
				} else {
					// update karma
					$( '#comment-weight-value-' + data.data.comment_id ).text( data.data.weight );
				}

			});

		});

	});

}(jQuery));

(function ( $ ) {
	"use strict";

	$(function () {

		// catch the upvote/downvote action
		$( 'div.comment-weight-container' ).on( 'click', 'span > a', function( e ){
			e.preventDefault();
			var value = 0;
			var comment_id = $(this).data('commentId');
			if ( $(this).hasClass( 'vote-up' ) ) {
				value = 1;
			} else if( $(this).hasClass( 'vote-down' ) ) {
				value = -1;
			}

			var post = $.post( comment_popularity.ajaxurl, {action: 'comment_vote_callback', vote: value, comment_id: comment_id, hmn_vote_nonce: comment_popularity.hmn_vote_nonce} );

			post.done( function( data ) {

				if ( data.success === false ) {
					alert( data.data.error_message );
				} else {
					// update karma
					$( '#comment-weight-value-' + data.data.comment_id ).text( data.data.weight );
				}

			});

		});

	});

}(jQuery));

Update ajax callback action param