'use strict';

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

function resourcificator ($http, $q) {

  var $resourcifyError = angular.$$minErr('resourcify'),
      requestOptions = ['query', 'get', '$get', '$save', '$update', '$delete'],
      requestMethods = {
        'query': 'GET',
        'get': 'GET',
        '$get': 'GET',
        '$save': 'POST',
        '$update': 'PUT',
        '$delete': 'DELETE'
      },
      validMethods = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH'],
      bodyMethods = ['$save', '$update', '$delete', 'PUT', 'POST', 'DELETE', 'PATCH'];

  function validMethod (method) {
    if (!~validMethods.indexOf(method)) {
      throw $resourcifyError('requesttype', '"@{0}" is not a valid request method.', method);
    }
    return method;
  }

  function replaceParams (params, url) {

  }
}

resourcificator.$inject = ['$http', '$q'];

resourcify.service('resourcify', resourcificator);

'use strict';

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

function resourcificator ($http, $q) {

  var $resourcifyError = angular.$$minErr('resourcify'),
      requestOptions = ['query', 'get', '$get', '$save', '$update', '$delete'],
      requestMethods = {
        'query': 'GET',
        'get': 'GET',
        '$get': 'GET',
        '$save': 'POST',
        '$update': 'PUT',
        '$delete': 'DELETE'
      },
      bodyMethods = ['$save', '$update', '$delete', 'PUT', 'POST', 'DELETE', 'PATCH'];

  // Finds and replaces query params and path params
  function replaceParams (params, url) {
    var findParam = /[\/=](:\w*[a-zA-Z]\w*)/g, copiedPath = angular.copy(url);
  }
}

resourcificator.$inject = ['$http', '$q'];

resourcify.service('resourcify', resourcificator);

Add regex for finding path params


//SatisfactionRatings.js: Client for the zendesk API.

var util        = require('util'),
    Client      = require('./client').Client,
    defaultgroups = require('./helpers').defaultgroups;

var SatisfactionRatings = exports.SatisfactionRatings = function (options) {
  this.jsonAPIName = 'satisfaction_ratings';
  Client.call(this, options);
};

// Inherit from Client base object
util.inherits(SatisfactionRatings, Client);

// ######################################################## SatisfactionRatings
// ====================================== Listing SatisfactionRatings
SatisfactionRatings.prototype.list = function (cb) {
  this.requestAll('GET', ['satisfaction_ratings'], cb);//all
};

SatisfactionRatings.prototype.received = function (cb) {
  this.requestAll('GET', ['satisfaction_ratings', 'received'], cb);//all
};

SatisfactionRatings.prototype.show = function (satisfactionRatingID, cb) {
  this.request('GET', ['satisfaction_ratings', satisfactionRatingID], cb);//all
};

// ====================================== Posting SatisfactionRatings
SatisfactionRatings.prototype.create = function (ticketID, satisfactionRating, cb) {
  this.request('POST', ['tickets', ticketId, 'satisfaction_rating'], satisfactionRating, cb);
};

Add support for creating Satisfaction Ratings


const chalk = require('chalk');

LOG_TYPES = {
    NONE: 0,
    ERROR: 1,
    NORMAL: 2,
    DEBUG: 3
};

let logType = LOG_TYPES.NORMAL;

const setLogType = (type) => {
    if (!(type in Object.values(LOG_TYPES))) return;

    logType = type;
};

const logTime = () => {
    let nowDate = new Date();
    return nowDate.toLocaleDateString() + ' ' + nowDate.toLocaleTimeString([], { hour12: false });
};

const log = (...args) => {
    if (logType < LOG_TYPES.NORMAL) return;

    console.log(logTime(), chalk.bold.green('[INFO]'), ...args);
};

const error = (...args) => {
    if (logType < LOG_TYPES.ERROR) return;

    console.log(logTime(), chalk.bold.red('[ERROR]'), ...args);
};

const debug = (...args) => {
    if (logType < LOG_TYPES.DEBUG) return;

    console.log(logTime(), chalk.bold.blue('[DEBUG]'), ...args);
};

module.exports = {
    LOG_TYPES,
    setLogType,

    log, error, debug
}

const chalk = require('chalk');

LOG_TYPES = {
    NONE: 0,
    ERROR: 1,
    NORMAL: 2,
    DEBUG: 3
};

let logType = LOG_TYPES.NORMAL;

const setLogType = (type) => {
    if (typeof type !== 'number') return;

    logType = type;
};

const logTime = () => {
    let nowDate = new Date();
    return nowDate.toLocaleDateString() + ' ' + nowDate.toLocaleTimeString([], { hour12: false });
};

const log = (...args) => {
    if (logType < LOG_TYPES.NORMAL) return;

    console.log(logTime(), chalk.bold.green('[INFO]'), ...args);
};

const error = (...args) => {
    if (logType < LOG_TYPES.ERROR) return;

    console.log(logTime(), chalk.bold.red('[ERROR]'), ...args);
};

const debug = (...args) => {
    if (logType < LOG_TYPES.DEBUG) return;

    console.log(logTime(), chalk.bold.blue('[DEBUG]'), ...args);
};

module.exports = {
    LOG_TYPES,
    setLogType,

    log, error, debug
}

Fix nodejs v6 'TypeError: Object.values is not a function'


import fs from 'fs';
import {
  pdf,
  View,
  Text,
  Link,
  Page,
  Font,
  Note,
  Image,
  version,
  Document,
  StyleSheet,
  PDFRenderer,
  createInstance,
} from './index';

export const renderToStream = function(element) {
  return pdf(element).toBuffer();
};

export const renderToFile = function(element, filePath, callback) {
  const output = renderToStream(element);
  const stream = fs.createWriteStream(filePath);

  output.pipe(stream);

  return new Promise((resolve, reject) => {
    stream.on('finish', () => {
      if (callback) callback(output, filePath);
      resolve(output);
    });
    stream.on('error', reject);
  });
};

export const render = renderToFile;

export {
  pdf,
  View,
  Text,
  Link,
  Page,
  Font,
  Note,
  Image,
  version,
  Document,
  StyleSheet,
  PDFRenderer,
  createInstance,
} from './index';

export default {
  pdf,
  View,
  Text,
  Link,
  Page,
  Font,
  Note,
  Image,
  version,
  Document,
  StyleSheet,
  PDFRenderer,
  createInstance,
  renderToStream,
  renderToFile,
  render,
};

import fs from 'fs';
import {
  pdf,
  View,
  Text,
  Link,
  Page,
  Font,
  Note,
  Image,
  version,
  Document,
  StyleSheet,
  PDFRenderer,
  createInstance,
} from './index';

export const renderToStream = function(element) {
  return pdf(element).toBuffer();
};

export const renderToFile = function(element, filePath, callback) {
  const output = renderToStream(element);
  const stream = fs.createWriteStream(filePath);

  output.pipe(stream);

  return new Promise((resolve, reject) => {
    stream.on('finish', () => {
      if (callback) callback(output, filePath);
      resolve(output);
    });
    stream.on('error', reject);
  });
};

const throwEnvironmentError = name => {
  throw new Error(
    `${name} is a web specific API. Or you're either using this component on Node, or your bundler is not loading react-pdf from the appropiate web build.`,
  );
};

export const PDFViewer = () => {
  throwEnvironmentError('PDFViewer');
};

export const PDFDownloadLink = () => {
  throwEnvironmentError('PDFDownloadLink');
};

export const BlobProvider = () => {
  throwEnvironmentError('BlobProvider');
};

export const render = renderToFile;

export {
  pdf,
  View,
  Text,
  Link,
  Page,
  Font,
  Note,
  Image,
  version,
  Document,
  StyleSheet,
  PDFRenderer,
  createInstance,
} from './index';

export default {
  pdf,
  View,
  Text,
  Link,
  Page,
  Font,
  Note,
  Image,
  version,
  Document,
  StyleSheet,
  PDFRenderer,
  createInstance,
  renderToStream,
  renderToFile,
  render,
};

Throw error when trying to use web specific APIs on Node


define(['rules/rules.module'
       ],
function() {
    angular.module('rules').factory('references',
    [
    function() {
        function generateReference(query) {
            var url = ('#/rules/explain?inference=' +
                       encodeURIComponent(angular.toJson(query, false)));
            var reference = { P854: [{ datatype: 'url',
                                       datavalue: { type: 'string',
                                                    value: url
                                                  },
                                       snaktype: 'value',
                                       property: 'P854'
                                     }]
                            };

            return [{ snaks: reference,
                      'snaks-order': ['P854']
                    }];
        }

        return { generateReference: generateReference
               };
    }]);

    return {};
});

define(['rules/rules.module'
       ],
function() {
    angular.module('rules').factory('references',
    [
    function() {
        function generateReference(query) {
            var bindings = [];

            angular.forEach(query.bindings, function(binding) {
                if ('id' in binding) {
                    bindings.push(binding.id);
                }
            });

            var info = { rule: query.rule,
                         query: query.query,
                         bindings: bindings,
                         constraints: query.constraints
            };
            var url = ('#/rules/explain?inference=' +
                       encodeURIComponent(angular.toJson(info, false)));
            var reference = { P854: [{ datatype: 'url',
                                       datavalue: { type: 'string',
                                                    value: url
                                                  },
                                       snaktype: 'value',
                                       property: 'P854'
                                     }]
                            };

            return [{ snaks: reference,
                      'snaks-order': ['P854']
                    }];
        }

        return { generateReference: generateReference
               };
    }]);

    return {};
});

Reduce amount of information in reference links


const Bluebird = require('bluebird');
const mongoose = require('mongoose');
const Alternative = require('../app/models/alternative');
const Election = require('../app/models/election');
const Vote = require('../app/models/vote');
const User = require('../app/models/user');

exports.dropDatabase = () =>
  mongoose.connection.dropDatabase().then(() => mongoose.disconnect());

exports.clearCollections = () =>
  Bluebird.map([Alternative, Election, Vote, User], collection =>
    collection.remove()
  );

const hash = '$2a$10$qxTI.cWwa2kwcjx4SI9KAuV4KxuhtlGOk33L999UQf1rux.4PBz7y'; // 'password'
const testUser = (exports.testUser = {
  username: 'testuser',
  cardKey: '99TESTCARDKEY',
  hash
});

const adminUser = (exports.adminUser = {
  username: 'admin',
  admin: true,
  cardKey: '55TESTCARDKEY',
  hash
});

exports.createUsers = () => User.create([testUser, adminUser]);

const Bluebird = require('bluebird');
const mongoose = require('mongoose');
const Alternative = require('../app/models/alternative');
const Election = require('../app/models/election');
const Vote = require('../app/models/vote');
const User = require('../app/models/user');

exports.dropDatabase = () =>
  mongoose.connection.dropDatabase().then(() => mongoose.disconnect());

exports.clearCollections = () =>
  Bluebird.map([Alternative, Election, Vote, User], collection =>
    collection.remove()
  );

const hash = '$2a$10$qxTI.cWwa2kwcjx4SI9KAuV4KxuhtlGOk33L999UQf1rux.4PBz7y'; // 'password'
const testUser = (exports.testUser = {
  username: 'testuser',
  cardKey: '99TESTCARDKEY',
  hash
});

const adminUser = (exports.adminUser = {
  username: 'admin',
  admin: true,
  moderator: true,
  cardKey: '55TESTCARDKEY',
  hash
});

exports.createUsers = () => User.create([testUser, adminUser]);

Make new code pass all new tests


import test from 'tape-catch';

var Symbol = require('es6-symbol');
var { curry, _ } = require('../module/index')({ Symbol });

test('The API is in good shape.', (is) => {
  is.equal(
    typeof curry,
    'function',
    '`curry_` is a function'
  );
  is.end();
});

test('basic usage', (is) => {
  const sum = (a, b, c) => a + b + c;

  is.equal(
    sum::curry()(1, 2, 3),
    6,
    'curries a function'
  );

  is.equal(
    sum::curry(1)(2, 3),
    6,
    'curries a function'
  );

  is.equal(
    sum::curry(1, 2)(3),
    6,
    'curries a function'
  );

  is.equal(
    sum::curry(1)(2)(3),
    6,
    'curries a function'
  );
  is.end();
});
test('placeholders', (is) => {
  const strJoin = (a, b, c) => '' + a + b + c;

  is.equal(
    strJoin::curry()(1, 2, 3),
    '123',
    'curries a function'
  );

  is.equal(
    strJoin::curry(1, _, 3)(2),
    '123',
    'curries a function'
  );

  is.equal(
    strJoin::curry(_, _, 3)(1)(2),
    '123',
    'curries a function'
  );

  is.equal(
    strJoin::curry(_, 2)(1)(3),
    '123',
    'curries a function'
  );

  is.end();
});

Add ES5 test by @stoeffel


var selftest = require('../selftest.js');
var Sandbox = selftest.Sandbox;
var files = require('../files.js');

// Add plugins to an app. Change the contents of the plugins and their
// dependencies, make sure that the app still refreshes.
selftest.define("add cordova platforms", function () {
  var s = new Sandbox();
  var run;

  // Starting a run
  s.createApp("myapp", "package-tests");
  s.cd("myapp");
  s.set("METEOR_TEST_TMP", files.mkdtemp());

  run = s.run("run", "android");
  run.matchErr("platform is not added");
  run.matchErr("meteor add-platform android");
  run.expectExit(1);

  run = s.run("add-platform", "android");
  run.match("Do you agree");
  run.write("Y\n");
  run.extraTime = 90; // Huge download
  run.match("added");

  run = s.run("remove-platform", "foo");
  run.match("foo is not");

  run = s.run("remove-platform", "android");
  run.match("removed");
  run = s.run("run", "android");
  run.matchErr("platform is not added");
  run.matchErr("meteor add-platform android");
  run.expectExit(1);
});

var selftest = require('../selftest.js');
var Sandbox = selftest.Sandbox;
var files = require('../files.js');

// Add plugins to an app. Change the contents of the plugins and their
// dependencies, make sure that the app still refreshes.
selftest.define("add cordova platforms", function () {
  var s = new Sandbox();
  var run;

  // Starting a run
  s.createApp("myapp", "package-tests");
  s.cd("myapp");
  s.set("METEOR_TEST_TMP", files.mkdtemp());

  run = s.run("run", "android");
  run.matchErr("Platform is not added");
  run.match("meteor add-platform android");
  run.expectExit(1);

  run = s.run("add-platform", "android");
  run.match("Do you agree");
  run.write("Y\n");
  run.extraTime = 90; // Huge download
  run.match("added");

  run = s.run("remove-platform", "foo");
  run.match("foo is not");

  run = s.run("remove-platform", "android");
  run.match("removed");
  run = s.run("run", "android");
  run.matchErr("Platform is not added");
  run.match("meteor add-platform android");
  run.expectExit(1);
});

Update 'add cordova platforms' to match latest command output


'use strict';

module.exports = (api) => {

  api.metasync.throttle = (
    // Function throttling
    timeout, // time interval
    fn, // function to be executed once per timeout
    args // arguments array for fn (optional)
  ) => {
    let timer = null;
    let wait = false;
    return function throttled() {
      if (!timer) {
        timer = setTimeout(() => {
          timer = null;
          if (wait) throttled();
        }, timeout);
        if (args) fn(...args);
        else fn();
        wait = false;
      } else {
        wait = true;
      }
    };
  };

  api.metasync.debounce = (
    timeout,
    fn,
    args = []
  ) => {
    let timer;
    return () => {
      clearTimeout(timer);
      timer = setTimeout(() => fn(...args), timeout);
    };
  };

  api.metasync.timeout = (
    // Set timeout for function execution
    timeout, // time interval
    asyncFunction, // async function to be executed
    // done - callback function
    done // callback function on done
  ) => {
    let finished = false;
    done = api.metasync.cb(done);

    const timer = setTimeout(() => {
      if (!finished) {
        finished = true;
        done();
      }
    }, timeout);

    asyncFunction(() => {
      if (!finished) {
        clearTimeout(timer);
        finished = true;
        done();
      }
    });
  };

};

'use strict';

module.exports = (api) => {

  api.metasync.throttle = (
    // Function throttling
    timeout, // time interval
    fn, // function to be executed once per timeout
    args // arguments array for fn (optional)
  ) => {
    let timer = null;
    let wait = false;
    return function throttled() {
      if (!timer) {
        timer = setTimeout(() => {
          timer = null;
          if (wait) throttled();
        }, timeout);
        if (args) fn(...args);
        else fn();
        wait = false;
      } else {
        wait = true;
      }
    };
  };

  api.metasync.debounce = (
    timeout,
    fn,
    args = []
  ) => {
    let timer;
    return () => {
      clearTimeout(timer);
      timer = setTimeout(() => fn(...args), timeout);
    };
  };

  api.metasync.timeout = (
    // Set timeout for function execution
    timeout, // time interval
    asyncFunction, // async function to be executed
    // done - callback function
    done // callback function on done
  ) => {
    let finished = false;
    done = api.metasync.cb(done);

    const timer = setTimeout(() => {
      if (!finished) {
        finished = true;
        done(null);
      }
    }, timeout);

    asyncFunction((err, data) => {
      if (!finished) {
        clearTimeout(timer);
        finished = true;
        done(err, data);
      }
    });
  };

};

Add null as error argument for callback


var semver = require('semver');

var versions = module.exports;

/**
Returns a number representation of the version number that can be compared with other such representations
e.g. compareable('0.6.12') > compareable('0.6.10')
*/
versions.compareable = function compareable(ver) {
  var parts = ver.split('.');
  return parseInt(parts.map(function(d){ while(d.length < 3) d = '0'+d; return d; }).join(''), 10);
}

/*
Returns the matching version number in a list of sorted version numbers
*/
versions.find = function(version_spec, list, cb) {
  var v, i = list.length-1;

  if(version_spec.match(/^stable$/i)) {
    if(i >= 0) do { v = list[i--] }while(v && parseInt(v.split('.')[1]) % 2 != 0 && i >= 0);// search for an even number: e.g. 0.2.0
  }else
  if(version_spec.match(/^latest$/i)) {
    v = list[list.length-1];
  }else{
    if(i >= 0) do { v = list[i--] }while(v && !semver.satisfies(v, version_spec) && i >= 0);
    if(!semver.satisfies(v, version_spec)) v = null;
  }
  if(!v) return cb(new Error('Version spec didn\'t match any available version'));
  cb(null, v);
};

var semver = require('semver');

var versions = module.exports;

/**
Returns a number representation of the version number that can be compared with other such representations
e.g. compareable('0.6.12') > compareable('0.6.10')
*/
versions.compareable = function compareable(ver) {
  var parts = ver.split('.');
  return parseInt(parts.map(function(d){ while(d.length < 3) d = '0'+d; return d; }).join(''), 10);
}

/*
Returns the matching version number in a list of sorted version numbers
*/
versions.find = function(version_spec, list, cb) {
  var v, i = list.length-1;

  if(version_spec.match(/^stable$/i)) {
    if(i >= 0) do { v = list[i--] }while(v && parseInt(v.split('.')[1]) % 2 != 0 && i >= 0);// search for an even number: e.g. 0.2.0
  }else
  if(version_spec.match(/^latest$/i)) {
    v = list[list.length-1];
  }else{
    if(i >= 0) do { v = list[i--] }while(v && !semver.satisfies(v, version_spec) && i >= 0);
    if(!semver.satisfies(v, version_spec)) v = null;
  }
  if(!v) return cb(new Error('Version spec, "' + version_spec + '", didn\'t match any available version'));
  cb(null, v);
};

Write out version spec that's being used, to make version errors more intuitive.


/**
 * Module dependencies.
 */
var TokenError = require('./tokenerror');

/**
 * `TokenError` error.
 *
 * @api public
 */
function MFARequiredError(message, uri, user) {
  TokenError.call(this, message, 'mfa_required', uri);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'MFARequiredError';
  this.user = user;
}

/**
 * Inherit from `TokenError`.
 */
MFARequiredError.prototype.__proto__ = TokenError.prototype;

/**
 * Expose `MFARequiredError`.
 */
module.exports = MFARequiredError;

/**
 * Module dependencies.
 */
var TokenError = require('./tokenerror');

/**
 * `TokenError` error.
 *
 * @api public
 */
function MFARequiredError(message, uri, user, areq) {
  TokenError.call(this, message, 'mfa_required', uri);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'MFARequiredError';
  this.user = user;
  this.req = areq;
}

/**
 * Inherit from `TokenError`.
 */
MFARequiredError.prototype.__proto__ = TokenError.prototype;

/**
 * Expose `MFARequiredError`.
 */
module.exports = MFARequiredError;

Add request to MFA error for keeping session context.


import * as privateMethods from './elements/private-methods.js';

const callbacks = ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback'];

export default function registerElement(tagName, Constructor) {

  // The WebIDL bindings generated this, thinking that they were in an ES6 world where the constructor they created
  // would be the same as the one registered with the system. So delete it and replace it with the one generated by
  // `document.registerElement`.
  delete window[Constructor.name];
  const GeneratedConstructor = window[Constructor.name] = document.registerElement(tagName, Constructor);

  // Delete any custom element callbacks since native elements don't have them and we don't want that kind of
  // observable difference. Their presence only matters at registration time anyway.
  for (const callback of callbacks) {
    delete GeneratedConstructor[callback];
  }

  // Register the appropriate private methods under the generated constructor name, since when they are looked up at
  // runtime it will be with that name. This is a band-aid until https://w3c.github.io/webcomponents/spec/custom/#es6
  // lands.
  const privateMethodsForConstructor = privateMethods.getAll(Constructor.name);
  if (privateMethodsForConstructor) {
    const registerElementGeneratedName = GeneratedConstructor.name;
    privateMethods.setAll(registerElementGeneratedName, privateMethodsForConstructor);
  }
}

import * as privateMethods from './elements/private-methods.js';

const callbacks = ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback'];

export default function registerElement(tagName, Constructor) {

  // The WebIDL bindings generated this, thinking that they were in an ES6 world where the constructor they created
  // would be the same as the one registered with the system. So delete it and replace it with the one generated by
  // `document.registerElement`.
  delete window[Constructor.name];
  const GeneratedConstructor = window[Constructor.name] = document.registerElement(tagName, Constructor);

  // Delete any custom element callbacks since native elements don't have them and we don't want that kind of
  // observable difference. Their presence only matters at registration time anyway.
  for (const callback of callbacks) {
    delete GeneratedConstructor.prototype[callback];
  }

  // Register the appropriate private methods under the generated constructor name, since when they are looked up at
  // runtime it will be with that name. This is a band-aid until https://w3c.github.io/webcomponents/spec/custom/#es6
  // lands.
  const privateMethodsForConstructor = privateMethods.getAll(Constructor.name);
  if (privateMethodsForConstructor) {
    const registerElementGeneratedName = GeneratedConstructor.name;
    privateMethods.setAll(registerElementGeneratedName, privateMethodsForConstructor);
  }
}

Fix logic for removing the custom element callbacks


'use strict';

var sandboxFactory = require('..'),
    MemoryFS = require('memory-fs'),
    memoryFS = new MemoryFS(),
    sandbox = sandboxFactory.create(memoryFS);

memoryFS.mkdirpSync('/my/dir');
memoryFS.writeFileSync(
    '/my/dir/file1.js',
    'console.log("File1"); require("./file2.js"); console.log("Then"); require("/my/dir"); console.log("End");'
);
memoryFS.writeFileSync(
    '/my/dir/index.js',
    'console.log("Index");'
);
memoryFS.writeFileSync(
    '/my/dir/file2.js',
    'console.log("File2");'
);

sandbox.execute('require("/my/dir/file1");');

'use strict';

var sandboxFactory = require('..'),
    mockFS = require('mock-fs').fs(),
    sandbox = sandboxFactory.create(mockFS);

mockFS.mkdirSync('/my');
mockFS.mkdirSync('/my/dir');
mockFS.writeFileSync(
    '/my/dir/file1.js',
    'console.log("File1"); require("./file2.js"); console.log("Then"); require("/my/dir"); console.log("End");'
);
mockFS.writeFileSync(
    '/my/dir/index.js',
    'console.log("Index");'
);
mockFS.writeFileSync(
    '/my/dir/file2.js',
    'console.log("File2");'
);

sandbox.execute('require("/my/dir/file1");');

Switch demo to use mock-fs rather than memory-fs


import HomeView from './HomeView';
import JoinView from './JoinView';

export default class ViewManager {
	constructor(target) {
		this.target = target;

		this.home = new HomeView();
		this.join = new JoinView();

		this.load('home');
	}

	load(viewName) {
		this[viewName].init().then(view => {

			// First remove all Childs
			while(this.target.firstChild) {
				this.target.removeChild(this.target.firstChild);
			}

			// Then load the view into it
			view.show(this.target);
		});
	}
}

import HomeView from './HomeView';
import JoinView from './JoinView';

export default class ViewManager {
	constructor(target) {
		this.target = target;

		// Register all known views
		this.home = new HomeView();
		this.join = new JoinView();

		// Define default view
		this.DEFAULT_VIEW = 'home';

		// Init URL bar and history
		this.init();
	}

	init() {
		if(location.hash == '')
			location.hash = '/';

		// Load the view given in the URL
		this.load(location.hash.substr(2), true);

		// Check history back and forward to load the correct view
		window.addEventListener('popstate', event => {
		  this.load(location.hash.substr(2), true);
		});
	}

	load(viewName = '', nohistory = false) {

		// Check if view exists
		if(!this[viewName || this.DEFAULT_VIEW])
			viewName = 'notfound';

		// Init the new view (load template etc.)
		this[viewName || this.DEFAULT_VIEW].init().then(view => {

			// Push the new view to the URL and the history
			if(!nohistory)
				history.pushState(null, viewName || this.DEFAULT_VIEW, `#/${viewName}`);

			// Remove the old view
			while(this.target.firstChild) {
				this.target.removeChild(this.target.firstChild);
			}

			// Load the view
			view.show(this.target);
		});
	}
}

Add URL support with history.pushState


var Promise = require('es6-promise').Promise;
var lodash = require('lodash');
var validateWithHtmllint = require('./html/htmllint.js');
var validateWithSlowparse = require('./html/slowparse.js');

function filterErrors(errors) {
  var indexedErrors = lodash(errors).indexBy('reason');

  var suppressedTypes = indexedErrors.
    values().
    map('suppresses').
    flatten().
    value();

  return indexedErrors.omit(suppressedTypes).values().value();
}

module.exports = function(source) {
  return Promise.all([
    validateWithSlowparse(source),
    validateWithHtmllint(source),
  ]).then(function(results) {
    var filteredErrors = filterErrors(lodash.flatten(results));
    return lodash.sortBy(filteredErrors, 'row');
  });
};

var Promise = require('es6-promise').Promise;
var lodash = require('lodash');
var validateWithHtmllint = require('./html/htmllint.js');
var validateWithSlowparse = require('./html/slowparse.js');

function filterErrors(errors) {
  var groupedErrors = lodash(errors).groupBy('reason');

  var suppressedTypes = groupedErrors.
    values().
    flatten().
    map('suppresses').
    flatten().
    value();

  return groupedErrors.omit(suppressedTypes).values().flatten().value();
}

module.exports = function(source) {
  return Promise.all([
    validateWithSlowparse(source),
    validateWithHtmllint(source),
  ]).then(function(results) {
    var filteredErrors = filterErrors(lodash.flatten(results));
    return lodash.sortBy(filteredErrors, 'row');
  });
};

Allow the same error on different lines


// Parse backticks

'use strict';

module.exports = function backtick(state, silent) {
  var start, max, marker, matchStart, matchEnd, token,
      pos = state.pos,
      ch = state.src.charCodeAt(pos);

  if (ch !== 0x60/* ` */) { return false; }

  start = pos;
  pos++;
  max = state.posMax;

  while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }

  marker = state.src.slice(start, pos);

  matchStart = matchEnd = pos;

  while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {
    matchEnd = matchStart + 1;

    while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }

    if (matchEnd - matchStart === marker.length) {
      if (!silent) {
        token         = state.push('code_inline', 'code', 0);
        token.markup  = marker;
        token.content = state.src.slice(pos, matchStart)
          .replace(/\n/g, ' ')
          .replace(/^ (.+) $/, '$1');
      }
      state.pos = matchEnd;
      return true;
    }
  }

  if (!silent) { state.pending += marker; }
  state.pos += marker.length;
  return true;
};

// Parse backticks

'use strict';

module.exports = function backtick(state, silent) {
  var start, max, marker, matchStart, matchEnd, token,
      pos = state.pos,
      ch = state.src.charCodeAt(pos);

  if (ch !== 0x60/* ` */) { return false; }

  start = pos;
  pos++;
  max = state.posMax;

  while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }

  marker = state.src.slice(start, pos);

  matchStart = matchEnd = pos;

  while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {
    matchEnd = matchStart + 1;

    while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }

    if (matchEnd - matchStart === marker.length) {
      if (!silent) {
        token         = state.push('code_inline', 'code', 0);
        token.markup  = marker;
        token.content = state.src.slice(pos, matchStart)
          .replace(/\n/g, ' ')
          .replace(/^ (.+) $/, '$1');
        token.position = start;
        token.size = (matchStart + 1) - token.position;
      }
      state.pos = matchEnd;
      return true;
    }
  }

  if (!silent) { state.pending += marker; }
  state.pos += marker.length;
  return true;
};

Add position and size to code_inline


ManageIQ.angular.app.directive('resetValidationStatus', ['$rootScope', function($rootScope) {
  return {
    require: 'ngModel',
    link: function (scope, elem, attrs, ctrl) {
      scope.$watch(attrs.ngModel, function() {
        adjustValidationStatus(ctrl.$modelValue, scope, ctrl, attrs, $rootScope);
      });

      ctrl.$parsers.push(function(value) {
        adjustValidationStatus(value, scope, ctrl, attrs, $rootScope);
        return value;
      });
    }
  }
}]);

var adjustValidationStatus = function(value, scope, ctrl, attrs, rootScope) {
  if(scope.checkAuthentication === true && angular.isDefined(scope.postValidationModel)) {
    var modelPostValidationObject = angular.copy(scope.postValidationModel[attrs.prefix]);
    delete modelPostValidationObject[ctrl.$name];

    var modelObject = angular.copy(scope[scope.model]);
    if(angular.isDefined(modelObject[ctrl.$name])) {
      delete modelObject[ctrl.$name];
    }

    if (value == scope.postValidationModel[attrs.prefix][ctrl.$name] && _.isMatch(modelObject, modelPostValidationObject)) {
      scope[scope.model][attrs.resetValidationStatus] = true;
      rootScope.$broadcast('clearErrorOnTab', {tab: attrs.prefix});
    } else {
      scope[scope.model][attrs.resetValidationStatus] = false;
      rootScope.$broadcast('setErrorOnTab', {tab: attrs.prefix});
    }
  }
};

ManageIQ.angular.app.directive('resetValidationStatus', ['$rootScope', function($rootScope) {
  return {
    require: 'ngModel',
    link: function (scope, elem, attrs, ctrl) {
      scope.$watch(attrs.ngModel, function() {
        adjustValidationStatus(ctrl.$modelValue, scope, ctrl, attrs, $rootScope);
      });

      ctrl.$parsers.push(function(value) {
        adjustValidationStatus(value, scope, ctrl, attrs, $rootScope);
        return value;
      });
    }
  }
}]);

var adjustValidationStatus = function(value, scope, ctrl, attrs, rootScope) {
  if(scope.checkAuthentication === true &&
     angular.isDefined(scope.postValidationModel) &&
     angular.isDefined(scope.postValidationModel[attrs.prefix])) {
    var modelPostValidationObject = angular.copy(scope.postValidationModel[attrs.prefix]);
    delete modelPostValidationObject[ctrl.$name];

    var modelObject = angular.copy(scope[scope.model]);
    if(angular.isDefined(modelObject[ctrl.$name])) {
      delete modelObject[ctrl.$name];
    }

    if (value == scope.postValidationModel[attrs.prefix][ctrl.$name] && _.isMatch(modelObject, modelPostValidationObject)) {
      scope[scope.model][attrs.resetValidationStatus] = true;
      rootScope.$broadcast('clearErrorOnTab', {tab: attrs.prefix});
    } else {
      scope[scope.model][attrs.resetValidationStatus] = false;
      rootScope.$broadcast('setErrorOnTab', {tab: attrs.prefix});
    }
  }
};

Check if postValidationModel is defined for the tab in question


import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

const { Route, RSVP } = Ember;
const { Promise, all, map } = RSVP;

export default Route.extend(AuthenticatedRouteMixin, {
  afterModel(course){
    return all([
      this.loadCourseLearhingMaterials(course),
      this.loadSessionLearhingMaterials(course),
    ])

  },
  loadCourseLearhingMaterials(course){
    return new Promise(resolve => {
      course.get('learningMaterials').then(courseLearningMaterials => {
        all(courseLearningMaterials.getEach('learningMaterial')).then(()=> {
          resolve();
        })
      });
    });
  },
  loadSessionLearhingMaterials(course){
    return new Promise(resolve => {
      course.get('sessions').then(sessions => {
        map(sessions.toArray(), session => {
          return all([
            session.get('learningMaterials'),
            session.get('firstOfferingDate')
          ]);
        }).then(()=>{
          resolve();
        })
      });
    });
  }
});

import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

const { Route, RSVP } = Ember;
const { Promise, all, map } = RSVP;

export default Route.extend(AuthenticatedRouteMixin, {
  afterModel(course){
    return all([
      this.loadCourseLearningMaterials(course),
      this.loadSessionLearningMaterials(course),
    ])

  },
  loadCourseLearningMaterials(course){
    return new Promise(resolve => {
      course.get('learningMaterials').then(courseLearningMaterials => {
        all(courseLearningMaterials.getEach('learningMaterial')).then(()=> {
          resolve();
        })
      });
    });
  },
  loadSessionLearningMaterials(course){
    return new Promise(resolve => {
      course.get('sessions').then(sessions => {
        map(sessions.toArray(), session => {
          return all([
            session.get('learningMaterials'),
            session.get('firstOfferingDate')
          ]);
        }).then(()=>{
          resolve();
        })
      });
    });
  }
});

Fix typo/miss spell in method names


gRenderer = {
  frame: 0,
  render: function() {
    this.context.fillStyle = '#000';
    this.context.fillRect(0, 0, this.context.canvas.width, this.context.canvas.height);

    switch (gScene.scene) {
      case 'title':
        gScene.renderTitle();
        break;
      case 'hangar':
      case 'game':
        gScene.renderBack();
        if (gPlayer.life > 0) gPlayer.render();
        gScene.renderFore();
        gPlayer.projectiles.forEach(function(p) { p.render() }.bind(this));
        if (gScene.inTransition) gScene.renderTransition();
        break;
      case 'levelTitle':
        gScene.renderLevelTitle();
        break;
    }

    if (!gScene.inTransition) gInput.render();
    // Debug display
    // this.context.font = '16px monospace';
    // this.context.textAlign = 'left';
    // this.context.fillStyle = '#FFF';
    // this.context.fillText('gCamera: ' + gCamera.x + ', ' + gCamera.y + ' vel: ' + gCamera.xVel + ', ' + gCamera.yVel, 12, 12);
    // this.context.fillText('gPlayer: ' + gPlayer.x + ', ' + gPlayer.y + ' vel: ' + gPlayer.xVel + ', ' + gPlayer.yVel, 12, 36);

    this.frame = (this.frame + 1) % 60;
  }
}

gRenderer = {
  frame: 0,
  render: function() {
    this.context.fillStyle = '#000';
    this.context.fillRect(0, 0, this.context.canvas.width, this.context.canvas.height);

    switch (gScene.scene) {
      case 'title':
        gScene.renderTitle();
        break;
      case 'hangar':
      case 'game':
        gScene.renderBack();
        if (gPlayer.life > 0) gPlayer.render();
        gScene.renderFore();
        gPlayer.projectiles.forEach(function(p) { p.render() }.bind(this));
        if (gScene.inTransition) gScene.renderTransition();
        break;
      case 'levelTitle':
        gScene.renderLevelTitle();
        break;
    }

    if (!gScene.inTransition) gInput.render();
    // Debug display
    // this.context.font = '16px monospace';
    // this.context.textAlign = 'left';
    // this.context.fillStyle = '#FFF';
    // this.context.fillText('gCamera: ' + gCamera.x + ', ' + gCamera.y + ' vel: ' + gCamera.xVel + ', ' + gCamera.yVel, 12, 12);
    // this.context.fillText('gPlayer: ' + gPlayer.x + ', ' + gPlayer.y + ' vel: ' + gPlayer.xVel + ', ' + gPlayer.yVel, 12, 36);

    this.frame = (this.frame + 1) % 240;
  }
}

Increase gRenderer frame max to 240


const LifeforcePlugin = require("../utils/LifeforcePlugin.js");

const serverhostname = "http://localhost:16001";
//const serverhostname = "https://api.repkam09.com";

class MetaEndpoints extends LifeforcePlugin {
    constructor(restifyserver, logger, name) {
        super(restifyserver, logger, name);
        this.apiMap = [
            {
                path: "/api/about",
                type: "get",
                handler: handleAboutApi
            },
            {
                path: "/",
                type: "get",
                handler: handleAboutApi
            }
        ];
    }
}

function handleAboutApi(req, res, next) {
    var apis = [];
    var keys = Object.keys(this.restifyserver.router.mounts);
    keys.forEach((key) => {
        var current = this.restifyserver.router.mounts[key];
        apis.push({ path: serverhostname + current.spec.path, method: current.method });
    });
    res.send(200, apis);
}

module.exports = MetaEndpoints;

const LifeforcePlugin = require("../utils/LifeforcePlugin.js");

//const serverhostname = "http://localhost:16001";
const serverhostname = "https://api.repkam09.com";

class MetaEndpoints extends LifeforcePlugin {
    constructor(restifyserver, logger, name) {
        super(restifyserver, logger, name);
        this.apiMap = [
            {
                path: "/api/about",
                type: "get",
                handler: handleAboutApi
            },
            {
                path: "/",
                type: "get",
                handler: handleAboutApi
            }
        ];
    }
}

function handleAboutApi(req, res, next) {
    var apis = [];
    var keys = Object.keys(this.restifyserver.router.mounts);
    keys.forEach((key) => {
        var current = this.restifyserver.router.mounts[key];
        apis.push({ path: serverhostname + current.spec.path, method: current.method });
    });
    res.send(200, apis);
}

module.exports = MetaEndpoints;

Fix url to real production url


'use strict';

var should = require('should');
var config = require('../config/configuration.js');
var retrieve = require('../lib/provider-google-drive/helpers/retrieve.js');

describe("Retrieve files", function () {
  it("should list files when no id passed and return the id of the last document", function(done) {
    retrieve(config.test_refresh_token, null, config, function(err, files, lastId) {
      if(err) {
        throw err;
      }
      files.should.have.lengthOf(4);
      should.exist(files[0]);
      lastId.should.equal("49");
      files[0].should.have.property('id', '1wnEFyXM4bSaSqMORS0NycszCse9dJvhYoiZnITRMeCE');
      files[0].should.have.property('title', 'Test');
      files[0].should.have.property('mimeType', 'application/vnd.google-apps.document');
      done();
    });
  });
  it("should list files from a given id", function(done) {
    retrieve(config.test_refresh_token, "44", config, function(err, files, lastId) {
      if(err) {
        throw err;
      }
      files.length.should.equal(3);
      done();
    });
  });
});

'use strict';

var should = require('should');
var config = require('../config/configuration.js');
var retrieve = require('../lib/provider-google-drive/helpers/retrieve.js');

describe("Retrieve files", function () {
  it("should list files when no id passed and return the id of the last document", function(done) {
    retrieve(config.test_refresh_token, null, config, function(err, files, lastId) {
      if(err) {
        throw err;
      }
      files.should.have.lengthOf(4);
      should.exist(files[0]);
      lastId.should.equal("82");
      files[0].should.have.property('id', '1wnEFyXM4bSaSqMORS0NycszCse9dJvhYoiZnITRMeCE');
      files[0].should.have.property('title', 'Test');
      files[0].should.have.property('mimeType', 'application/vnd.google-apps.document');
      done();
    });
  });
  it("should list files from a given id", function(done) {
    retrieve(config.test_refresh_token, "44", config, function(err, files, lastId) {
      if(err) {
        throw err;
      }
      files.length.should.equal(4);
      done();
    });
  });
});

Update to the new drive state


#!/usr/bin/env node
"use strict";

process.title = "oui";

var arg  = process.argv[2],
    oui  = require("./"),
    spin = require("char-spinner");

if (arg === "--update") {
    var interval = spin();
    oui.update(true, function (err) {
        clearInterval(interval);
        if (err) process.stdout.write(err + "\n");
        process.exit(err ? 1 : 0);
    });
} else if (!arg || arg === "--help") {
    process.stdout.write([
        "",
        "  Usage: oui mac [options]",
        "",
        "  Options:",
        "",
        "    --help      display this help",
        "    --update    update the database",
        "",
        ""
    ].join("\n"));
    process.exit(1);
} else {
    var result;
    try {
        result = oui(arg);
    } catch (err) {
        process.stdout.write(err.message + "\n");
        process.exit(1);
    }

    if (result) {
        process.stdout.write(result + "\n");
    } else {
        process.stdout.write(arg + " not found in database\n");
    }
    process.exit(0);
}

#!/usr/bin/env node
"use strict";

process.title = "oui";

var arg  = process.argv[2],
    oui  = require("./"),
    spin = require("char-spinner");

if (arg === "--update") {
    var interval = spin();
    oui.update(true, function (err) {
        clearInterval(interval);
        if (err) process.stdout.write(err + "\n");
        process.exit(err ? 1 : 0);
    });
} else if (!arg || arg === "--help") {
    process.stdout.write([
        "",
        "  Usage: oui mac [options]",
        "",
        "  Options:",
        "",
        "    --help      display this help",
        "    --update    update the database",
        "",
        ""
    ].join("\n"));
    process.exit(0);
} else {
    var result;
    try {
        result = oui(arg);
    } catch (err) {
        process.stdout.write(err.message + "\n");
        process.exit(1);
    }

    if (result)
        process.stdout.write(result + "\n");
    else
        process.stdout.write(arg + " not found in database\n");

    process.exit(0);
}

Correct exit code on help


/**
 * Date.prototype.toISOString()
 * version 0.0.0
 * Feature	        Chrome  Firefox Internet Explorer Opera Safari  Edge
 * Basic support    3       1       9                 10.5  5       12
 * -------------------------------------------------------------------------------
 */
if (!Date.prototype.toISOString) {
  Date.prototype.toISOString = function () {
    function pad(number) {
      if (number < 10) {
        return '0' + number;
      }
      return number;
    }

    return this.getUTCFullYear() +
      '-' + pad(this.getUTCMonth() + 1) +
      '-' + pad(this.getUTCDate()) +
      'T' + pad(this.getUTCHours()) +
      ':' + pad(this.getUTCMinutes()) +
      ':' + pad(this.getUTCSeconds()) +
      '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
      'Z';
  };
}

/**
 * Date.prototype.toISOString()
 * version 0.0.0
 * Feature	        Chrome  Firefox Internet Explorer Opera Safari  Edge
 * Basic support    3       1       9                 10.5  5       12
 * -------------------------------------------------------------------------------
 */
if (!Date.prototype.toISOString) {
  Object.defineProperty(Array.prototype, 'toISOString', {
    configurable : true,
    writable : true,
    value :  function () {
    function pad(number) {
      if (number < 10) {
        return '0' + number;
      }
      return number;
    }

    return this.getUTCFullYear() +
      '-' + pad(this.getUTCMonth() + 1) +
      '-' + pad(this.getUTCDate()) +
      'T' + pad(this.getUTCHours()) +
      ':' + pad(this.getUTCMinutes()) +
      ':' + pad(this.getUTCSeconds()) +
      '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
      'Z';
    } });
}

Define all Date toISOString properties with Object.defineProperty, using the descriptors configurable, writable and non-enumerable.


$(".presentation").each(function() {
    var md = new Remarkable('full', { html: true });
    var markup = md.render($(this).html());
    var slides = markup.split('
');
    var new_document = [];
    for (var j = 0; j < slides.length; j++)
        new_document.push('
' + slides[j] + '
');
    document.write(new_document.join(""));
});
$(".presentation").remove();

// If you want to syntax highlight all your code in the same way then
// you can uncomment and customize the next line
//
//$("pre>code").parent().addClass("syntax cpp");

w3c_slidy.add_listener(document.body, "touchend", w3c_slidy.mouse_button_click);

$.syntax();

// Automatic detection for theme javascript. It will run after slides
// have been generated
for(i in document.styleSheets) {
    stylesheet = document.styleSheets[i].href;
    if (stylesheet && stylesheet.indexOf("theme") != -1) {
        theme = stylesheet.slice(stylesheet.lastIndexOf("/")+1, stylesheet.length);
        eval(theme.replace(".css", "()"));
    }
}

$(".presentation").each(function() {
  var md = new Remarkable('full', { html: true//,
                                    // Here goes a real syntax highlighter
                                    //highlight: function (str, lang) {
                                    //  return str;
                                    //}
                                  });
    var markup = md.render($(this).html());
    var slides = markup.split('
');
    var new_document = [];
    for (var j = 0; j < slides.length; j++)
        new_document.push('
' + slides[j] + '
');
    document.write(new_document.join(""));
});
$(".presentation").remove();

// If you want to syntax highlight all your code in the same way then
// you can uncomment and customize the next line
//
//$("pre>code").parent().addClass("syntax cpp");

w3c_slidy.add_listener(document.body, "touchend", w3c_slidy.mouse_button_click);

// XXX: Work Around
// RemarkableJS above translates content of
 Tags into HTML.
// Therefore empty lines will create new paragraphs. Remove those
// paragraphs, so that the newlines stay intact for code highlighting.

// Note: Indentation is lost and cannot be retrieved here

// Note: The better solution is to ditch jquery-syntax and go with
// something that can be used together with RemarkableJS.
$("pre.syntax").map(function(element) {
  $(this).html($(this).
               html().
               replace(/
/g, "\n").
               replace(/<\/p>/g, ""));
});

$.syntax();

// Automatic detection for theme javascript. It will run after slides
// have been generated
for(i in document.styleSheets) {
    stylesheet = document.styleSheets[i].href;
    if (stylesheet && stylesheet.indexOf("theme") != -1) {
        theme = stylesheet.slice(stylesheet.lastIndexOf("/")+1, stylesheet.length);
        eval(theme.replace(".css", "()"));
    }
}

Add workaround to introduce slightly better syntax highlighting.


/**
 * Created by Kanthanarasimhaiah on 14/11/13.
 */
fs = require('fs');

var num_of_tasks;
var total_time;
var fileName = process.argv[2];

fs.readFile(fileName, 'utf8', function (err,data) {
    if (err) {
        return console.log(err);
    }
    //console.log(data);

    var input=data.split('\n');
    var line1 = input[0].split(' ');
    num_of_tasks=parseInt(line1[0], 10);
    total_time=parseInt(line1[1], 10);
    console.log("Numer of Tasks:", num_of_tasks);
    console.log("Total Time:", total_time);

    // read in the tasks
    var queue= [];

    for(var j=1;j<num_of_tasks;j++) {
        var task_data=input[j].split(' ');
        var task = {id         :          task_data[0],
                    start_time : parseInt(task_data[1], 10),
                    duration   : parseInt(task_data[2], 10)};
        queue.push(task);
    }
    function sort_function (a, b) {
        return a.start_time - b.start_time;
    }
    queue.sort(sort_function);
    console.log("Tasks:");
    console.log(queue);
});

/**
 * Created by Kanthanarasimhaiah on 14/11/13.
 */
fs = require('fs');

function readTasks (file) {
    var data = fs.readFileSync(file, 'utf8');

    var input=data.split('\n');
    var line1 = input[0].split(' ');
    var num_of_tasks=parseInt(line1[0], 10);
    var total_time=parseInt(line1[1], 10);

    // read in the tasks
    var queue= [];

    for(var j=1;j<num_of_tasks;j++) {
        var task_data=input[j].split(' ');
        var task = {id         :          task_data[0],
                    start_time : parseInt(task_data[1], 10),
                    duration   : parseInt(task_data[2], 10)};
        queue.push(task);
    }

    function sort_function (a, b) {
        return a.start_time - b.start_time;
    }
    queue.sort(sort_function);
    return {num_of_tasks: num_of_tasks,
            total_time:   total_time,
            task_queue:   queue};
}

var fileName = process.argv[2];
var tasks = readTasks(fileName);

console.log("Numer of Tasks:", tasks.num_of_tasks);
console.log("Total Time:", tasks.total_time);
console.log("Task Queue:");
console.log(tasks.task_queue);

Move task reading into a standalone function.


let UserRecipes = require(`${__dirname}/../schemas.js`).UserRecipes;

module.exports = {
  signup: (req, res) => {

  },

  login: (req, res) => {

  },

  logout: (req, res) => {

  },

  //Gets all the recipes that belong to that user
  getProfile: (req, res) => {
    UserRecipes.findOne({
      username: req.params.username
    }).then(result => {
      res.status(200).send(result);
    }).catch(error => {
      res.status(404).send(error);
    });
  }
};

let UserRecipe = require(`${__dirname}/../schemas.js`).UserRecipe;

module.exports = {
  signup: (req, res) => {

  },

  login: (req, res) => {

  },

  logout: (req, res) => {

  },

  //Gets all the recipes that belong to that user
  getProfile: (req, res) => {
    UserRecipe.findOne({
      username: req.params.username
    }).then(result => {
      res.status(200).send(result);
    }).catch(error => {
      res.status(404).send(error);
    });
  }
};

Remove 's' from UserRecipe(s) in user controller


'use strict';
//Import events
const events = require('events');

//Create EventHandler function
class EventHandler extends events.EventEmitter {
  constructor() {
    super()
  }

  registered() {
    this.emit('registered')
  }

  request(callback) {
    this.emit('request', callback)
  }

  submit(data, callback) {
    this.emit('submit', data, callback)
  }
}

module.exports = EventHandler;

'use strict';
//Import events
const events = require('events');

//Create EventHandler function
class EventHandler extends events.EventEmitter {
  constructor() {
    super();
  }

  registered() {
    this.emit('registered');
  }

  request(callback) {
    this.emit('request', callback);
  }

  submit(data, callback) {
    this.emit('submit', data, callback);
  }
}

module.exports = EventHandler;

Fix conventional errors from previos commit


/*
  Makes API calls to fetch caretaker roles.

  However, until there is an API to call, it returns canned data.
*/

export default class CaretakerRolesGateway {

    static allRoles = null;

    static getAll() {
        if(this.allRoles === null) {
            //api call to get roles
            this.allRoles = [
                {id: 1, name: 'Driver', description: 'Gives rides to things'},
                {id: 2, name: 'Coordinator', description: 'Helps coordinate people sign ups'},
                {id: 3, name: 'Groceries', description: 'Picks up groceries'},
                {id: 4, name: 'Active Friend', description: 'Gets focus out and active (eg, walks) during vulnerable times'},
                {id: 5, name: 'Chef', description: 'Cooks food cause yum'}
            ]
        }
        return this.allRoles;
    }
}

/*
  Makes API calls to fetch caretaker roles.

  However, until there is an API to call, it returns canned data.
*/

const createCaretakerRolesGateway = () => {

    let allRoles = null;

    return {
        getAll: () => {
            if(allRoles === null) {
                //api call to get roles
                allRoles = [
                    {id: 1, name: 'Driver', description: 'Gives rides to things'},
                    {id: 2, name: 'Coordinator', description: 'Helps coordinate people sign ups'},
                    {id: 3, name: 'Groceries', description: 'Picks up groceries'},
                    {id: 4, name: 'Active Friend', description: 'Gets focus out and active (eg, walks) during vulnerable times'},
                    {id: 5, name: 'Chef', description: 'Cooks food cause yum'}
                ]
            }
            return allRoles;
        }
    }
}

export default createCaretakerRolesGateway();

Refactor CaretakerRolesGateway to use factory pattern


/*
 * To Title Case 2.0 – http://individed.com/code/to-title-case/
 * Copyright © 2008–2012 David Gouch. Licensed under the MIT License.
 */

String.prototype.toTitleCase = function() {
  var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i;

  return this.replace(/([^\W_]+[^\s-]*) */g, function(match, p1, index, title) {
    if (index > 0 && index + p1.length !== title.length &&
      p1.search(smallWords) > -1 && title[index - 2] !== ":" &&
      title[index - 1].search(/[^\s-]/) < 0) {
      return match.toLowerCase();
    }

    if (p1.substr(1).search(/[A-Z]|\../) > -1) {
      return match;
    }

    return match.charAt(0).toUpperCase() + match.substr(1);
  });
};

/*
 * To Title Case 2.0 – http://individed.com/code/to-title-case/
 * Copyright © 2008–2012 David Gouch. Licensed under the MIT License.
 */

String.prototype.toTitleCase = function () {
  var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i;

  return this.replace(/([^\W_]+[^\s-]*) */g, function (match, p1, index, title) {
    if (index > 0 && index + p1.length !== title.length &&
      p1.search(smallWords) > -1 && title[index - 2] !== ":" &&
      title[index - 1].search(/[^\s-]/) < 0) {
      return match.toLowerCase();
    }

    if (p1.substr(1).search(/[A-Z]|\../) > -1) {
      return match;
    }

    return match.charAt(0).toUpperCase() + match.substr(1);
  });
};

Add space between anon function and parens.


module.exports = {
    "extends": "airbnb",
    "parser": "babel-eslint",
    "plugins": [
        "react"
    ],
    "rules": {
      "react/prop-types": 0,
      "space-before-function-paren": [2, { "anonymous": "never", "named": "always" }]
    }
};

module.exports = {
    "extends": "airbnb",
    "parser": "babel-eslint",
    "plugins": [
        "react"
    ],
    "rules": {
      "react/prop-types": 0,
      "react/jsx-boolean-value": 0,
      "consistent-return": 0,
      "space-before-function-paren": [2, { "anonymous": "never", "named": "always" }]
    }
};

Add react rules to eslint file


module.exports = [
    { action: '\\sqrt', label: '\\sqrt{X}' },
    { action: '^', label: 'x^{X}' },
    { action: '\\frac', label: '\\frac{X}{X}' },
    { action: '\\int', label: '\\int_{X}^{X}' },
    { action: '\\lim_', label: '\\lim_{X}' },
    { action: '\\overrightarrow', label: '\\overrightarrow{X}' },
    { action: '_', label: 'x_X' },
    { action: '\\nthroot', label: '\\sqrt[X]{X}' },
    { action: '\\sum', label: '\\sum_{X}^{X}' },
    { action: '\\binom', label: '\\binom{X}{X}' },
    { action: '\\sin' },
    { action: '\\cos' },
    { action: '\\tan' },
    { action: '\\arcsin' },
    { action: '\\arccos' },
    { action: '\\arctan' },
    { action: '\\not' },
    { action: '\\vec', label: '\\vec{X}' },
    { action: '\\bar', label: '\\bar{X}' },
    { action: '\\underline', label: '\\underline{X}' },
    { action: '\\overleftarrow', label: '\\overleftarrow{X}' },
    { action: '|', label: '|X|'},
    { action: '(', label: '(X)'}
]

module.exports = [
    { action: '\\sqrt', label: '\\sqrt{X}' },
    { action: '^', label: 'x^{X}' },
    { action: '\\frac', label: '\\frac{X}{X}' },
    { action: '\\int', label: '\\int_{X}^{X}' },
    { action: '\\lim_', label: '\\lim_{X}' },
    { action: '\\overrightarrow', label: '\\overrightarrow{X}' },
    { action: '_', label: 'x_X' },
    { action: '\\nthroot', label: '\\sqrt[X]{X}' },
    { action: '\\sum', label: '\\sum_{X}^{X}' },
    { action: '\\binom', label: '\\binom{X}{X}' },
    { action: '\\sin' },
    { action: '\\cos' },
    { action: '\\tan' },
    { action: '\\arcsin' },
    { action: '\\arccos' },
    { action: '\\arctan' },
    { action: '\\vec', label: '\\vec{X}' },
    { action: '\\bar', label: '\\bar{X}' },
    { action: '\\underline', label: '\\underline{X}' },
    { action: '\\overleftarrow', label: '\\overleftarrow{X}' },
    { action: '|', label: '|X|'},
    { action: '(', label: '(X)'}
]

Remove problematic not tool from the equation toolbar;


const UserController = require('../src/Http/Controllers/User');

const { define, wrap, post, get } = require('spirit-router');
const { json } = require('body-parser');
const express  = require('spirit-express');

module.exports = define('/api', [
  get('/users', UserController.index),
  get('/users/:user_id', ['user_id'], UserController.show),
  wrap(post('/users', ['body'], UserController.store), express(json())),
]);

const UserController = require('../src/Http/Controllers/User');

const { define, wrap, post, get, any, notFound } = require('spirit-router');
const { json } = require('body-parser');
const express  = require('spirit-express');

const api = define('/api', [
  get('/users', UserController.index),
  get('/users/:user_id', ['user_id'], UserController.show),
  wrap(post('/users', ['body'], UserController.store), express(json())),
]);

module.exports = define([api, any('*', notFound())]);

Add default not found route


import Ember from 'ember';

export default Ember.Component.extend({
    classNames: ['draggable-dropzone'],
    classNameBindings: ['dragClass'],
    dragClass: 'deactivated',

    dragLeave: function(event) {
        event.preventDefault();
        this.set('dragClass', 'deactivated');
    },

    dragOver: function(event) {
        event.preventDefault();
        this.set('dragClass', 'activated');
    },

    drop: function(event) {
        event.preventDefault();
        this.set('dragClass', 'deactivated');
        data = event.dataTransfer.getData('text/data');
        // default drop action - change with {{draggable-dropzone dropped=xyz}}
        this.sendAction('dropped', data);
    }
});

import Ember from 'ember';

export default Ember.Component.extend({
    classNames: ['draggable-dropzone'],
    classNameBindings: ['dragClass'],
    dragClass: 'deactivated',

    dragLeave: function(event) {
        event.preventDefault();
        this.set('dragClass', 'deactivated');
    },

    dragOver: function(event) {
        event.preventDefault();
        this.set('dragClass', 'activated');
    },

    drop: function(event) {
        event.preventDefault();
        this.set('dragClass', 'deactivated');
        var data = event.dataTransfer.getData('text/data');
        // default drop action - change with {{draggable-dropzone dropped=xyz}}
        this.sendAction('dropped', data);
    }
});

Fix small issue with ember dropzone


module.exports = {
    extends: ["matrix-org"],
    plugins: [
        "babel",
    ],
    env: {
        browser: true,
        node: true,
    },

    rules: {
        "no-var": ["warn"],
        "prefer-rest-params": ["warn"],
        "prefer-spread": ["warn"],
        "one-var": ["warn"],
        "padded-blocks": ["warn"],
        "no-extend-native": ["warn"],
        "camelcase": ["warn"],
        "no-multi-spaces": ["error", { "ignoreEOLComments": true }],
        "space-before-function-paren": ["error", {
            "anonymous": "never",
            "named": "never",
            "asyncArrow": "always",
        }],
        "arrow-parens": "off",
        "prefer-promise-reject-errors": "off",
        "quotes": "off",
        "indent": "off",
        "no-constant-condition": "off",
        "no-async-promise-executor": "off",
        // We use a `logger` intermediary module
        "no-console": "error",
    },
    overrides: [{
        "files": ["src/**/*.ts"],
        "extends": ["matrix-org/ts"],
        "rules": {
            // While we're converting to ts we make heavy use of this
            "@typescript-eslint/no-explicit-any": "off",
            "quotes": "off",
        },
    }],
};

module.exports = {
    extends: ["matrix-org"],
    plugins: [
        "babel",
    ],
    env: {
        browser: true,
        node: true,
    },

    rules: {
        "no-var": ["warn"],
        "prefer-rest-params": ["warn"],
        "prefer-spread": ["warn"],
        "one-var": ["warn"],
        "padded-blocks": ["warn"],
        "no-extend-native": ["warn"],
        "camelcase": ["warn"],
        "no-multi-spaces": ["error", { "ignoreEOLComments": true }],
        "space-before-function-paren": ["error", {
            "anonymous": "never",
            "named": "never",
            "asyncArrow": "always",
        }],
        "arrow-parens": "off",
        "prefer-promise-reject-errors": "off",
        "quotes": "off",
        "indent": "off",
        "no-constant-condition": "off",
        "no-async-promise-executor": "off",
        // We use a `logger` intermediary module
        "no-console": "error",
    },
    overrides: [{
        "files": ["src/**/*.ts"],
        "extends": ["matrix-org/ts"],
        "rules": {
            // We're okay being explicit at the moment
            "@typescript-eslint/no-empty-interface": "off",
            // While we're converting to ts we make heavy use of this
            "@typescript-eslint/no-explicit-any": "off",
            "quotes": "off",
        },
    }],
};

Resolve linting errors after upgrades


module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module'
  },
  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
  extends: 'standard',
  plugins: [
    'html'  // required to lint *.vue files
  ],
  // add your custom rules here
  'rules': {
    // allow paren-less arrow functions
    'arrow-parens': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
  }
}

module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module'
  },
  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
  extends: 'standard',
  plugins: [
    'html'  // required to lint *.vue files
  ],
  // add your custom rules here
  'rules': {
    // allow no-spaces between function name and argument parethesis list
    'space-before-function-paren': 0,
    // allow paren-less arrow functions
    'arrow-parens': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
  }
}

Update eslint rules to allow no-spaces between function name and argument parenthesis


angular.module('gitphaser')
  .controller('NearbyCtrl', NearbyCtrl);

// @controller NearbyCtrl
// @params: $scope, $reactive
// @route: /tab/nearby
//
// Exposes Meteor mongo 'connections' to DOM, filtered against current user as 'transmitter'
// Subscription to 'connections' is handled in the route resolve. Also
// exposes GeoLocate service (for the maps view) and Notify service (to trigger notification when user
// clicks on list item to see profile)
function NearbyCtrl ($scope, $reactive, Notify, GeoLocate ){
  $reactive(this).attach($scope);

  var self = this;

  // Slide constants bound to the GeoLocate directive
  // and other DOM events, trigger updates based on
  // whether we are looking at List || Map view.
  self.listSlide = 0
  self.mapSlide = 1;
  self.slide = 0;

  // Services
  self.geolocate = GeoLocate;
  self.notify = Notify;

  self.helpers({
      connections: function () {
        if (Meteor.userId()){
          return Connections.find( {transmitter: Meteor.userId() } );
        }
      }
  });

};

angular.module('gitphaser').controller('NearbyCtrl', NearbyCtrl);

/**
 * Exposes Meteor mongo 'connections' to DOM, filtered against current user as 'transmitter'
 * Subscription to 'connections' is handled in the route resolve. Also
 * exposes GeoLocate service (for the maps view) and Notify service (to trigger notification when user
 * clicks on list item to see profile)
 * @controller NearbyCtrl
 * @route: /tab/nearby
 */
function NearbyCtrl ($scope, $reactive, Notify, GeoLocate ){
  $reactive(this).attach($scope);

  var self = this;

  // Slide constants bound to the GeoLocate directive
  // and other DOM events, trigger updates based on
  // whether we are looking at List || Map view.
  self.listSlide = 0
  self.mapSlide = 1;
  self.slide = 0;

  // Services
  self.geolocate = GeoLocate;
  self.notify = Notify;

  self.helpers({
      connections: function () {
        if (Meteor.userId()){
          return Connections.find( {transmitter: Meteor.userId() } );
        }
      }
  });

};

Test push after changing local remote


(function () {
    angular
        .module('GVA.Creation')
        .controller('CreateBasicPageController', ['$scope', 'AccountService', 'PollService',
        function ($scope, AccountService, PollService) {

            $scope.openLoginDialog = function () {
                AccountService.openLoginDialog($scope);
            };

            $scope.openRegisterDialog = function () {
                AccountService.openRegisterDialog($scope);
            };

            $scope.createPoll = function (question) {
                PollService.createPoll(question, function (data) {
                    window.location.href = "/Manage/" + data.ManageId;
                });
            };

        }]);
})();

(function () {
    angular
        .module('GVA.Creation')
        .controller('CreateBasicPageController', ['$scope', 'AccountService', 'PollService',
        function ($scope, AccountService, PollService) {

            $scope.openLoginDialog = function () {
                AccountService.openLoginDialog($scope);
            };

            $scope.openRegisterDialog = function () {
                AccountService.openRegisterDialog($scope);
            };

            $scope.createPoll = function (question) {
                PollService.createPoll(question, function (data) {
                    window.location.href = "/#/Manage/" + data.ManageId;
                });
            };

        }]);
})();

Fix redirect after poll creation


const $answer = $('.answer')
const {makeRichText} = require('./math-editor')

const save = ($elem, async = true) => $.post({
    url: '/save',
    data: {text: $elem.html(), answerId: $elem.attr('id')},
    async
})

function saveScreenshot(questionId) {
    return ({data, type, id}) => {
        return $.post({
            type: 'POST',
            url: `/saveImg?answerId=${questionId}&id=${id}`,
            data: data,
            processData: false,
            contentType: type
        }).then(res => {
            console.log('heh', res)
            return res.url
        })
}
}
const richTextOptions = id => ({
    screenshot: {
        saver: data => saveScreenshot(id)(data)
    }
})

$answer.each((i, answer) => {
    makeRichText(answer, richTextOptions(answer.id))
    $.get(`/load?answerId=${answer.id}`, data => data && $(answer).html(data.html))
}).on('keypress', e => {
    if (e.ctrlKey && !e.altKey && !e.shiftKey && e.key === 's') {
        e.preventDefault()
        save($(e.target))
    }
})
$('#answer1').focus()

Set focus automatically to first field


// toggle display of all code cells' inputs

define([
    'jquery',
    'base/js/namespace',
    'base/js/events'
], function(
    $,
    Jupyter,
    events
) {
    "use strict";

    function initialize () {
        console.log("Embedded HTML Exporter loaded!");
    }

    var load_ipython_extension = function() {

        var dwm = $("#download_menu")
        var downloadEntry = $('
HTML Embedded (.html)
')
        dwm.append(downloadEntry)
        downloadEntry.click(function () {
            Jupyter.menubar._nbconvert('html_embed', true);
        });

        Jupyter.toolbar.add_buttons_group([{
            id : 'export_embeddedhtml',
            label : 'Embedded HTML Export',
            icon : 'fa-save',
            callback : function() {
                Jupyter.menubar._nbconvert('html_embed', true);
            }
        }]);
        if (Jupyter.notebook !== undefined && Jupyter.notebook._fully_loaded) {
            // notebook_loaded.Notebook event has already happened
            initialize();
        }
        events.on('notebook_loaded.Notebook', initialize);
    };

    return {
        load_ipython_extension : load_ipython_extension
    };
});

// toggle display of all code cells' inputs

define([
    'jquery',
    'base/js/namespace',
    'base/js/events'
], function(
    $,
    Jupyter,
    events
) {
    "use strict";

    function initialize () {
    }

    var load_ipython_extension = function() {

        /* Add an entry in the download menu */
        var dwm = $("#download_menu")
        var downloadEntry = $('
HTML Embedded (.html)
')
        dwm.append(downloadEntry)
        downloadEntry.click(function () {
            Jupyter.menubar._nbconvert('html_embed', true);
        });

        /* Add also a Button, currently disabled */
        /*
        Jupyter.toolbar.add_buttons_group([{
            id : 'export_embeddedhtml',
            label : 'Embedded HTML Export',
            icon : 'fa-save',
            callback : function() {
                Jupyter.menubar._nbconvert('html_embed', true);
            }
        }]);
        */
        if (Jupyter.notebook !== undefined && Jupyter.notebook._fully_loaded) {
            // notebook_loaded.Notebook event has already happened
            initialize();
        }
        events.on('notebook_loaded.Notebook', initialize);
    };

    return {
        load_ipython_extension : load_ipython_extension
    };
});

Remove Button, only in Download Menu


const { getContact } = require('../../contacts/repos')

function setInteractionsDetails (req, res, next) {
  res.locals.interactions = {
    returnLink: `/contacts/${req.params.contactId}/interactions/`,
    entityName: `${res.locals.contact.first_name} ${res.locals.contact.last_name}`,
    query: { contacts_id: req.params.contactId },
    view: 'contacts/views/interactions',
    canAdd: true,
  }

  next()
}

async function setCompanyDetails (req, res, next) {
  try {
    const contact = await getContact(req.session.token, req.params.contactId)
    res.locals.company = contact.company
    next()
  } catch (error) {
    next(error)
  }
}

module.exports = {
  setInteractionsDetails,
  setCompanyDetails,
}

const { getContact } = require('../../contacts/repos')

function setInteractionsDetails (req, res, next) {
  res.locals.interactions = {
    returnLink: `/contacts/${req.params.contactId}/interactions/`,
    entityName: `${res.locals.contact.first_name} ${res.locals.contact.last_name}`,
    query: { contacts__id: req.params.contactId },
    view: 'contacts/views/interactions',
    canAdd: true,
  }

  next()
}

async function setCompanyDetails (req, res, next) {
  try {
    const contact = await getContact(req.session.token, req.params.contactId)
    res.locals.company = contact.company
    next()
  } catch (error) {
    next(error)
  }
}

module.exports = {
  setInteractionsDetails,
  setCompanyDetails,
}

Add missing underscore on query param to contacts


// Copyright 2012 Google Inc.
//
// 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.

AuditRules.addRule({
    name: 'unfocusableElementsWithOnClick',
    severity: Severity.Warning,
    opt_shouldRunInDevtools: true,
    relevantNodesSelector: function() {
        var potentialOnclickElements = document.querySelectorAll('span, div, img');

        var unfocusableClickableElements = [];
        for (var i = 0; i < potentialOnclickElements.length; i++) {
            var element = potentialOnclickElements[i];

            if (AccessibilityUtils.isElementOrAncestorHidden)
                continue;

            var eventListeners = getEventListeners(element);
            if ('click' in eventListeners) {
                unfocusableClickableElements.push(element);
            }
        }
        return unfocusableClickableElements;
    },
    test: function(element) {
        return element.tabIndex == null;
    }
});

// Copyright 2012 Google Inc.
//
// 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.

AuditRules.addRule({
    name: 'unfocusableElementsWithOnClick',
    severity: Severity.Warning,
    opt_shouldRunInDevtools: true,
    relevantNodesSelector: function() {
        var potentialOnclickElements = document.querySelectorAll('*');

        var unfocusableClickableElements = [];
        for (var i = 0; i < potentialOnclickElements.length; i++) {
            var element = potentialOnclickElements[i];

            if (AccessibilityUtils.isElementOrAncestorHidden)
                continue;

            var eventListeners = getEventListeners(element);
            if ('click' in eventListeners) {
                unfocusableClickableElements.push(element);
            }
        }
        return unfocusableClickableElements;
    },
    test: function(element) {
        return element.tabIndex == null;
    }
});

Check all elements, not just [span, div, img], for unfocusableElementsWithOnClick


module.exports = {
    options: {
      map: true, // inline sourcemaps

      processors: [
        require('pixrem')(), // add fallbacks for rem units
        require('autoprefixer-core')({
          // add vendor prefixes
          browsers: [
            'last 3 version',
            'ie 8',
            'ff 3.6',
            'opera 11.1',
            'ios 4',
            'android 2.3'
          ]
        }),
        require('cssnano')() // minify the result
      ]
    },
    dist: {
      src: '<%= destCSSDir %>' + '/*.css'
    }
};

module.exports = {
    options: {
      map: true, // inline sourcemaps

      processors: [
        require('pixrem')(), // add fallbacks for rem units
        require('autoprefixer-core')({
          // add vendor prefixes
          browsers: [
            'last 3 version',
            'ie 8',
            'ff 3.6',
            'opera 11.1',
            'ios 4',
            'android 2.3'
          ]
        }),
        require('cssnano')({
          convertValues: false
        }) // minify the result
      ]
    },
    dist: {
      src: '<%= destCSSDir %>' + '/*.css'
    }
};

Disable not-safe PostCSS value conversions


#!/usr/bin/env node

var ncp = require('ncp').ncp;
var path = require('path');

require('yargs')
    .usage('$0 <cmd> [args]')
    .option('directory', {
        alias: 'd',
        describe: 'Provide the directory to install Violet to'
    })
    .command('install', 'Install violet', {}, function (argv) {
        var directory = 'violet';
        if (argv.directory != null) {
            directory = argv.directory;
        }

        ncp(path.resolve(__dirname, './source'), directory, function (err) {
            if (err) {
                return console.error(err);
            }
            console.log('Installed Violet!');
        });
    })
    .help('help')
    .argv;

#!/usr/bin/env node

var ncp = require('ncp').ncp;
var path = require('path');
var fs = require('fs');

require('yargs')
    .usage('$0 <cmd> [args]')
    .option('directory', {
        alias: 'd',
        describe: 'Provide the directory to install Violet to'
    })
    .command('install', 'Install Violet', {}, function (argv) {
        var directory = 'violet';
        if (argv.directory != null) {
            directory = argv.directory;
        }

        install(directory);
    })
    .command('update', 'Update Violet', {}, function (argv) {
        var directory = 'violet';
        if (argv.directory != null) {
            directory = argv.directory;
        }

        deleteFolderRecursive(directory);
        install(directory);
    })
    .help('help')
    .argv;

function install(directory) {
    ncp(path.resolve(__dirname, './source'), directory, function (err) {
        if (err) {
            return console.error(err);
        }
        console.log('Installed Violet!');
    });
}

// thanks to http://www.geedew.com/remove-a-directory-that-is-not-empty-in-nodejs/
function deleteFolderRecursive(path) {
    if (fs.existsSync(path)) {
        fs.readdirSync(path).forEach(function (file, index) {
            var curPath = path + "/" + file;
            if (fs.lstatSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
};

Add update fucntion to CLI


#!/usr/bin/env node

var _ = require('lodash');
var docdown = require('docdown');
var fs = require('fs');
var path = require('path');
var srcPath = path.join(__dirname, '../src');
var outPath = path.join(__dirname, '../docs');

// Define which files to scan
var sourceFiles = [
    'tree.js',
    'treenode.js',
    'treenodes.js'
];

// Create output directory
if (!fs.existsSync(outPath)) {
    fs.mkdirSync(outPath);
}

_.each(sourceFiles, function(sourceFile) {
    var markdown = docdown({
        title: '',
        toc: 'categories',
        path: path.join(srcPath, sourceFile),
        url: 'https://github.com/helion3/inspire-tree/blob/master/src/' + sourceFile
    });

    var docName = sourceFile.split('/').pop().replace('.js', '.md');

    // Write file
    fs.writeFile(path.join(outPath, docName), markdown, function(err) {
        if (err) {
            console.log('Error writing to file:');
            console.log(err);
            return;
        }

        console.log('Wrote output for ' + sourceFile);
    });
});

#!/usr/bin/env node

var _ = require('lodash');
var docdown = require('docdown');
var fs = require('fs');
var path = require('path');
var srcPath = path.join(__dirname, '../src');
var outPath = path.join(__dirname, '../docs');

// Define which files to scan
var sourceFiles = [
    'tree.js',
    'treenode.js',
    'treenodes.js'
];

// Create output directory
if (!fs.existsSync(outPath)) {
    fs.mkdirSync(outPath);
}

_.each(sourceFiles, function(sourceFile) {
    var markdown = docdown({
        title: '',
        toc: 'categories',
        path: path.join(srcPath, sourceFile),
        style: 'github',
        url: 'https://github.com/helion3/inspire-tree/blob/master/src/' + sourceFile
    });

    var docName = sourceFile.split('/').pop().replace('.js', '.md');

    // Write file
    fs.writeFile(path.join(outPath, docName), markdown, function(err) {
        if (err) {
            console.log('Error writing to file:');
            console.log(err);
            return;
        }

        console.log('Wrote output for ' + sourceFile);
    });
});

Set docdown style to github.


(function(global) {
  'use strict';
  define([
  ], function() {
// $HEADER$

    /**
     * This will be the warmsea namespace.
     * @namespace
     * @alias warmsea
     */
    var w = _.extend({}, _);

    /**
     * The unmodified underlying underscore object.
     */
    w._ = w.underscore = _;

    /**
     * The version of this WarmseaJS.
     * @type {string}
     */
    w.VERSION = '$VERSION$';

    /**
     * The global object of the executing environment.
     * @type {object}
     */
    w.global = global;

    /**
     * Save the previous `warmsea`.
     */
    var previousWarmsea = global.warmsea;

    /**
     * Return the current `warmsea` and restore the previous global one.
     * @return {warmsea} This warmsea object.
     */
    w.noConflict = function() {
      global.warmsea = previousWarmsea;
      return this;
    };

    /**
     * A function that throws an error with the message "Unimplemented".
     */
    w.unimplemented = function() {
      w.error('Unimplemented');
    };

    /**
     * Throws an Error.
     * @method
     * @param {string} msg
     * @throws {Error}
     */
    w.error = function(msg) {
      throw new Error(msg);
    };

// $FOOTER$
    return w;
  });
})(this);

(function(global) {
  'use strict';
  define([
  ], function() {
// $HEADER$

    /**
     * This will be the warmsea namespace.
     * @namespace
     * @alias warmsea
     */
    var w = _.extend({}, _);

    /**
     * The unmodified underlying underscore object.
     */
    w._ = w.underscore = _;

    /**
     * The version of this WarmseaJS.
     * @type {string}
     */
    w.VERSION = '$VERSION$';

    /**
     * The global object of the executing environment.
     * @type {object}
     */
    w.global = global;

    /**
     * Save the previous `warmsea`.
     */
    var previousWarmsea = global.warmsea;

    /**
     * Return the current `warmsea` and restore the previous global one.
     * @return {warmsea} This warmsea object.
     */
    w.noConflict = function() {
      global.warmsea = previousWarmsea;
      return this;
    };

    /**
     * A function that throws an error with the message "Unimplemented".
     */
    w.unimplemented = function() {
      w.error('Unimplemented');
    };

    /**
     * Throws an Error.
     * @method
     * @param {string} msg
     * @throws {Error}
     */
    w.error = function(msg) {
      if (w.isFunction(w.format)) {
        msg = w.format.apply(w, arguments);
      }
      throw new Error(msg);
    };

// $FOOTER$
    return w;
  });
})(this);

Format support for w.error() if possible.


/*
 * Module dependencies
 */

var app = module.parent.exports,
	Joiner = require('../libs/joiner').Joiner;

/*
 * Middlewares
 */

function isAnotherFile (req, res, next) {
	var folder = req.params.version;
	if (folder === 'assets' || folder === 'vendor' || folder === 'test' || folder === 'libs') {
		next('route');
	} else {
		next();
	}
};

function isView (req, res, next) {
	if (req.params.type === undefined) {
		res.render(req.params.version + '.html');
	} else {
		next();
	}
};

/*
 * Views
 */
app.get('/:version/:type?/:min?', isAnotherFile, isView, function (req, res, next) {
	var name = req.params.version + req.params.type.toUpperCase(),
		min = ((req.params.min) ? true : false),
		joiner = new Joiner();

	joiner.on('joined', function (data) {
		res.set('Content-Type', 'text/' + (req.params.type === 'js' ? 'javascript' : 'css'));
		res.send(data.raw);
	});

	joiner.run(name, min);
});

/*
 * Index
 */
app.get('/', function (req, res, next) {
	res.redirect('/ui')
});

/*
 * Module dependencies
 */

var app = module.parent.exports,
	Joiner = require('../libs/joiner').Joiner;

/*
 * Middlewares
 */

function isAnotherFile (req, res, next) {
	var folder = req.params.version;
	if (folder === 'assets' || folder === 'vendor' || folder === 'test' || folder === 'libs') {
		next('route');
	} else {
		next();
	}
};

function isView (req, res, next) {
	if (req.params.type === undefined) {
		res.render(req.params.version + '.html');
	} else {
		next();
	}
};

/*
 * Views
 */
app.get('/:version/:type?', isAnotherFile, isView, function (req, res, next) {
	var name = req.params.version + req.params.type.toUpperCase(),
		min = ((req.query.min) ? req.query.min : false),
		joiner = new Joiner();

	joiner.on('joined', function (data) {
		res.set('Content-Type', 'text/' + (req.params.type === 'js' ? 'javascript' : 'css'));
		res.send(data.raw);
	});

	joiner.run(name, min);
});

/*
 * Index
 */
app.get('/', function (req, res, next) {
	res.redirect('/ui')
});

Change the min feature to a parameter as ?min=true to get data form joiner.


'use babel';

import yarnExec from '../yarn/exec';
import reportError from '../report-error';

const cleanCache = async () => {
  const success = await yarnExec(null, 'cache', ['clean']);

  if (!success) {
    atom.notifications.addError(
      'An error occurred whilst cleaning cache. See output for more information.',
    );

    return;
  }

  atom.notifications.addSuccess('Global package cache has been cleaned');
};

const confirmation = async () => {
  atom.confirm({
    message: 'Are you sure you want to clean the global Yarn cache?',
    detailedMessage:
      'Cleaning your global package cache will force Yarn to download packages from the npm registry the next time a package is requested.',
    buttons: {
      'Clean Cache': () => {
        cleanCache().catch(reportError);
      },
      Cancel: null,
    },
  });
};

export default confirmation;

'use babel';

import yarnExec from '../yarn/exec';
import reportError from '../report-error';
import addProgressNotification from '../add-progress-notification';

const cleanCache = async () => {
  let progress;

  const options = {
    onStart: () => {
      progress = addProgressNotification('Cleaning global package cache...');
    },
  };

  const success = await yarnExec(null, 'cache', ['clean'], options);

  progress.dismiss();

  if (!success) {
    atom.notifications.addError(
      'An error occurred whilst cleaning global cache. See output for more information.',
    );

    return;
  }

  atom.notifications.addSuccess('Global package cache has been cleaned');
};

const confirmation = async () => {
  atom.confirm({
    message: 'Are you sure you want to clean the global Yarn cache?',
    detailedMessage:
      'Cleaning your global package cache will force Yarn to download packages from the npm registry the next time a package is requested.',
    buttons: {
      'Clean Cache': () => {
        cleanCache().catch(reportError);
      },
      Cancel: null,
    },
  });
};

export default confirmation;

Add progress notification to clean cache command


(function() {

    var defur = require('../../../src/defur');
    var assert = require('chai').assert;

    suite('defur:', function() {
        var services = null;

        setup(function() {
            services = {};
        });

        test('`defur` is a function', function() {
            assert.isFunction(defur);
        });

        test('`defur` defers execution of definition', function() {
            defur('foo', services, function() {
                throw new Error('This should be deferred.');
            });

            assert.throws(function() {
                services.foo;
            });
        });

        test('`defur` creates the service only once', function() {
            defur('foo', services, function() {
                return {};
            });

            assert.strictEqual(services.foo, services.foo);
        });

        test('`defur` works with multiple service containers', function() {
            var otherServices = {};

            defur('foo', services, function() {
                return {};
            });
            defur('foo', otherServices, function() {
                return {};
            });

            assert.notEqual(services.foo, otherServices.foo);
        });

    });

})();

(function() {

    var defur = require('../../../src/defur');
    var assert = require('chai').assert;

    suite('defur:', function() {
        var services = null;

        setup(function() {
            services = {};
        });

        test('`defur` is a function', function() {
            assert.isFunction(defur);
        });

        test('`defur` defers execution of definition', function() {
            defur('foo', services, function() {
                throw new Error('This should be deferred.');
            });

            assert.throws(function() {
                services.foo;
            });
        });

        test('`defur` creates the service only once', function() {
            defur('foo', services, function() {
                return {};
            });

            assert.strictEqual(services.foo, services.foo);
        });

        test('`defur` services don\'t collide', function() {
            defur('foo', services, function() {
                return {};
            });
            defur('bar', services, function() {
                return {};
            });

            assert.notEqual(services.foo, services.bar);
        });

        test('`defur` works with multiple service containers', function() {
            var otherServices = {};

            defur('foo', services, function() {
                return {};
            });
            defur('foo', otherServices, function() {
                return {};
            });

            assert.notEqual(services.foo, otherServices.foo);
        });

    });

})();

Add test to cover container collisions


/**
 * Monkeypatches the EmberApp instance from Ember CLI to contain the hooks we
 * need to filter environment-specific initializers. Hopefully we can upstream
 * similar hooks to Ember CLI and eventually remove these patches.
 */
function patchEmberApp(emberApp) {
  // App was already patched
  if (emberApp.addonPreconcatTree) { return; }

  // Save off original implementation of the `concatFiles` hook
  var originalConcatFiles = emberApp.concatFiles;

  // Install method to invoke `preconcatTree` hook on each addon
  emberApp.addonPreconcatTree = addonPreconcatTree;

  // Install patched `concatFiles` method. This checks options passed to it
  // and, if it detects that it's a concat for the app tree, invokes our
  // preconcat hook. Afterwards, we invoke the original implementation to
  // return a tree concating the files.
  emberApp.concatFiles = function(tree, options) {
    if (options.annotation === 'Concat: App') {
      tree = this.addonPreconcatTree(tree);
    }
    return originalConcatFiles.call(this, tree, options);
  };
}

function addonPreconcatTree(tree) {
  var workingTree = tree;

  this.project.addons.forEach(function(addon) {
    if (addon.preconcatTree) {
      workingTree = addon.preconcatTree(workingTree);
    }
  });

  return workingTree;
}

module.exports = patchEmberApp;

/**
 * Monkeypatches the EmberApp instance from Ember CLI to contain the hooks we
 * need to filter environment-specific initializers. Hopefully we can upstream
 * similar hooks to Ember CLI and eventually remove these patches.
 */
function patchEmberApp(emberApp) {
  // App was already patched
  if (emberApp.addonPreconcatTree) { return; }

  // Save off original implementation of the `concatFiles` hook
  var originalConcatFiles = emberApp.concatFiles;

  // Install method to invoke `preconcatTree` hook on each addon
  emberApp.addonPreconcatTree = addonPreconcatTree;

  // Install patched `concatFiles` method. This checks options passed to it
  // and, if it detects that it's a concat for the app tree, invokes our
  // preconcat hook. Afterwards, we invoke the original implementation to
  // return a tree concating the files.
  emberApp.concatFiles = function(tree, options) {
    if (options.annotation === 'Concat: App') {
      tree = this.addonPreconcatTree(tree);
    }
    return originalConcatFiles.apply(this, arguments);
  };
}

function addonPreconcatTree(tree) {
  var workingTree = tree;

  this.project.addons.forEach(function(addon) {
    if (addon.preconcatTree) {
      workingTree = addon.preconcatTree(workingTree);
    }
  });

  return workingTree;
}

module.exports = patchEmberApp;

Fix deprecation warning in for using EmberApp.concatFiles


import React from 'react'

export default function TravelObject(props) {
    let content = null;
    switch(props.type) {
        case 'event':
            content =
Event!
;
            break;
        case 'flight':
            content =
Flight!

            break;
        case 'hotel':
            content =
Hotel!

            break;
        default:
            console.log("Invalid type");
            break;
    }
    return (

            {content}
            <button onClick={() => console.log("editing")}>Edit</button>
            <button onClick={() => console.log("deleting")}>Delete</button>

    )

}

import React from 'react'
import Flight from './Flight'

export default function TravelObject(props) {
    let content = null;
    switch(props.type) {
        case 'event':
            content =
Event!
;
            break;
        case 'flight':
            content = <Flight />
            break;
        case 'hotel':
            content =
Hotel!

            break;
        default:
            console.log("Invalid type");
            break;
    }
    return (

            {content}
            <button onClick={() => console.log("editing")}>Edit</button>
            <button onClick={() => console.log("deleting")}>Delete</button>

    )

}

Replace dummy code for flight case with flight component


var historyApiFallback = require("connect-history-api-fallback");

var dest = "./build";
var src = './src';

module.exports = {
    browserSync: {
        server: {
            // Serve up our build folder
            baseDir: dest,
            middleware: [historyApiFallback()]
        }
    },
    js: {
        src: src + '/js/app.js'
    },
    templates: {
        src: src + '/templates/**/*.html'
    },
    css: {
        src: src + "/js/vendor/highlight.js/styles/docco.css",
        dest: dest
    },
    sass: {
        src: src + "/sass/**/*.scss",
        dest: dest,
        settings: {
            outputStyle: "compressed",
            indentedSyntax: false, // Disable .sass syntax!
            imagePath: 'img' // Used by the image-url helper
        }
    },
    images: {
        src: src + "/img/**",
        dest: dest + "/img"
    },
    markup: {
        src: src + "/{index.html,favicon.ico,/platform/**,/resources/**}",
        dest: dest
    },
    browserify: {
        bundleConfigs: [{
            entries: src + '/js/app.js',
            dest: dest,
            outputName: 'worker_ui.js',
            extensions: [],
            transform: ["ractivate"]
        }]
    },
    production: {
        cssSrc: dest + '/*.css',
        jsSrc: dest + '/*.js',
        dest: dest
    }
};

var historyApiFallback = require("connect-history-api-fallback");

var dest = "./build";
var src = './src';

module.exports = {
    browserSync: {
        server: {
            // Serve up our build folder
            baseDir: dest,
            middleware: [historyApiFallback()]
        }
    },
    js: {
        src: src + '/js/app.js'
    },
    templates: {
        src: src + '/templates/**/*.html'
    },
    css: {
        src: src + "/js/vendor/highlight.js/styles/docco.css",
        dest: dest
    },
    sass: {
        src: src + "/sass/**/*.scss",
        dest: dest,
        settings: {
            outputStyle: "compressed",
            indentedSyntax: false, // Disable .sass syntax!
            imagePath: 'img' // Used by the image-url helper
        }
    },
    images: {
        src: src + "/img/**",
        dest: dest + "/img"
    },
    markup: {
        src: src + "/{index.html,debug.html,favicon.ico,/platform/**,/resources/**}",
        dest: dest
    },
    browserify: {
        bundleConfigs: [{
            entries: src + '/js/app.js',
            dest: dest,
            outputName: 'worker_ui.js',
            extensions: [],
            transform: ["ractivate"]
        }]
    },
    production: {
        cssSrc: dest + '/*.css',
        jsSrc: dest + '/*.js',
        dest: dest
    }
};

Add debug.html to build script