import ddRender from 'skatejs-dom-diff/src/render';
import nsRender from 'skatejs-named-slots/src/render';
import nsSlot from 'skatejs-named-slots/src/slot';
import skate from 'skatejs';
import skRender from 'skatejs/src/api/render';

function linkPropsToAttrsIfNotSpecified (opts) {
  const props = opts.properties;
  Object.keys(props || {}).forEach(function (name) {
    const prop = props[name];
    if (typeof prop.attribute === 'undefined') {
      prop.attribute = true;
    }
  });
}

function createSlotProperties (opts) {
  if (!opts.slots) {
    opts.slots = [];
  }

  if (!opts.properties) {
    opts.properties = {};
  }

  const props = opts.properties;

  opts.slots.forEach(function (name, index) {
    props[name] = nsSlot({
      default: index === 0,
      set: skRender
    });
  });
}

function wrapRender (opts) {
  opts.render = nsRender(ddRender(opts.render));
}

export default function (name, opts) {
  linkPropsToAttrsIfNotSpecified(opts);
  createSlotProperties(opts);
  wrapRender(opts);
  return skate(name, opts);
}

import ddRender from 'skatejs-dom-diff/lib/render';
import nsRender from 'skatejs-named-slots/lib/render';
import nsSlot from 'skatejs-named-slots/lib/slot';
import skate from 'skatejs';
import skRender from 'skatejs/lib/api/render';

function linkPropsToAttrsIfNotSpecified (opts) {
  const props = opts.properties;
  Object.keys(props || {}).forEach(function (name) {
    const prop = props[name];
    if (typeof prop.attribute === 'undefined') {
      prop.attribute = true;
    }
  });
}

function createSlotProperties (opts) {
  if (!opts.slots) {
    opts.slots = [];
  }

  if (!opts.properties) {
    opts.properties = {};
  }

  const props = opts.properties;

  opts.slots.forEach(function (name, index) {
    props[name] = nsSlot({
      default: index === 0,
      set: skRender
    });
  });
}

function wrapRender (opts) {
  opts.render = nsRender(ddRender(opts.render));
}

export default function (name, opts) {
  linkPropsToAttrsIfNotSpecified(opts);
  createSlotProperties(opts);
  wrapRender(opts);
  return skate(name, opts);
}

Use lib instead of src so non-babel builds can process the lib of kickfliip.


#!/usr/bin/env node

// Requires
var _ = require('underscore');

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

// Comannder
var prog = require('commander');

// etcd-dump's package.json file
var pkg = require('../package.json');

// Dumper class
var parser = require('../');

// General options
prog
.version(pkg.version);

// Commands
prog
.command('compile [filename]')
.description('Compile an *.itermcolors file to a JSON scheme')
.action(function(filename, opts) {
    // Output JSON color array
    console.log(JSON.stringify(
        parser(fs.readFileSync(filename)),
        null,
        4 // 4 spaces
    ));
});

prog
.command('bundle [dir]')
.description('Bundle a given directory of schemes to one json file')
.action(function(dir, opts) {

    // Merge scheme's together and add name attribute based on filename
    var bundle = fs.readdirSync(dir).map(function(filename) {
        var name = filename.split('.')[0];
        var data = require(path(dir, filename));
        data.name = name;

        return data;
    }).reduce(function(bundle, data) {
        bundle[name] = data;
        return bundle;
    }, {});

    // Output bundle's JSON
    console.log(JSON.stringify(bundle));
});

// Parse and fallback to help if no args
if(_.isEmpty(prog.parse(process.argv).args)) { return prog.help(); }

#!/usr/bin/env node

// Requires
var _ = require('underscore');

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

// Comannder
var prog = require('commander');

// etcd-dump's package.json file
var pkg = require('../package.json');

// Dumper class
var parser = require('../');

// General options
prog
.version(pkg.version);

// Commands
prog
.command('compile [filename]')
.description('Compile an *.itermcolors file to a JSON scheme')
.action(function(filename, opts) {
    // Output JSON color array
    console.log(JSON.stringify(
        parser(fs.readFileSync(filename)),
        null,
        4 // 4 spaces
    ));
});

prog
.command('bundle [dir]')
.description('Bundle a given directory of schemes to one json file')
.action(function(dir, opts) {

    // Merge scheme's together and add name attribute based on filename
    var bundle = fs.readdirSync(dir).map(function(filename) {
        var name = filename.split('.')[0];
        var data = require('../' + path.join(dir, filename));
        data.name = name;

        return data;
    }).reduce(function(bundle, data) {
        bundle[data.name] = data;
        return bundle;
    }, {});

    // Output bundle's JSON
    console.log(JSON.stringify(bundle));
});

// Parse and fallback to help if no args
if(_.isEmpty(prog.parse(process.argv).args)) { return prog.help(); }

Fix small bugs in bundle command


import { StyleSheet, Dimensions } from 'react-native';

export default StyleSheet.create({
  mainContainer: {
    width: Dimensions.get('window').width,
    height: Dimensions.get('window').height
  },
  image: {
    height: 80,
    width: 80,
    resizeMode: 'contain'
  },
  ActorView: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center'
  },
  endingPaths: {
    marginTop: Dimensions.get('window').height / 14
  }
})

import { StyleSheet, Dimensions } from 'react-native';

export default StyleSheet.create({
  mainContainer: {
    // flex: 3,
    width: Dimensions.get('window').width * .97,
    height: Dimensions.get('window').height * .95,
    marginLeft: Dimensions.get('window').width / 60,
    marginTop: Dimensions.get('window').width / 20,
  },
  image: {
    height: 80,
    width: 80,
    resizeMode: 'contain'
  },
  actorView: {
    flex: .6,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    // borderWidth: 1,
  },
  endingActorView: {
    flex: .6,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    // borderWidth: 1,
  },
  pathsView: {
    flex: 3,
    // borderWidth: 1,
    left: 0,
  },
  path: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    alignItems: 'flex-start',
    justifyContent: 'space-between'
  },
  endingPaths: {
    marginTop: Dimensions.get('window').height / 14
  }
})

Add styling for views and images


'use strict';
import React from 'react';

const About = () => (

Davie Poplar Capital is a Raleigh-based private investment firm

      Davie Poplar Capital (DPC) is a Raleigh, NC based private investment firm that acquires, operates, and grows established private businesses.  We make controlling investments in small and mid-sized profitable companies that are based in or relocatable to North and South Carolina.

      Davie Poplar is led by Ralph Isenrich. Prior to founding DPC, Ralph worked in middle market private equity at Blue Point Capital Partners and investment banking at Wells Fargo Securities.  Ralph is a CFA Charterholder and a graduate of the University of North Carolina at Chapel Hill.

);

export default About;

Remove poor use of <br> elements


/**
 * This demo is meant to be straight-forward and
 * not use very complex techniques, such as regular
 * expressions.
 *
 */

function throwFormatError() {
  throw "You should enter a value in the form \"$987.52\" with a dollar sign and optionally two decimal places.";
}

function demo1(numeric) {
  var text = "";

  // Validation of the input
  if (numeric.length() < 1) {
    throwFormatError();
  }

  if (numeric[0] != "$") {
    throwFormatError();
  }

  // Strip off the dollar sign
  numeric = numeric.substring(1);

  // Validate that cents portion is either of length 0 or 2
  var decimalPos = numeric.lastIndexOf(".");

  if (decimalPos != -1 && decimalPos != numeric.length() - 4) {
    throwFormatError();
  }

  var cents = numeric.substring(decimalPos);

  numeric = numeric.substring(0, decimalPos - 1);

  text = numeric + " / " + cents;
  return text;
}

/**
 * demo2 uses regular expressions.
 *
 */

function demo2(numeric) {

}

/**
 * This demo is meant to be straight-forward and
 * not use very complex techniques, such as regular
 * expressions.
 *
 */

function throwFormatError() {
  throw "You should enter a value in the form \"$987.52\" with a dollar sign and optionally two decimal places.";
}

function demo1(numeric) {
  var text = "";

  // Validation of the input
  if (numeric.length < 1) {
    throwFormatError();
  }

  if (numeric[0] != "$") {
    throwFormatError();
  }

  // Strip off the dollar sign
  numeric = numeric.substring(1);

  // Validate that cents portion is either of length 0 or 2
  var decimalPos = numeric.lastIndexOf(".");

  if (decimalPos != -1 && decimalPos != numeric.length - 4) {
    throwFormatError();
  }

  var cents = numeric.substring(decimalPos);

  numeric = numeric.substring(0, decimalPos - 1);

  text = numeric + " / " + cents;
  return text;
}

/**
 * demo2 uses regular expressions.
 *
 */

function demo2(numeric) {

}

Remove erroneous call to property length


var cradle = require('cradle');
var applyDesignDocuments = require('./design-documents');

var couchLocation = process.env.CLOUDANT_URL || process.env.COUCHDB || 'http://localhost';
var couch = new(cradle.Connection)(couchLocation, 5984, {
  cache: true,
  raw: false
});

var db = couch.database('emergencybadges');

db.setup = function (callback) {
  db.exists(function (err, exists) {
    if (err) {
      console.log('error', err);
    } else if (exists) {
      console.log('Database exists.');
      if (typeof callback === 'function') callback();
    } else {
      console.log('Database does not exist. Creating.');
      db.create(function (err, res) {
        if (!err) {
          applyDesignDocuments(db);
          if (typeof callback === 'function') callback();
        }
      });
    }
  });
};

db.updateDesignDocuments = function (callback) {
  applyDesignDocuments(db);
  if (typeof callback === 'function') callback();
};

module.exports = db;

var cradle = require('cradle');
var applyDesignDocuments = require('./design-documents');

var couchLocation = process.env.IRISCOUCH;
// var couchLocation = process.env.CLOUDANT_URL || process.env.COUCHDB || 'http://localhost';
var couch = new(cradle.Connection)(couchLocation, 5984, {
  cache: true,
  raw: false
});

var db = couch.database('emergencybadges');

db.setup = function (callback) {
  db.exists(function (err, exists) {
    if (err) {
      console.log('error', err);
    } else if (exists) {
      console.log('Database exists.');
      if (typeof callback === 'function') callback();
    } else {
      console.log('Database does not exist. Creating.');
      db.create(function (err, res) {
        if (!err) {
          applyDesignDocuments(db);
          if (typeof callback === 'function') callback();
        }
      });
    }
  });
};

db.updateDesignDocuments = function (callback) {
  applyDesignDocuments(db);
  if (typeof callback === 'function') callback();
};

module.exports = db;

Switch to Iriscouch in production


/* Mock interface to load and save bookings to the "back end" */

import { v4 } from 'uuid';

import bookingsByDay from './bookings.json';

const data = bookingsByDay
  .map(day => ({
    ...day,
    bookings: day.bookings.map(booking => ({
      ...booking,
      id: v4()
    }))
  }))
  .sort((a, b) => new Date(a.date) - new Date(b.date));

export const getLatestBookings = async () => data[data.length-1];

export const getBookingsForDate = async (date=null) => data.find(bookings => date === bookings.date);

export const saveBooking = async (booking) => booking;

/* Mock interface to load and save bookings to the "back end" */

import { v4 } from 'uuid';

import bookingsByDay from './bookings.json';

const cache = {};

const _fetchData = async () => {

  if (!cache.data)
  {
    cache.data = bookingsByDay
      .map(day => ({
        ...day,
        bookings: day.bookings.map(booking => ({
          ...booking,
          id: v4()
        }))
      }))
      .sort((a, b) => new Date(a.date) - new Date(b.date));
  }

  return cache.data;

};

const _saveData = async (newBooking) => {

  const data = await _fetchData();

  return data.some(({ bookings }) => {
    const oldBooking = bookings.find(booking => booking.id === newBooking.id);
    if (oldBooking)
    {
      Object.assign(oldBooking, newBooking);
      return true;
    }
    else
    {
      return false;
    }
  });

};

export const getLatestBookings = async () => {
  const data = await _fetchData();
  return data[data.length-1];
};

export const getBookingsForDate = async (date=null) => {
  const data = await _fetchData();
  return data.find(bookings => date === bookings.date);
};

export const saveBooking = async (booking) => {

  if (await _saveData(booking))
  {
    return booking;
  }
  else
  {
    throw new Error(404);
  }

};

Make data persist through date-changes


if (Meteor.is_client) {
  Template.hello.greeting = function () {
    return "Welcome to ~name~.";
  };

  Template.hello.events = {
    'click input' : function () {
      // template data, if any, is available in 'this'
      if (typeof console !== 'undefined')
        console.log("You pressed the button");
    }
  };
}

if (Meteor.is_server) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

if (Meteor.is_client) {
  Template.hello.greeting = function () {
    return "Welcome to ~name~.";
  };

  Template.hello.events({
    'click input' : function () {
      // template data, if any, is available in 'this'
      if (typeof console !== 'undefined')
        console.log("You pressed the button");
    }
  });
}

if (Meteor.is_server) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

Use new event handler syntax in skeleton app


;(function($, ns) {
    ns.WorkspaceSummaryPage = chorus.pages.Base.extend({
        crumbs : function() {
            return [
                { label: t("breadcrumbs.home"), url: "#/" },
                { label: this.model.get("name") }
            ]
        },

        setup : function(workspaceId) {
            // chorus.router supplies arguments to setup
            this.model = new chorus.models.Workspace({id : workspaceId});
            this.model.fetch();
            this.breadcrumbs = new chorus.views.WorkspaceBreadcrumbsView({model: this.model});
            this.subNav = new chorus.views.SubNav({workspace : this.model, tab: "Summary"})
            this.sidebar = new chorus.views.WorkspaceSummarySidebar({model: this.model});

            this.mainContent = new chorus.views.MainContentView({
                model: this.model,
                content : new chorus.views.WorkspaceDetail({model: this.model }),
                contentHeader : new chorus.views.StaticTemplate("plain_text", {text: "Summary"}),
            });
        }
    });
})(jQuery, chorus.pages);

;(function($, ns) {
    ns.WorkspaceSummaryPage = chorus.pages.Base.extend({
        crumbs : function() {
            return [
                { label: t("breadcrumbs.home"), url: "#/" },
                { label: this.model.get("name") }
            ]
        },

        setup : function(workspaceId) {
            // chorus.router supplies arguments to setup
            this.model = new chorus.models.Workspace({id : workspaceId});
            this.model.fetch();
            this.breadcrumbs = new chorus.views.WorkspaceBreadcrumbsView({model: this.model});
            this.subNav = new chorus.views.SubNav({workspace : this.model, tab: "summary"})
            this.sidebar = new chorus.views.WorkspaceSummarySidebar({model: this.model});

            this.mainContent = new chorus.views.MainContentView({
                model: this.model,
                content : new chorus.views.WorkspaceDetail({model: this.model }),
                contentHeader : new chorus.views.StaticTemplate("plain_text", {text: "Summary"}),
            });
        }
    });
})(jQuery, chorus.pages);

Fix current tab styling on workspace summary page


/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

export default ['$http', '$q', function($http, $q) {
    return {
        getInitialPageForList: function(id, url, pageSize) {
            // get the name of the object
            if ($.isNumeric(id)) {
                return $http.get(url + "?id=" + id)
                    .then(function (data) {
                        var queryValue, queryType;
                        if (data.data.results[0].type === "user") {
                            queryValue = data.data.results[0].username;
                            queryType = "username";
                        } else {
                            queryValue = data.data.results[0].name;
                            queryType = "name";
                        }
                        // get how many results are less than or equal to
                        // the name
                        return $http.get(url + "?" + queryType + "__lte=" + queryValue)
                            .then(function (data) {
                                // divide by the page size to get what
                                // page the data should be on
                                var count = data.data.count;
                                return Math.ceil(count/parseInt(pageSize));
                            });
                    });
            } else {
                var defer = $q.defer();
                defer.resolve(1);
                return(defer.promise);
            }
        }
    };
}];

/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

export default ['$http', '$q', function($http, $q) {
    return {
        getInitialPageForList: function(id, url, pageSize) {
            // get the name of the object
            if ($.isNumeric(id)) {
                return $http.get(url + "?id=" + id)
                    .then(function (data) {
                        var queryValue, queryType;
                        if (data.data.results.length) {
                            if (data.data.results[0].type === "user") {
                                queryValue = data.data.results[0].username;
                                queryType = "username";
                            } else {
                                queryValue = data.data.results[0].name;
                                queryType = "name";
                            }
                        } else {
                            queryValue = "";
                            queryType = "name";
                        }
                        // get how many results are less than or equal to
                        // the name
                        return $http.get(url + "?" + queryType + "__lte=" + queryValue)
                            .then(function (data) {
                                // divide by the page size to get what
                                // page the data should be on
                                var count = data.data.count;
                                return Math.max(1, Math.ceil(count/parseInt(pageSize)));
                            });
                    });
            } else {
                var defer = $q.defer();
                defer.resolve(1);
                return(defer.promise);
            }
        }
    };
}];

Fix app crash from our pagination when editing invalid things


module.exports = function listShortCode (host, list) {
    return `
<h2>${host}</h2>
<ol reversed>
${list.map(entry => `<li>${entry}</li>`).join('\n')}
</ol>`;
}

module.exports = function listShortCode (host, list) {
    return `
<h2>${host}</h2>
<ol reversed>
${list.map(entry => `<li>${entry.replaced == undefined ? '' : '<span style="text-decoration:line-through;">' + entry.replaced + '</span> '}${entry}</li>`).join('\n')}
</ol>`;
}

Add replaced item to list shortcode


$(function() {
	$('.gcal-control').click(function() {
		target = $(this).data('target');
		if($(this).hasClass('gcal-control-disabled')) {
			$(this).removeClass('gcal-control-disabled');
			$('.event.'+target).slideDown(500);
		} else {
			$(this).addClass('gcal-control-disabled');
			$('.event.'+target).slideUp(500);
		}
		$(this).blur();
	});

	$('#event-modal').on('show.bs.modal', function(event) {
		var trigger = $(event.relatedTarget);

		$('#event-title').html(trigger.data('summary'));
		$('#event-date').html(trigger.data('date'));
		$('#event-when').html(trigger.data('time'));
		$('#event-where').html(trigger.data('where'));
		$('#event-desc').html(trigger.data('details'));
	});

	//Not the standard method Bootstrap's docs recommend, but we'll need
	//the data-toggle attribute for the details modal.
	$('.event,.month-control').tooltip();
});

$(function() {
	$('.gcal-control').click(function() {
		target = $(this).data('target');
		if($(this).hasClass('gcal-control-disabled')) {
			$(this).removeClass('gcal-control-disabled');
			$('.event.'+target).slideDown(500);
		} else {
			$(this).addClass('gcal-control-disabled');
			$('.event.'+target).slideUp(500);
		}
		$(this).blur();
	});

	$('#event-modal').on('show.bs.modal', function(event) {
		var trigger = $(event.relatedTarget);

		$('#event-title').html(trigger.data('summary'));
		$('#event-date').html(trigger.data('date'));
		$('#event-when').html(trigger.data('time'));
		$('#event-where').html(trigger.data('where'));
		$('#event-desc').html(trigger.data('details'));

		trigger.tooltip('hide');
	});

	//Not the standard method Bootstrap's docs recommend, but we'll need
	//the data-toggle attribute for the details modal.
	$('.event,.month-control').tooltip();
});

Hide tooltip when showing modal


/**
 * @class Denkmal_Component_HeaderBar
 * @extends Denkmal_Component_Abstract
 */
var Denkmal_Component_HeaderBar = Denkmal_Component_Abstract.extend({

	/** @type String */
	_class: 'Denkmal_Component_HeaderBar',

	events: {
		'click .showSearch': 'showSearch'
	},

	childrenEvents: {
		'CM_FormField_Text focus': function() {
			this._expandSearch(true);
		},
		'CM_FormField_Text blur': function() {
			this._expandSearch(false);
		}
	},

	showSearch: function() {
		if (!this._hasSearchForm()) {
			return;
		}
		this._expandSearch(true);
		this._getSearchForm().setFocus();
	},

	/**
	 * @return FB_Form_SearchContent
	 */
	_getSearchForm: function() {
		if (null === this._searchForm) {
			this._searchForm = this.findChild('FB_Form_SearchContent');
		}
		return this._searchForm;
	},

	/**
	 * @returns {Boolean}
	 */
	_hasSearchForm: function() {
		return (null !== this._getSearchForm());
	},

	/**
	 * @param {Boolean} state
	 */
	_expandSearch: function(state) {
		this.$('.bar').toggleClass('search-expand', state);
	}
});

/**
 * @class Denkmal_Component_HeaderBar
 * @extends Denkmal_Component_Abstract
 */
var Denkmal_Component_HeaderBar = Denkmal_Component_Abstract.extend({

	/** @type String */
	_class: 'Denkmal_Component_HeaderBar',

	/** @type Denkmal_Form_SearchContent|Null */
	_searchForm: null,

	events: {
		'click .showSearch': 'showSearch'
	},

	childrenEvents: {
		'CM_FormField_Text focus': function() {
			this._expandSearch(true);
		},
		'CM_FormField_Text blur': function() {
			this._expandSearch(false);
		}
	},

	showSearch: function() {
		if (!this._hasSearchForm()) {
			return;
		}
		this._expandSearch(true);
		console.log(this);
		console.log(this._getSearchForm());
		this._getSearchForm().setFocus();
	},

	/**
	 * @return Denkmal_Form_SearchContent
	 */
	_getSearchForm: function() {
		if (null === this._searchForm) {
			this._searchForm = this.findChild('Denkmal_Form_SearchContent');
		}
		return this._searchForm;
	},

	/**
	 * @returns {Boolean}
	 */
	_hasSearchForm: function() {
		return (null !== this._getSearchForm());
	},

	/**
	 * @param {Boolean} state
	 */
	_expandSearch: function(state) {
		this.$('.bar').toggleClass('search-expand', state);
	}
});

Fix searchForm JS in headerbar


(function(app) {
  'use strict';

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');

  var ContentHeader = helper.inherits(function(props) {
    ContentHeader.super_.call(this);

    this.element = this.prop(props.element);

    this.sidebarToggleButton = this.prop(new SidebarToggleButton({
      element: this.sidebarToggleButtonElement(),
      collapser: props.sidebarCollapser,
      expander: props.sidebarExpander
    }));

    this.sidebarToggleButton().registerTapListener();
  }, jCore.Component);

  ContentHeader.prototype.sidebarToggleButtonElement = function() {
    return dom.child(this.element(), 0);
  };

  ContentHeader.prototype.loadButtonElement = function() {
    return dom.child(this.element(), 1);
  };

  ContentHeader.prototype.redraw = function() {
    this.sidebarToggleButton().redraw();
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = ContentHeader;
  else
    app.ContentHeader = ContentHeader;
})(this.app || (this.app = {}));

(function(app) {
  'use strict';

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var SidebarToggleButton = app.SidebarToggleButton || require('./sidebar-toggle-button.js');

  var ContentHeader = helper.inherits(function(props) {
    ContentHeader.super_.call(this);

    this.element = this.prop(props.element);

    this.sidebarToggleButton = this.prop(new SidebarToggleButton({
      element: this.sidebarToggleButtonElement(),
      collapser: props.sidebarCollapser,
      expander: props.sidebarExpander
    }));

    this.sidebarToggleButton().registerTapListener();
  }, jCore.Component);

  ContentHeader.prototype.sidebarToggleButtonElement = function() {
    return dom.child(this.element(), 0);
  };

  ContentHeader.prototype.loadButtonElement = function() {
    return dom.child(this.element(), 1);
  };

  ContentHeader.prototype.saveButtonElement = function() {
    return dom.child(this.element(), 2);
  };

  ContentHeader.prototype.redraw = function() {
    this.sidebarToggleButton().redraw();
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = ContentHeader;
  else
    app.ContentHeader = ContentHeader;
})(this.app || (this.app = {}));

Add method to access an element of save-button


import express from 'express';
import mongoose from 'mongoose';

import config from '../config';

import apiRouter from './api';

// Assemble the routes
const app = express();
app.use('/api', apiRouter);

// Connect to MongoDB
const {MONGODB_URL} = config;
mongoose.connect(MONGODB_URL);

// Start the server when the connection is up
const SERVER_PORT = 3000;
mongoose.connection.db.once('open', () => {
  app.listen(SERVER_PORT, () => {
    // process.on('SIGINT')
    console.log(`Running server on port ${SERVER_PORT}`);
  });
});

import express from 'express';
import mongoose from 'mongoose';

import config from '../config';

import apiRouter from './api';

// Assemble the routes
const app = express();
app.use('/api', apiRouter);

// TODO: Change to properly resolve path
app.use(express.static('../frontend/build'));

// Connect to MongoDB
const {MONGODB_URL} = config;
mongoose.connect(MONGODB_URL);

// Start the server when the connection is up
const SERVER_PORT = 3000;
mongoose.connection.db.once('open', () => {
  app.listen(SERVER_PORT, () => {
    // process.on('SIGINT')
    console.log(`Running server on port ${SERVER_PORT}`);
  });
});

Add static files handling to express app.


const axios = require('axios');
const querystring = require('querystring');

exports.handler = function (event, _context, callback) {
  if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
  }

  console.log("Logging inside functions");

  const apiToken = process.env.API_TOKEN;
  const query = querystring.stringify(event.queryStringParameters);

  // Only use an authorization header if there is an apiToken defined from the .env file
  const configHeader =
    typeof apiToken === 'undefined'
      ? null
      : {
          headers: { Authorization: 'bearer ' + apiToken },
        };

  axios
    .get(`https://api.github.com/search/issues?${query}`, configHeader)
    .then((response) => {
      callback(null, {
        statusCode: 200,
        body: JSON.stringify(response.data),
      });
    })
    .catch((error) => {
      console.log(error);
    });
};

const axios = require('axios');
const querystring = require('querystring');

exports.handler = function (event, _context, callback) {
  if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
  }

  console.log("Logging inside functions ", process.env.TEST);

  const apiToken = process.env.API_TOKEN;
  const query = querystring.stringify(event.queryStringParameters);

  // Only use an authorization header if there is an apiToken defined from the .env file
  const configHeader =
    typeof apiToken === 'undefined'
      ? null
      : {
          headers: { Authorization: 'bearer ' + apiToken },
        };

  axios
    .get(`https://api.github.com/search/issues?${query}`, configHeader)
    .then((response) => {
      callback(null, {
        statusCode: 200,
        body: JSON.stringify(response.data),
      });
    })
    .catch((error) => {
      console.log(error);
    });
};

Test env variable in function


/** @jsx React.DOM */
'use strict';

var React = require('react'),
  ReactIntlMixin = require('react-intl');

var Role = React.createClass({
  mixins: [ReactIntlMixin],
  propTypes: {
    disabled: React.PropTypes.bool,
    error: React.PropTypes.string,
    label: React.PropTypes.string.isRequired,
    maxCardinality: React.PropTypes.number,
    onCreateIndividuInEntity: React.PropTypes.func.isRequired,
    role: React.PropTypes.string.isRequired,
  },
  render() {
    var maxCardinality = this.props.maxCardinality;
    return (

{this.props.label}

        {this.props.error &&
{this.props.error}
}
        {this.props.children}
        {
          ! this.props.disabled && (typeof maxCardinality === 'undefined' || ! this.props.children ||
          this.props.children.length < maxCardinality) && (
             { event.preventDefault(); this.props.onCreateIndividuInEntity(); }}>
              {this.getIntlMessage('add')}

          )
        }

    );
  },
});

module.exports = Role;

/** @jsx React.DOM */
'use strict';

var React = require('react'),
  ReactIntlMixin = require('react-intl');

var Role = React.createClass({
  mixins: [ReactIntlMixin],
  propTypes: {
    disabled: React.PropTypes.bool,
    error: React.PropTypes.string,
    label: React.PropTypes.string.isRequired,
    maxCardinality: React.PropTypes.number,
    onCreateIndividuInEntity: React.PropTypes.func.isRequired,
    role: React.PropTypes.string.isRequired,
  },
  render() {
    var maxCardinality = this.props.maxCardinality;
    return (

        {
          (
            typeof maxCardinality === 'undefined' || ! this.props.children ||
              this.props.children.length < maxCardinality
          ) && (
            <button
              className='btn btn-default btn-sm pull-right'
              disabled={this.props.disabled}
              onClick={(event) => {
                  event.preventDefault();
                  this.props.onCreateIndividuInEntity();
              }}
            >
              {this.getIntlMessage('add')}
            </button>
          )
        }

{this.props.label}

        {this.props.error &&
{this.props.error}
}
        {this.props.children}

    );
  },
});

module.exports = Role;

Disable add button too when test-case is disabled


function onKeyPress(key) {
    if (key === NEXT) {
        var nextButton = document.querySelector('.nxt');
        simulateClick(nextButton);
    } else if (key === PLAY) {
        var playPauseButton = document.querySelector('.ply');
        simulateClick(playPauseButton);
    } else if (key === PREV) {
        var backButton = document.querySelector('.prv');
        simulateClick(backButton);
    }
}

function onKeyPress(key) {
    if (key === NEXT) {
        var nextButton = document.querySelector('.m-playbar .nxt');
        simulateClick(nextButton);
    } else if (key === PLAY) {
        var playPauseButton = document.querySelector('.m-playbar .ply');
        simulateClick(playPauseButton);
    } else if (key === PREV) {
        var backButton = document.querySelector('.m-playbar .prv');
        simulateClick(backButton);
    }
}

Update extension for 163 Music


/**
 * Created by Ennis on 21/02/16.
 */
var lexer = new Lexer();

var doLexer = function () {
    // String handling
    var lexer = new Lexer();
    lexer.addRule(/[a-zA-Z0-9]+/, function (lexeme) {
        return arguments;
    }
    )
    // Whitespace Ignore
    lexer.addRule(/\S+/, function (lexeme) {

    }
    )

}

/**
 * Created by Ennis on 21/02/16.
 */
var lexer = new Lexer();

var doLexer = function () {
    // String handling
    var lexer = new Lexer();
    lexer.addRule(/[a-zA-Z0-9]+/, function (lexeme) {
        return arguments;
    }
    );
    // Whitespace Ignore
    lexer.addRule(/\S+/, function (lexeme) {

    }
    );
};

Add branch for koding vm testing


ngDefine('cockpit.plugin.base.views', ['require'], function(module, require) {

  var Controller = [ '$scope', '$dialog',
    function($scope, $dialog) {

    $scope.openDialog = function () {
      var dialog = $dialog.dialog({
        resolve: {
          processData: function() { return $scope.processData; },
          processInstance: function() { return $scope.processInstance; }
        },
        controller: 'UpdateProcessInstanceSuspensionStateController',
        templateUrl: require.toUrl('./update-suspension-state-dialog.html')
      });

      dialog.open().then(function(result) {

        // dialog closed. YEA!
        if (result.status === 'SUCCESS') {
          $scope.processInstance.suspended = result.suspended;

          $scope.processData.set('filter', angular.extend({}, $scope.filter));
        }

      });
    };

  }];

  var Configuration = function PluginConfiguration(ViewsProvider) {

    ViewsProvider.registerDefaultView('cockpit.processInstance.action', {
      id: 'update-suspension-state-action',
      label: 'Update Suspension State',
      url: 'plugin://base/static/app/views/processInstance/update-suspension-state-action.html',
      controller: Controller,
      priority: 50
    });
  };

  Configuration.$inject = ['ViewsProvider'];

  module.config(Configuration);

});

ngDefine('cockpit.plugin.base.views', ['require'], function(module, require) {

  var Controller = [ '$scope', '$dialog',
    function($scope, $dialog) {

    $scope.openDialog = function () {
      var dialog = $dialog.dialog({
        resolve: {
          processData: function() { return $scope.processData; },
          processInstance: function() { return $scope.processInstance; }
        },
        controller: 'UpdateProcessInstanceSuspensionStateController',
        templateUrl: require.toUrl('./update-suspension-state-dialog.html')
      });

      dialog.open().then(function(result) {

        // dialog closed. YEA!
        if (result.status === 'SUCCESS') {
          $scope.processInstance.suspended = result.suspended;

          $scope.processData.set('filter', angular.extend({}, $scope.filter));
        }

      });
    };

  }];

  var Configuration = function PluginConfiguration(ViewsProvider) {

    ViewsProvider.registerDefaultView('cockpit.processInstance.action', {
      id: 'update-suspension-state-action',
      label: 'Update Suspension State',
      url: 'plugin://base/static/app/views/processInstance/update-suspension-state-action.html',
      controller: Controller,
      priority: 5
    });
  };

  Configuration.$inject = ['ViewsProvider'];

  module.config(Configuration);

});

Reorder action button in toolbar


'use strict';

// Dependencies
const moment = require('moment')

module.exports = function setup() {
  return function plugin(files, aldous, done) {
    files.forEach(function(file) {
      if (file.date) {
        file.date = moment(file.date)
      }
    })
  }
}

'use strict';

// Dependencies
const moment = require('moment')

module.exports = function setup() {
  return function plugin(files, aldous, done) {
    setImmediate(done)
    files.forEach(function(file) {
      if (file.date) {
        file.date = moment(file.date)
      }
    })
  }
}

Fix missing call to done()


import Controller from '@ember/controller';
import {inject as service} from '@ember/service';

export default class UploadThemeController extends Controller {
    @service limit;

    get isAllowed() {
        return !this.limit.limiter.isLimited('customThemes');
    }
}

import Controller from '@ember/controller';
import {inject as service} from '@ember/service';

export default class UploadThemeController extends Controller {
    @service config;

    get isAllowed() {
        return !this.config.get('hostSettings')?.limits?.customThemes;
    }
}

Revert "Replaced the config service by the limiter service"


// Use Parse.Cloud.define to define as many cloud functions as you want.
// For example:
Parse.Cloud.define("hello", function(request, response) {
  response.success("Hello world!");
});

// Status code 0 : request made ; 1 : process started ; 2 : process completed successfully
// Function to set status code to 1 and assign a tutor ; return no tutor availble in ur locality in case of no tutor
// After tutor is assigned , he must be sent a push notification consisting of name of student , subject and topic along with his phone number
// If the tutor accepts the request , a notification must be sent to the student with details of the tutor

Add to do for cloud code


module.exports = function crawler(callback) {
	const request = require('request');
	const cheerio = require('cheerio');

	const URL = 'http://sarc.pucrs.br/Default/';

	var data = {};
	let requestHandler = (err, response, html) => {
		if(err) return callback(err);

		let $ = cheerio.load(html)('#ctl00_cphTitulo_UpdatePanel2 > div > table');

		for (let i = 0, l = $.length; i < l; i++) {
			let content    = cheerio.load($.eq(i).html());
			let horario    = content('span').html();
			let table_data = content('.ms-btoolbar').children();
			let details = [];
			for (let j = 0, l = table_data.length; j < l; j+=3) {
				let detail = {
					'resource' : table_data.eq(j).text().trim(),
					'course'   : table_data.eq(j+1).text().trim(),
					'owner'    : table_data.eq(j+2).text().trim()
				};
				details.push(detail);
			}
			data[horario] = details;
		}
		callback(null, data);
	}
	request(URL, requestHandler);
}

module.exports = function crawler(callback) {
	const request = require('request');
	const cheerio = require('cheerio');

	const URL = 'http://sarc.pucrs.br/Default/';

	var data = {};
	let requestHandler = (err, response, html) => {
		if(err) return callback(err);

		let $ = cheerio.load(html)('#ctl00_cphTitulo_UpdatePanel2 > div > table');

		for (let i = 0, l = $.length; i < l; i++) {
			let content    = cheerio.load($.eq(i).html());
			let time       = content('span').html();
			let table_data = content('.ms-btoolbar').children();
			let details = [];
			for (let j = 0, l = table_data.length; j < l; j+=3) {
				let detail = {
					'resource' : table_data.eq(j).text().trim(),
					'course'   : table_data.eq(j+1).text().trim(),
					'owner'    : table_data.eq(j+2).text().trim()
				};
				details.push(detail);
			}
			time = formatTime(time);
			data[time] = details;
		}
		callback(null, data);
	}
	request(URL, requestHandler);
}

function formatTime(time) {
	var weekday = new Date().getDay() + 1
	return weekday + time
}

Add day of the week to time.


'use strict';

let React = require('react-native');
let {
 Image,
 PixelRatio,
 PropTypes,
} = React;

class ResponsiveImage extends React.Component {

  setNativeProps(nativeProps) {
    this.refs.image.setNativeProps(nativeProps);
  }

  render() {
    let { source } = this.props;
    let optimalSource = this._getClosestHighQualitySource();
    if (optimalSource) {
      source = optimalSource;
    }
    if (!source) {
      throw new Error(`Couldn't find an appopriate image source`);
    }

    return <Image {...this.props} ref="image" source={source} />;
  }

  _getClosestHighQualitySource() {
    let { sources } = this.props;
    let pixelRatios = Object.keys(sources).map(parseFloat);
    if (!pixelRatios.length) {
      return null;
    }

    pixelRatios.sort((ratioA, ratioB) => ratioA - ratioB);
    for (let ii = 0; ii < pixelRatios.length; ii++) {
      if (pixelRatios[ii] >= PixelRatio.get()) {
        return sources[pixelRatios[ii]];
      }
    }

    let largestPixelRatio = pixelRatios[pixelRatios.length - 1];
    return sources[largestPixelRatio];
  }
}

ResponsiveImage.propTypes = {
  ...Image.propTypes,
  sources: PropTypes.objectOf(Image.propTypes.source.isRequired),
};

module.exports = ResponsiveImage;

'use strict';

let React = require('react-native');
let {
 Image,
 PixelRatio,
 PropTypes,
} = React;

class ResponsiveImage extends React.Component {

  setNativeProps(nativeProps) {
    this.refs.image.setNativeProps(nativeProps);
  }

  render() {
    let { source } = this.props;
    let optimalSource = this._getClosestHighQualitySource();
    if (optimalSource) {
      source = optimalSource;
    }
    if (!source) {
      throw new Error(`Couldn't find an appropriate image source`);
    }

    return <Image {...this.props} ref="image" source={source} />;
  }

  _getClosestHighQualitySource() {
    let { sources } = this.props;
    let pixelRatios = Object.keys(sources);
    if (!pixelRatios.length) {
      return null;
    }

    pixelRatios.sort((ratioA, ratioB) =>
      parseFloat(ratioA) - parseFloat(ratioB)
    );
    for (let ii = 0; ii < pixelRatios.length; ii++) {
      if (pixelRatios[ii] >= PixelRatio.get()) {
        return sources[pixelRatios[ii]];
      }
    }

    let largestPixelRatio = pixelRatios[pixelRatios.length - 1];
    return sources[largestPixelRatio];
  }
}

ResponsiveImage.propTypes = {
  ...Image.propTypes,
  sources: PropTypes.objectOf(Image.propTypes.source.isRequired),
};

module.exports = ResponsiveImage;

Sort the original keys instead of the parsed floats


'use strict';

var slice      = Array.prototype.slice
  , isFunction = require('es5-ext/lib/Function/is-function')
  , a2p        = require('../apply_async_fn');

require('../../extend')('invokeAsync', null, function (args, resolve) {
	var fn;
	if (this.failed) {
		resolve(this.promise);
		return;
	}
	fn = args[0];
	args = slice.call(args, 1);
	if (!isFunction(fn)) {
		if (!isFunction(this.value[fn])) {
			resolve(new Error("Cannot invoke '" + fn +
				"' on given result. It's not a function."));
			return;
		}
		fn = this.value[fn];
	}
	a2p(fn, this.value, args, resolve);
});

module.exports = require('../../deferred');

'use strict';

var slice      = Array.prototype.slice
  , isCallable = require('es5-ext/lib/Object/is-callable')
  , a2p        = require('../apply_async_fn');

require('../../extend')('invokeAsync', null, function (args, resolve) {
	var fn;
	if (this.failed) {
		resolve(this.promise);
		return;
	}
	fn = args[0];
	args = slice.call(args, 1);
	if (!isCallable(fn)) {
		if (!isCallable(this.value[fn])) {
			resolve(new Error("Cannot invoke '" + fn +
				"' on given result. It's not a function."));
			return;
		}
		fn = this.value[fn];
	}
	a2p(fn, this.value, args, resolve);
});

module.exports = require('../../deferred');

Replace isFunction check with more open isCallable


"use strict";

var setup = require("../../common/setup-base"),
    desired = require('./desired'),
    unorm = require('unorm');

describe('testapp - accented characters', function () {
  var driver;
  setup(this, desired).then(function (d) { driver = d; });

  it('should send accented text', function (done) {
    var testText = unorm.nfd("é Œ ù ḍ");
    driver
      .elementsByClassName('UIATextField').at(1)
        .sendKeys(testText)
        .text()
        .should.become(testText)
      .nodeify(done);
  });

  it('should send delete key', function (done) {
    driver
      .elementsByClassName('UIATextField').at(1)
        .clear()
        .sendKeys("abc")
        .sendKeys('\uE003\uE003\uE003')
        .text()
        .should.become("")
      .nodeify(done);
  });
});

"use strict";

var setup = require("../../common/setup-base"),
    desired = require('./desired'),
    unorm = require('unorm');

describe('testapp - accented characters', function () {
  var driver;
  setup(this, desired).then(function (d) { driver = d; });

  it('should send accented text', function (done) {
    var testText = unorm.nfd("é Œ ù ḍ");
    driver
      .elementsByClassName('UIATextField').at(1)
        .sendKeys(testText)
        .text()
        .should.become(testText)
      .nodeify(done);
  });

  it('should send delete key', function (done) {
    driver
      .elementsByClassName('UIATextField').at(1)
        .clear()
        .sendKeys("abcd")
        .sendKeys('\uE003\uE003')
        .text()
        .should.become("ab")
      .nodeify(done);
  });
});

Clean up ios delete key test


import('helma.system', 'system');

system.addHostObject(org.helma.web.Response);

system.addCallback("onResponse", "debugFlusher", function(res) {
    if (res.status == 200 || res.status >= 400) {
        res.flushDebug();
    }
})

/**
 * Render a skin to the response's buffer
 * @param skin
 * @param context
 * @param scope
 */
Response.prototype.render = function(skin, context, scope) {
    var render = require('helma.skin').render;
    this.write(render(skin, context, scope));
}

/**
 * Print a debug message to the rendered page.
 */
Response.prototype.debug = function() {
    var buffer = this.debugBuffer || new Buffer();
    buffer.write("
");
    var length = arguments.length;
    for (var i = 0; i < length; i++) {
        buffer.write(arguments[i]);
        if (i < length - 1) {
            buffer.write(" ");
        }
    }
    buffer.writeln("
");
    this.debugBuffer = buffer;
    return null;
};

/**
 * Write the debug buffer to the response's main buffer.
 */
Response.prototype.flushDebug = function() {
    if (this.debugBuffer != null) {
        this.write(this.debugBuffer);
        this.debugBuffer.reset();
    }
    return null;
};

import('helma.system', 'system');

system.addHostObject(org.helma.web.Response);

/**
 * Render a skin to the response's buffer
 * @param skin
 * @param context
 * @param scope
 */
Response.prototype.render = function render(skin, context, scope) {
    var render = require('helma.skin').render;
    this.write(render(skin, context, scope));
}

/**
 * Print a debug message to the rendered page.
 */
Response.prototype.debug = function debug() {
    var buffer = this.debugBuffer || new Buffer();
    buffer.write("
");
    var length = arguments.length;
    for (var i = 0; i < length; i++) {
        buffer.write(arguments[i]);
        if (i < length - 1) {
            buffer.write(" ");
        }
    }
    buffer.writeln("
");
    this.debugBuffer = buffer;
    return null;
};

/**
 * Write the debug buffer to the response's main buffer.
 */
Response.prototype.flushDebug = function() {
    if (this.debugBuffer != null) {
        this.write(this.debugBuffer);
        this.debugBuffer.reset();
    }
    return null;
};

Remove old style system callback, add function names for render() and debug()


'use strict';

// MODULES //

var isInteger = require( '@stdlib/utils/is-integer' );

// CONSTANTS //

var MAX = require( '@stdlib/math/constants/float64-max-safe-integer' );

// IS ARRAY-LIKE //

/**
* FUNCTION: isArrayLike( value )
*	Tests if a value is array-like.
*
* @param {*} value - value to test
* @param {Boolean} boolean indicating if a value is array-like
*/
function isArrayLike( value ) {
	return (
		value !== void 0 &&
		value !== null &&
		typeof value !== 'function' &&
		isInteger( value.length ) &&
		value.length >= 0 &&
		value.length <= MAX
	);
} // end FUNCTION isArrayLike()

// EXPORTS //

module.exports = isArrayLike;

'use strict';

// MODULES //

var isInteger = require( '@stdlib/utils/is-integer' );

// CONSTANTS //

var MAX = require( '@stdlib/math/constants/uint32-max' );

// IS ARRAY-LIKE //

/**
* FUNCTION: isArrayLike( value )
*	Tests if a value is array-like.
*
* @param {*} value - value to test
* @param {Boolean} boolean indicating if a value is array-like
*/
function isArrayLike( value ) {
	return (
		value !== void 0 &&
		value !== null &&
		typeof value !== 'function' &&
		isInteger( value.length ) &&
		value.length >= 0 &&
		value.length <= MAX
	);
} // end FUNCTION isArrayLike()

// EXPORTS //

module.exports = isArrayLike;

Fix array-like check for max length value


var process = require('process')
var elasticsearch = require('elasticsearch')
require('dotenv').config({silent: process.env.NODE_ENV === 'production'})

var client = new elasticsearch.Client({
  // host: 'search-ppsandbox-6atza6pvphfjp73xqg7yhyl5qi.us-east-1.es.amazonaws.com',
  host: 'search-pp-stage-37xn6cdq7tj7ehv5rjrgxgrjhq.us-east-1.es.amazonaws.com',
  connectionClass: require('http-aws-es'),
  amazonES: {
    region: 'us-east-1',
    accessKey: process.env.AWS_ACCESS_KEY_ID,
    secretKey: process.env.AWS_SECRET_ACCESS_KEY
  },
  // log: 'debug'
})

// var client = new elasticsearch.Client({
//   hosts: 'localhost:32769',
// })

module.exports = exports = client

var process = require('process')
var elasticsearch = require('elasticsearch')
require('dotenv').config({silent: process.env.NODE_ENV === 'production'})
var AWS = require("aws-sdk")

AWS.config.update({
  profile: "pp",
  region: "us-east-1"
});

var client = new elasticsearch.Client({
  host: 'search-pp-stage-37xn6cdq7tj7ehv5rjrgxgrjhq.us-east-1.es.amazonaws.com',
  connectionClass: require('http-aws-es'),
  amazonES: {
    region: 'us-east-1',
    credentials: AWS.config.credentials
  },
  // log: 'debug'
})

module.exports = exports = client

Configure ElasticSearch to use AWS config


import Ember from 'ember';

export default Ember.Route.extend({
  setupController(controller, session) {
    this._super(controller, session);
    controller.set('experiment', this.controllerFor('participate.survey').get('experiment'));
    controller.set('session', session);
    controller.set('pastSessions', []);
  },
  actions: {
    willTransition(transition) {
      this._super(transition);
      if (transition.targetName === 'participate.survey.results' || transition.targetName === 'exit') {
        return true;
      }

      var frameIndex = this.controllerFor('participate.survey.index').get('frameIndex');
      var framePage = this.controllerFor('participate.survey.index').get('framePage');

      if (frameIndex !== 0) {
        this.replaceWith('participate.survey.index');
        // Disable back button in qsort page 2, rating-form page 1, and thank-you page
        if (!(frameIndex === 2 && framePage === 1) && frameIndex !== 3 && frameIndex !== 4) {
          this.controllerFor('participate.survey.index').set('frameIndex', frameIndex - 1);
        }
        // Update pages within the rating-form
        if (frameIndex === 3 && framePage !== 0) {
          this.controllerFor('participate.survey.index').set('framePage', framePage - 1);
        }
      }
    }
  }
});

import Ember from 'ember';

export default Ember.Route.extend({
  setupController(controller, session) {
    this._super(controller, session);
    controller.set('experiment', this.controllerFor('participate.survey').get('experiment'));
    controller.set('session', session);
    controller.set('pastSessions', []);
  },
  actions: {
    willTransition(transition) {
      this._super(transition);
      var oldURL = this.router.generate(this.routeName);
      var newURL = this.router.location.getURL();
      if (oldURL !== newURL) {
        this.router.location.setURL(oldURL);
      }

      if (transition.targetName === 'participate.survey.results' || transition.targetName === 'exit') {
        return true;
      }

      var frameIndex = this.controllerFor('participate.survey.index').get('frameIndex');
      var framePage = this.controllerFor('participate.survey.index').get('framePage');
      if (frameIndex !== 0) {
        // Disable back button in qsort page 2, rating-form page 1, and thank-you page
        if (!(frameIndex === 2 && framePage === 1) && frameIndex !== 3 && frameIndex !== 4) {
          this.controllerFor('participate.survey.index').set('frameIndex', frameIndex - 1);
        }
        // Update pages within the rating-form
        if (frameIndex === 3 && framePage !== 0) {
          this.controllerFor('participate.survey.index').set('framePage', framePage - 1);
        }
      }
      transition.abort();
    }
  }
});

Set router location in willTransition


import m from 'mithril';

export const HomeBannerSlide = {
    view({attrs}) {

        const {
            slide,
            slideClass,
            sliderTransitionStyle
        } = attrs;

        return m(`.slide.w-slide.${slideClass}`, {
            style: `${sliderTransitionStyle} background-image: url(${slide.image});`
        }, [
            m('.hero-slide-wrapper', [
                m('.w-container.u-text-center', [
                    m('.w-row', [
                        m('.w-col.w-col-8.w-col-push-2', [
                            m('h1.hero-home-title', m.trust(slide.title)),
                            m('h2.hero-home-subtitle.u-marginbottom-20', m.trust(slide.subtitle))
                        ]),
                        m('a.btn.btn-large.btn-inline', { href: slide.link }, slide.cta)
                    ])
                ])
            ])
        ]);
    }
};

import m from 'mithril';

export const HomeBannerSlide = {
    view({attrs}) {

        const {
            slide,
            slideClass,
            sliderTransitionStyle
        } = attrs;

        return m(`.slide.w-slide.${slideClass}`, {
            style: `${sliderTransitionStyle} background-image: url(${slide.image});`
        }, [
            m('.hero-slide-wrapper', [
                m('.w-container.u-text-center', [
                    m('.w-row', [
                        m('.w-col.w-col-8.w-col-push-2', [
                            m('h1.hero-home-title', m.trust(slide.title)),
                            m('h2.hero-home-subtitle.u-marginbottom-20', m.trust(slide.subtitle)),
                            m('a.btn.btn-large.btn-inline', { href: slide.link }, slide.cta)
                        ])
                    ])
                ])
            ])
        ]);
    }
};

Fix a broken line in html


const { GraphQLClient } = require("graphql-request");
const { writeFileSync, existsSync, mkdirSync } = require("fs");

async function fetchMembers(organisation) {
  const token = process.env.GH_TOKEN;

  if (!token) {
    console.error("'GH_TOKEN' not set. Could not fetch nteract members.");
    return [];
  }

  const client = new GraphQLClient("https://api.github.com/graphql", {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });

  const query = `{
    organization(login: ${organisation}) {
      members(first: 100) {
        totalCount
          nodes {
            name
            login
            websiteUrl
            avatarUrl
            url
          }
      }
    }
  }`;

  try {
    const data = await client.request(query);
    if (data.organization.members.totalCount > 100) {
      console.error(
        "100+ members in the organization. That's too much for one GraphQL call."
      );
    }
    return data.organization.members.nodes;
  } catch (e) {
    console.error(e);
    return [];
  }
}

async function main() {
  const members = await fetchMembers("nteract");
  if (!existsSync("generated")) mkdirSync("generated");
  writeFileSync("./generated/nteract-members.json", JSON.stringify(members));
}

main();

const { GraphQLClient } = require("graphql-request");
const { writeFileSync, existsSync, mkdirSync } = require("fs");

async function fetchMembers(organisation) {
  const token = process.env.GH_TOKEN;

  if (!token) {
    console.error("'GH_TOKEN' not set. Could not fetch nteract members.");
    return [];
  }

  const client = new GraphQLClient("https://api.github.com/graphql", {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });

  const query = `{
    organization(login: ${organisation}) {
      membersWithRole(first: 100) {
        totalCount
          nodes {
            name
            login
            websiteUrl
            avatarUrl
            url
          }
      }
    }
  }`;

  try {
    const data = await client.request(query);
    return data.organization.membersWithRole.nodes;
  } catch (e) {
    console.error(e);
    return [];
  }
}

async function main() {
  const members = await fetchMembers("nteract");
  if (!existsSync("generated")) mkdirSync("generated");
  writeFileSync("./generated/nteract-members.json", JSON.stringify(members));
}

main();

Update GitHub API query for latest version


export default (doc, fields) => {
    fields.forEach(field => {
        process(doc, field.split('.'));
    })
}

const process = (doc, parts) => {
    if (parts.length === 1) {
        if (!(parts[0] in doc)) {
            doc[parts[0]] = undefined;
        }
    } else {
        if (parts[0] in doc) {
            process(doc[parts[0]], parts.slice(-1*(parts.length - 1)))
        } else {
            doc[parts[0]] = undefined;
        }
    }
};

export default (doc, fields) => {
    fields.forEach(field => {
        process(doc, field.split('.'));
    })
}

const process = (doc, parts) => {
    if (parts.length === 1) {
        if (!(parts[0] in doc)) {
            doc[parts[0]] = undefined;
        }
    } else {
        if (parts[0] in doc) {
            if (doc[parts[0]]) {
                process(doc[parts[0]], parts.slice(-1*(parts.length - 1)))
            }
        } else {
            doc[parts[0]] = undefined;
        }
    }
};

Fix for undefined on nested fields


/**
 * Created by mbinet on 3/27/17.
 */
import cookie from 'react-cookie'

function getLang() {

    var user;
    if (user = cookie.load('user')) {
        return (user.profile.lang)
    }
    else {
        return ('en')
    }
}

export default getLang;

/**
 * Created by mbinet on 3/27/17.
 */
import cookie from 'react-cookie'

function getLang() {

    var user;
    if (user = cookie.load('user')) {
        if (user[0] == 'j') {
            user = user.substr(2)
            user = JSON.parse(user)
        }
        if (user.profile)
            return (user.profile.lang)
        else
            return ('en')
    }
    else {
        return ('en')
    }
}

export default getLang;

Fix 'j:' issue on cookie


var cmd = require('commander')
, fs = require('fs')
, inquirer = require('inquirer')
, pjson = require('../package.json')
, request = require('request')

var API_URL = 'https://api.digitalocean.com/v2/'

var digio = (function () {

  var check_droplet = function () {
    console.log('check');
  }

  return {
    init: function () {
      cmd
        .version('Digio v' + pjson.version)
        .option('-c, --check', 'Check droplet', check_droplet)
        .parse(process.argv)
    }
  }

})()

digio.init()

#!/usr/bin/env node

var cmd = require('commander')
, fs = require('fs')
, inquirer = require('inquirer')
, _package = require('../package.json')
, request = require('request')

var digio = (function () {

  var exec = function (options, callback) {
    options.url = 'https://api.digitalocean.com/v2/' + options.action
    options.headers = {
      json: true,
      Authorization: 'Bearer ' + options.token
    }

    delete options.action
    delete options.token

    request(options, function (err, res, body) {
      if (err) return callback(err)
      if (res.statusCode === 401) return callback(JSON.parse(body))

      callback(null, body)
    })
  }

  var list_droplets = function (token) {
    var options = {
      action: 'droplets',
      token: token
    }

    exec(options, function (err, res) {
      if (err) {
        console.log('Something went terribly wrong!')
        return
      }

      var json = JSON.parse(res)

      console.log('\nDroplets: ' + json.meta.total)

      json.droplets.forEach(function (droplet) {
        var result = '- ' + droplet.name + ' ('+droplet.id+')\n'
        console.log(result)
      })
    })
  }

  return {
    init: function () {
      cmd
        .version('Digio v' + _package.version)
        .option('droplets [token]', 'List all droplets', list_droplets)
        .parse(process.argv)
    }
  }

})()

digio.init()

Add option for listing droplets. Remove placeholder code


const hapi = require('hapi');
const { graphqlHapi, graphiqlHapi } = require('graphql-server-hapi');

const rootSchema = require('./graphql/schema');
const dataLoaders = require('./graphql/data');
const config = require('../../config');

const server = new hapi.Server();

server.connection({
  host: config.HOST,
  port: config.PORT
});

server.register({
  register: graphqlHapi,
  options: {
    path: '/graphql',
    graphqlOptions: {
      schema: rootSchema,
      context: { dataLoaders }
    },
    route: {
      cors: true
    }
  }
});

server.register({
  register: graphiqlHapi,
  options: {
    path: '/graphiql',
    graphiqlOptions: {
      endpointURL: '/graphql'
    }
  }
});

server.start(err => {
  if (err) {
    throw err;
  }
  console.log(`Server running at: ${server.info.uri}`);
});

const hapi = require('hapi');
const { graphqlHapi, graphiqlHapi } = require('graphql-server-hapi');

const rootSchema = require('./graphql/schema');
const dataLoaders = require('./graphql/data');
const config = require('../../config');

const server = new hapi.Server();

server.connection({
  host: config.HOST,
  port: config.PORT
});

server.register({
  register: graphqlHapi,
  options: {
    path: '/graphql/',
    graphqlOptions: {
      schema: rootSchema,
      context: { dataLoaders }
    },
    route: {
      cors: true
    }
  }
});

server.register({
  register: graphiqlHapi,
  options: {
    path: '/graphiql/',
    graphiqlOptions: {
      endpointURL: '/graphql/'
    }
  }
});

server.start(err => {
  if (err) {
    throw err;
  }
  console.log(`Server running at: ${server.info.uri}`);
});

Add trailing slash to endpoint url


const router = require('express').Router();

function longRunningResponse(req, res, timeout) {
  let index = 0;
  const parts = 'HTTP/1.1 204 No Content'.split('');

  res.socket.write(parts[index]);
  index += 1;

  const token = setInterval(() => {
    if (index === parts.length) {
      clearInterval(token);
      res.socket.end();
      return;
    }

    res.socket.write(parts[index]);
    index += 1;
  }, timeout);
}

router.get('/empty', (req, res) => {
  res.socket.end();
  res.socket.destroy();
});

router.post('/empty-string', (req, res) => {
  res.socket.end('');
  res.socket.destroy();
});

router.get('/long-running/5', (req, res) => {
  longRunningResponse(req, res, 5000);
});

router.get('/long-running/30', (req, res) => {
  longRunningResponse(req, res, 30000);
});

router.get('/malformed', (req, res) => {
  res.socket.end('foo bar');
  res.socket.destroy();
});

router.post('/malformed', (req, res) => {
  res.socket.end('foo bar');
  res.socket.destroy();
});

router.get('/none', () => {});

module.exports = router;

const router = require('express').Router();

function longRunningResponse(req, res, timeout) {
  let index = 0;
  const parts = 'HTTP/1.1 204 No Content'.split('');

  res.socket.write(parts[index]);
  index += 1;

  res.socket.on('data', (data) => {
    res.socket.write(data);
  });

  const token = setInterval(() => {
    if (index === parts.length) {
      clearInterval(token);
      res.socket.end();
      return;
    }

    res.socket.write(parts[index]);
    index += 1;
  }, timeout);
}

router.get('/empty', (req, res) => {
  res.socket.end();
  res.socket.destroy();
});

router.post('/empty-string', (req, res) => {
  res.socket.end('');
  res.socket.destroy();
});

router.get('/long-running/5', (req, res) => {
  longRunningResponse(req, res, 5000);
});

router.get('/long-running/30', (req, res) => {
  longRunningResponse(req, res, 30000);
});

router.get('/malformed', (req, res) => {
  res.socket.end('foo bar');
  res.socket.destroy();
});

router.post('/malformed', (req, res) => {
  res.socket.end('foo bar');
  res.socket.destroy();
});

router.get('/none', () => {});

module.exports = router;

Fix long running response (server side)


// Load optional local-config file

"use strict"
/* eslint-env node */
/* jslint node: true */

const log = require("./log")
const configDefault = require("./configDefault")

const argv = require("yargs").argv
console.log("argv", argv)

let localConfig = {}

try {
    log("info", "Loading config file")
    if (!argv.config) {
        localConfig = require("../../local-config")
    } else {
        localConfig = require("../../" + argv.config)
    }
} catch (e) {
    if (e.code === "MODULE_NOT_FOUND") {
        log("info", "No config file found -- using defaults")
    } else {
        log("error", "Problem when loading config file:", e)
        throw e
    }
}

const config = Object.assign({}, configDefault, localConfig)

module.exports = {
    config
}

// Load optional local-config file

"use strict"
/* eslint-env node */
/* jslint node: true */

const log = require("./log")
const configDefault = require("./configDefault")

const yargs = require("yargs")

let localConfig = {}

const argv = yargs.option({
    config: {
        describe: "use different config file then config-local.js"
    }
}).help().argv

console.log("yargs.argv", argv)

try {
    log("info", "Loading config file")
    if (!argv.config) {
        localConfig = require("../../local-config")
    } else {
        localConfig = require("../../" + argv.config)
    }
} catch (e) {
    if (e.code === "MODULE_NOT_FOUND") {
        log("info", "No config file found, so using defaults")
    } else {
        log("error", "Problem when loading config file:", e)
        throw e
    }
}

const config = Object.assign({}, configDefault, localConfig)

module.exports = {
    config
}

Improve comannd line help for config option


if (process.env.NODE_ENV === 'production' && process.env.MOCHIFY !== 'true') {
	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

	ga('create', 'UA-49350923-3', 'auto');
	ga('send', 'pageview');
} else {
	// Dummy ga function
	window.ga = () => {};
}

Add dummy ga function for development environment


/**
 * isUndefined
 * Checks if a value is undefined or not.
 *
 * @name isUndefined
 * @function
 * @param {Anything} input The input value.
 * @returns {Boolean} `true`, if the input is `undefined`, `false` otherwise.
 */
module.exports = function isUndefined(input) {
    return input === undefined;
};

/**
 * isUndefined
 * Checks if a value is undefined or not.
 *
 * @name isUndefined
 * @function
 * @param {Anything} input The input value.
 * @returns {Boolean} `true`, if the input is `undefined`, `false` otherwise.
 */
module.exports = function isUndefined(input) {
    return typeof input === 'undefined';
};

Remove direct comparison against undefined.


chrome.contextMenus.create(
    {
        "title": "Define \"%s\"",
        "contexts":["selection"],
        "onclick": function(info, tab){
            chrome.tabs.create(
                {url: "http://www.google.com/search?q=define" + encodeURIComponent(" " + info.selectionText).replace(/%20/g, "+")
            });
        }
});

chrome.contextMenus.create(
    {
        "title": "Define \"%s\"",
        "contexts":["selection"],
        "onclick": function(info, tab){
            chrome.tabs.create(
                {url: "http://www.google.com/search?q=define" + encodeURIComponent(" " + info.selectionText).replace(/%20/g, "+"),
                index: tab.index + 1,
                openerTabId: tab.id
            });
        }
});

Make the tab open directly to the right of the tab the lookup was started from, instead of at the end of all the window's tabs. Also, make the created tab have set an opener tab for it (affecting what tab gets focus when you close a tab).


var NodeGit = require("../");
var Signature = NodeGit.Signature;

/**
 * Standard string representation of an author.
 *
 * @return {string} Representation of the author.
 */
Signature.prototype.toString = function() {
  return this.name().toString() + " <" + this.email().toString() + ">";
};

var NodeGit = require("../");
var Signature = NodeGit.Signature;

const toPaddedDoubleDigitString = (number) => {
  if (number < 10) {
    return `0${number}`;
  }

  return `${number}`;
};

/**
 * Standard string representation of an author.
 * @param {Boolean} withTime Whether or not to include timestamp
 * @return {String} Representation of the author.
 */
Signature.prototype.toString = function(withTime) {
  const name = this.name().toString();
  const email = this.email().toString();

  let stringifiedSignature = `${name} <${email}>`;

  if (!withTime) {
    return stringifiedSignature;
  }

  const when = this.when();
  const offset = when.offset();
  const offsetMagnitude = Math.abs(offset);
  const time = when.time();

  const sign = (offset < 0 || when.sign() === "-") ? "-" : "+";
  const hours = toPaddedDoubleDigitString(Math.floor(offsetMagnitude / 60));
  const minutes = toPaddedDoubleDigitString(offsetMagnitude % 60);

  stringifiedSignature += ` ${time} ${sign}${hours}${minutes}`;
  return stringifiedSignature;
};

Extend `Signature.toString` to optionally include timestamps


/**
 * jasmine
 * =======
 *
 * Test settings
 *
 * Link: https://github.com/gruntjs/grunt-contrib-jasmine
 */

'use strict';

module.exports = function (grunt) {
  return {
    dist: {
      src: [
        '<%= pkg.config.src %>/scripts/core.js',
        '<%= pkg.config.src %>/scripts/event.js',
        '<%= pkg.config.src %>/scripts/class.js',
        '<%= pkg.config.src %>/scripts/base.js',
        '<%= pkg.config.src %>/scripts/svg.js',
        '<%= pkg.config.src %>/scripts/charts/line.js',
        '<%= pkg.config.src %>/scripts/charts/bar.js',
        '<%= pkg.config.src %>/scripts/charts/pie.js'
      ],
      options: {
        specs: '<%= pkg.config.test %>/spec/**/spec-*.js',
        helpers: '<%= pkg.config.test %>/spec/**/helper-*.js',
        phantomjs: {
          'ignore-ssl-errors': true
        }
      }
    }
  };
};

/**
 * jasmine
 * =======
 *
 * Test settings
 *
 * Link: https://github.com/gruntjs/grunt-contrib-jasmine
 */

'use strict';

module.exports = function (grunt) {
  return {
    dist: {
      src: [
        '<%= pkg.config.src %>/scripts/core.js',
        '<%= pkg.config.src %>/scripts/event.js',
        '<%= pkg.config.src %>/scripts/class.js',
        '<%= pkg.config.src %>/scripts/base.js',
        '<%= pkg.config.src %>/scripts/svg.js',
        '<%= pkg.config.src %>/scripts/charts/line.js',
        '<%= pkg.config.src %>/scripts/charts/bar.js',
        '<%= pkg.config.src %>/scripts/charts/pie.js'
      ],
      options: {
        specs: '<%= pkg.config.test %>/spec/**/spec-*.js',
        helpers: '<%= pkg.config.test %>/spec/**/helper-*.js',
        vendor: [
          'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js'
        ],
        phantomjs: {
          'ignore-ssl-errors': true
        }
      }
    }
  };
};

Include jQuery in Jasmine specs


'use strict';
var path = require('path');
var tape = require('tape');
var app = require('express')();
var request = require('supertest');

require('../')
    .argmentApp(app, {
        appRoot: path.join(__dirname, 'example'),
        assetsDirName: 'assets',
        viewsDirName: 'views'
    });

tape('partial/a', function (test) {
    test.plan(2);
    request(app)
        .get('/a')
        .expect(200)
        .end(function (err, res) {
            test.notOk(err);
            test.equal(res.text.trim(), 'partial aaa');
        });
});

tape('partial/deep', function (test) {
    test.plan(2);
    request(app)
        .get('/deep')
        .expect(200)
        .end(function (err, res) {
            test.notOk(err);
            test.equal(res.text.trim(), 'deep partial');
        });
});

'use strict';
var path = require('path');
var tape = require('tape');
var app = require('express')();
var request = require('supertest');

require('../')
    .argmentApp(app, {
        appRoot: path.join(__dirname, 'example'),
        assetsDirName: 'assets',
        viewsDirName: 'views'
    });

tape('partial/a', function (test) {
    test.plan(2);
    request(app)
        .get('/a')
        .expect(200)
        .end(function (err, res) {
            test.notOk(err);
            test.equal(res.text.trim(), 'partial a');
        });
});

tape('partial/deep', function (test) {
    test.plan(2);
    request(app)
        .get('/deep')
        .expect(200)
        .end(function (err, res) {
            test.notOk(err);
            test.equal(res.text.trim(), 'deep partial');
        });
});

Revert "break test case, test ci"


'use strict';

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

const env = cfenv.getAppEnv();
env.host = env.url.replace(`:${env.port}`, '');

module.exports = {
  contentTypes: {
    contentTypesHome: {
      path: '/content',
      title: 'Content Type ALL Landing Page',
      desc: 'This is the content type ALL landing page.',
    },
    contentTypeDir: path.join(__dirname, '../content-types'),
    contentTypeExt: 'yml',
    viewsDir: path.join(__dirname, '../views/'),
    formTemplateFile: '_content-type-form.html',
  },
  knex: {
    dialect: 'pg',
    connection: {
      host: 'localhost',
      user: 'punchcard',
      database: 'punchcard',
    },
    debug: true,
    acquireConnectionTimeout: 1000,
  },
  env,
  cookies: {
    secure: false,
    secret: process.env.COOKIE_SECRET || 'babka',
  },
};

'use strict';

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

const env = cfenv.getAppEnv();
env.host = env.url.replace(`:${env.port}`, '');

module.exports = {
  contentTypes: {
    contentTypesHome: {
      path: '/content',
      title: 'Content Type ALL Landing Page',
      desc: 'This is the content type ALL landing page.',
    },
    contentTypeDir: path.join(__dirname, '../content-types'),
  },
  knex: {
    dialect: 'pg',
    connection: {
      host: 'localhost',
      user: 'punchcard',
      database: 'punchcard',
    },
    debug: false,
    acquireConnectionTimeout: 1000,
  },
  site: {
    name: 'Punchcard CMS',
  },
  env,
  cookies: {
    secure: false,
    secret: process.env.COOKIE_SECRET || 'babka',
  },
};

Add Site info to Config


var _ = require('underscore'),
    StatementsByFilter = require('./StatementsByFilter'),
    AmountEntryCollection = require('../../AmountEntryCollection'),
    Statement = require('../../Statement');

var StatementsByCategory = function() { };

StatementsByCategory.prototype = {
   /**
    * This converts an AmountEntryCollection into a set of Statements
    * based on what category is stored for the entry.
    *
    * @param entries AmountEntryCollection
    * @param categoryPreference [String]
    * @return StatementCollection
    */
   run: function(entries, categoryPreference) {
      var shouldUsePreference = categoryPreference && categoryPreference.length > 0,
          statements;

      statements = (new StatementsByFilter()).run(entries, function(entry) {
         // Only allow categories that are in the preference to be added
         var category = entry.get('category');
         return shouldUsePreference && _.indexOf(categoryPreference, category) === -1 ? false : category;
      });

      if (shouldUsePreference) {
         var categoriesPresent = statements.pluck('key'),
             categoriesMissing = _.difference(categoryPreference, categoriesPresent);

         // Fill in categories mentioned in categoryPreference
         // but don't have any entries currently
         _.each(categoriesMissing, function(categoryKey) {
            statements.add(new Statement({
               'key': categoryKey,
               'entries': new AmountEntryCollection()
            }));
         });
      }

      return statements;
   }
};

module.exports = StatementsByCategory;

var _ = require('underscore'),
    StatementsByFilter = require('./StatementsByFilter'),
    AmountEntryCollection = require('../../AmountEntryCollection'),
    Statement = require('../../Statement');

/**
 * @param categoryField String - Field to use as the Statment key
 */
var StatementsByCategory = function(categoryField) {
   this.field = categoryField || 'category';
};

StatementsByCategory.prototype = {
   /**
    * This converts an AmountEntryCollection into a set of Statements
    * based on what category is stored for the entry.
    *
    * @param entries AmountEntryCollection
    * @param categoryPreference [String]
    * @return StatementCollection
    */
   run: function(entries, categoryPreference) {
      var self = this,
          shouldUsePreference = categoryPreference && categoryPreference.length > 0,
          statements;

      statements = (new StatementsByFilter()).run(entries, function(entry) {
         // Only allow categories that are in the preference to be added
         var category = entry.get(self.field);
         return shouldUsePreference && _.indexOf(categoryPreference, category) === -1 ? false : category;
      });

      if (shouldUsePreference) {
         var categoriesPresent = statements.pluck('key'),
             categoriesMissing = _.difference(categoryPreference, categoriesPresent);

         // Fill in categories mentioned in categoryPreference
         // but don't have any entries currently
         _.each(categoriesMissing, function(categoryKey) {
            statements.add(new Statement({
               'key': categoryKey,
               'entries': new AmountEntryCollection()
            }));
         });
      }

      return statements;
   }
};

module.exports = StatementsByCategory;

Allow customization of grouping field


//Invitations.js: Client for the Zendesk NPS API.

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

const Invitations = (exports.Invitations = function(options) {
  this.jsonAPINames = ['agent activity'];
  Client.call(this, options);
});

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

// ######################################################## Invitations
// ====================================== Showing Invitations
Invitations.prototype.list = function({ surveyId }, cb) {
  this.request('GET', ['nps', 'surveys', surveyId, 'invitations'], cb);
};

// ====================================== Showing Invitation by ID
Invitations.prototype.show = function({ surveyId, invitationId }, cb) {
  this.request(
    'GET',
    ['nps', 'surveys', surveyId, 'invitations', invitationId],
    cb
  );
};

// ====================================== Create Invitation
Invitations.prototype.create = function({ surveyId, data }, cb) {
  this.request('POST', ['nps', 'surveys', surveyId, 'invitations'], data, cb);
};

//Invitations.js: Client for the Zendesk NPS API.

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

const Invitations = (exports.Invitations = function(options) {
  this.jsonAPINames = ['agent activity'];
  Client.call(this, options);
});

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

// ######################################################## Invitations
// ====================================== Showing Invitations
Invitations.prototype.list = function({ surveyId }, cb) {
  this.request('GET', ['nps', 'surveys', surveyId, 'invitations'], cb);
};

// ====================================== Showing Invitation by ID
Invitations.prototype.show = function({ surveyId, invitationId }, cb) {
  this.request(
    'GET',
    ['nps', 'surveys', surveyId, 'invitations', invitationId],
    cb
  );
};

/**
 * Create invitation https://developer.zendesk.com/rest_api/docs/nps-api/nps_invitations
 *
 * @param {object} params
 * @param {string} params.surveyId
 * @param {{
 *    invitation: {
 *      recipients: {
 *        name: string,
 *        email: string,
 *        language: string
 *      }[]
 *    }
 *  }} params.data
 * @param {*} cb
 */
Invitations.prototype.create = function({ surveyId, data }, cb) {
  this.request('POST', ['nps', 'surveys', surveyId, 'invitations'], data, cb);
};

Add documentation for create invitation


'use strict';

var stream = require('stream');

function hello(restbase, req) {
    var body = new stream.PassThrough();
    body.end('hello');
    return {
        status: 200,
        headers: {
            'content-type': 'text/html',
        },
        body: body
    };
}

function buffer(restbase, req) {
    var body = new stream.PassThrough();
    body.end(new Buffer('hello'));
    return {
        status: 200,
        headers: {
            'content-type': 'text/html',
        },
        body: body
    };
}

function chunks(restbase, req) {
    var body = new stream.PassThrough();
    for (var i = 0; i < 100; i++) {
        body.write(i.toString());
    }
    body.end();
    return {
        status: 200,
        headers: {
            'content-type': 'text/html',
        },
        body: body
    };
}

module.exports = function(options) {
    return {
        spec: {
            paths: {
                '/hello': {
                    get: {
                        operationId: 'hello'
                    }
                },
                '/buffer': {
                    get: {
                        operationId: 'buffer'
                    }
                },
                '/chunks': {
                    get: {
                        operationId: 'chunks'
                    }
                }
            }
        },
        operations: {
            hello: hello,
            buffer: buffer,
            chunks: chunks,
        }
    };
};

'use strict';

var stream = require('stream');

function hello(restbase, req) {
    var body = new stream.PassThrough();
    body.end('hello');
    return {
        status: 200,
        headers: {
            'content-type': 'text/html',
        },
        body: body
    };
}

function buffer(restbase, req) {
    var body = new stream.PassThrough();
    body.write(new Buffer('hel'));
    // Delay the final write to test async production.
    setTimeout(function() {
        body.end(new Buffer('lo'));
    }, 500);

    return {
        status: 200,
        headers: {
            'content-type': 'text/html',
        },
        body: body
    };
}

function chunks(restbase, req) {
    var body = new stream.PassThrough();
    for (var i = 0; i < 100; i++) {
        body.write(i.toString());
    }
    body.end();
    return {
        status: 200,
        headers: {
            'content-type': 'text/html',
        },
        body: body
    };
}

module.exports = function(options) {
    return {
        spec: {
            paths: {
                '/hello': {
                    get: {
                        operationId: 'hello'
                    }
                },
                '/buffer': {
                    get: {
                        operationId: 'buffer'
                    }
                },
                '/chunks': {
                    get: {
                        operationId: 'chunks'
                    }
                }
            }
        },
        operations: {
            hello: hello,
            buffer: buffer,
            chunks: chunks,
        }
    };
};

Make the buffer test stream write async


/**
 * Sanitize values
 *
 * @param  {String | Array<string>} value     The value to be sanitized
 * @param  {Object}                 sanitize  A sanitization type from sanitizer
 * @return {String | Array<string>}
 */
const valueSanitizer = (key, value, sanitize) => {
  switch (key) {
    // case 'image_link': TODO: Check if a sanitized 'image_link' field get here as it should
    case 'images':
    case 'categories':
      return sanitize.arrays(value);
    case 'id': {
      const sanitizeTexts = sanitize.__texts(value);
      const sanitizeUnderscores = sanitize.underscore(sanitizeTexts);
      return sanitizeUnderscores;
    }
    case 'installment':
      return sanitize.installment(value);
    case 'sku':
      return sanitize.underscore(value);
    default:
  }
  return value;
};

module.exports = valueSanitizer;

/**
 * Sanitize values
 *
 * @param  {String | Array<string>} value     The value to be sanitized
 * @param  {Object}                 sanitize  A sanitization type from sanitizer
 * @return {String | Array<string>}
 */
const valueSanitizer = (key, value, sanitize) => {
  switch (key) {
    case 'image_link':
    case 'images':
    case 'categories':
      return sanitize.arrays(value);
    case 'id': {
      const sanitizeTexts = sanitize.__texts(value);
      const sanitizeUnderscores = sanitize.underscore(sanitizeTexts);
      return sanitizeUnderscores;
    }
    case 'price':
      return sanitize.__texts(value);
    case 'installment':
      return sanitize.installment(value);
    case 'sku':
      return sanitize.underscore(value);
    default:
  }
  return value;
};

module.exports = valueSanitizer;

Add __text satitization to price and image_link


import express from 'express';
import bodyParser from 'body-parser';
import path from 'path';
import handleReactRoutes from './reactRoutes';
import dbRoutes from './dbRoutes';
import auth0Auth from './auth0Auth';
import restrictRoutes from './restrictRoutes';

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(express.static(path.join(__dirname, '../../dist/public')));
auth0Auth(app);
restrictRoutes(app);
dbRoutes(app);
app.use('*', handleReactRoutes);

app.get('*', (req, res) => {
  res.status(404).end();
});

export default app;

import express from 'express';
import bodyParser from 'body-parser';
import path from 'path';
import handleReactRoutes from './reactRoutes';
import dbRoutes from './dbRoutes';
import auth0Auth from './auth0Auth';
import restrictRoutes from './restrictRoutes';

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(express.static(path.join(__dirname, '../../dist/public'), { maxage: '31536000000' }));
auth0Auth(app);
restrictRoutes(app);
dbRoutes(app);
app.use('*', handleReactRoutes);

app.get('*', (req, res) => {
  res.status(404).end();
});

export default app;

Set default Cache Control Header max-age > 0


var path = require('path');
var ejs = require('ejs');
var fs = require('hexo-fs');

var layout = 'layout.ejs';
var bodyTag = '</body>';
var mathjaxScript = fs.readFileSync(path.join(__dirname, 'mathjax.html'));

hexo.extend.renderer.register('ejs', 'html', function(data, options, callback) {
    var path = options.filename = data.path;
    var content = data.text;
    if (layout === path.substring(path.length - layout.length))
        content = content.replace(bodyTag, mathjaxScript + '\n' + bodyTag);
    callback(null, ejs.render(content, options));
});

var path = require('path');
var ejs = require('ejs');
var Hexo = require('hexo');
var hexo = new Hexo(process.cwd(), {});
var fs = require('hexo-fs');

var layout = 'layout.ejs';
var bodyTag = '</body>';
var mathjaxScript = fs.readFileSync(path.join(__dirname, 'mathjax.html'));

hexo.extend.renderer.register('ejs', 'html', function(data, options, callback) {
    var path = options.filename = data.path;
    var content = data.text;
    if (layout === path.substring(path.length - layout.length))
        content = content.replace(bodyTag, mathjaxScript + '\n' + bodyTag);
    callback(null, ejs.render(content, options));
});

Add hexo Require for hexo3


/*
 * client.js: Base client from which all AWS clients inherit from
 *
 * (C) 2012 Nodejitsu Inc.
 *
 */

var utile = require('utile'),
    request = require('request'),
    base = require('../core/base');

var Client = exports.Client = function (options) {
  base.Client.call(this, options);

  // Allow overriding serversUrl in child classes
  this.provider   = 'amazon';
  this.version = (options || {}).version || '2012-04-01';
  this.serversUrl = (options || {}).serversUrl
    || this.serversUrl
    || 'ec2.amazonaws.com';

  if (!this.before) {
    this.before = [];
  }
};

utile.inherits(Client, base.Client);

Client.prototype._toArray = function toArray(obj) {
  return Array.isArray(obj) ? obj : [obj];
};

Client.prototype.failCodes = {
  400: 'Bad Request',
  401: 'Unauthorized',
  403: 'Resize not allowed',
  404: 'Item not found',
  409: 'Build in progress',
  413: 'Over Limit',
  415: 'Bad Media Type',
  500: 'Fault',
  503: 'Service Unavailable'
};

Client.prototype.successCodes = {
  200: 'OK',
  201: 'Created',
  202: 'Accepted',
  203: 'Non-authoritative information',
  204: 'No content'
};

/*
 * client.js: Base client from which all AWS clients inherit from
 *
 * (C) 2012 Nodejitsu Inc.
 *
 */

var utile = require('utile'),
    request = require('request'),
    base = require('../core/base');

var Client = exports.Client = function (options) {
  base.Client.call(this, options);

  // Allow overriding serversUrl in child classes
  this.provider   = 'amazon';
  this.version = (options || {}).version || '2012-04-01';
  this.serversUrl = (options || {}).serversUrl
    || this.serversUrl
    || 'ec2.amazonaws.com';

  if (!this.before) {
    this.before = [];
  }
};

utile.inherits(Client, base.Client);

Client.prototype._toArray = function toArray(obj) {
  if (typeof obj === 'undefined') {
    return [];
  }

  return Array.isArray(obj) ? obj : [obj];
};

Client.prototype.failCodes = {
  400: 'Bad Request',
  401: 'Unauthorized',
  403: 'Resize not allowed',
  404: 'Item not found',
  409: 'Build in progress',
  413: 'Over Limit',
  415: 'Bad Media Type',
  500: 'Fault',
  503: 'Service Unavailable'
};

Client.prototype.successCodes = {
  200: 'OK',
  201: 'Created',
  202: 'Accepted',
  203: 'Non-authoritative information',
  204: 'No content'
};

Return empty array when passed `undefined` or `null` in amazon.Client.prototype._toArray


'use strict';

var CloudFoundry = require('cf-nodejs-client'),
    Promise = require('bluebird'),
    util = require('util'),
    Spinner = require('cli-spinner').Spinner,
    spinner = new Spinner('%s'),
    cf = new CloudFoundry.CloudFoundry(),
    routes = new CloudFoundry.Routes(),
    manifest = require('./lib/manifest'),
    config = require('./lib/config'),
    apps = new CloudFoundry.Apps();

module.exports = function (options) {
  spinner.start();

  config(options).then(function (config) {
    cf.setEndPoint(config.endpoint);
    routes.setEndPoint(config.endpoint);
    apps.setEndPoint(config.endpoint);

    return cf.getInfo().then(function (result) {
      return cf.login(result.authorization_endpoint,
        config.username,
        config.password);
    }).then(function (auth) {
      return apps.getApps(auth.token_type, auth.access_token).then(function (result) {
        var guid;

        // ha--node-starter
        result.resources.forEach(function (item) {
          if (item.entity.name === config.name) {
            guid = item.metadata.guid;
          }
        });

        if (guid) {
          return manifest(auth, guid).then(function (settings) {
            spinner.stop();
            return settings;
          });
        }
      });
    })
  }).catch(function (error) {
    spinner.stop(true);
    console.error('Error: ' + error);
    process.exit(1);
  });
}

'use strict';

var CloudFoundry = require('cf-nodejs-client'),
    Promise = require('bluebird'),
    util = require('util'),
    Spinner = require('cli-spinner').Spinner,
    spinner = new Spinner('%s'),
    cf = new CloudFoundry.CloudFoundry(),
    routes = new CloudFoundry.Routes(),
    manifest = require('./lib/manifest'),
    config = require('./lib/config'),
    apps = new CloudFoundry.Apps();

module.exports = function (options) {
  spinner.start();

  config(options).then(function (config) {
    cf.setEndPoint(config.endpoint);
    routes.setEndPoint(config.endpoint);
    apps.setEndPoint(config.endpoint);

    return cf.getInfo().then(function (result) {
      return cf.login(result.authorization_endpoint,
        config.username,
        config.password);
    }).then(function (auth) {
      return apps.getApps(auth.token_type, auth.access_token).then(function (result) {
        var guid;

        result.resources.forEach(function (item) {
	  if (item.entity.name === config.app) {
            guid = item.metadata.guid;
          }
        });

        if (guid) {
          return manifest(auth, guid).then(function (settings) {
            spinner.stop();
            return settings;
          });
        }
      });
    })
  }).catch(function (error) {
    spinner.stop(true);
    console.error('Error: ' + error);
    process.exit(1);
  });
}

Change config property to app from name


var Promise = require('bluebird');
var deepExtend = require('deep-extend');

var AnalyticsContext = require('./AnalyticsContext');
var AnalyticsEventModel = require('./AnalyticsEventModel');
var AnalyticsDispatcher = require('./AnalyticsDispatcher');

var createEventModel = function(eventName, context){
  var eventModel = new AnalyticsEventModel();
  eventModel.Name = eventName;
  eventModel.Scope = context.Scopes.join("_");

  deepExtend(eventModel.ExtraData, context.ExtraData);
  deepExtend(eventModel.MetaData, context.MetaData);
  return context.Filters.reduce(function(cur, next) {
    return cur.then(
      function(){
        return next(eventModel);
      });
    }, Promise.resolve())
    .then(function() {
      return eventModel;
    });
};

module.exports = function(eventModelWriter, rootContext) {
  return new AnalyticsDispatcher(function(name, context)
  {
    return Promise.resolve()
    .then(function () {
      return createEventModel(name,context);
    })
    .then(function (eventModel){
      return eventModelWriter(eventModel);
    });
  }, rootContext);
};

var Promise = require('bluebird');
var deepExtend = require('deep-extend');

var AnalyticsContext = require('./AnalyticsContext');
var AnalyticsEventModel = require('./AnalyticsEventModel');
var AnalyticsDispatcher = require('./AnalyticsDispatcher');

var createEventModel = function(eventName, context){
  var eventModel = new AnalyticsEventModel();
  eventModel.Name = eventName;
  eventModel.Scope = context.Scopes.join("_");
  deepExtend(eventModel.ExtraData, context.ExtraData);
  deepExtend(eventModel.MetaData, context.MetaData);
  deepExtend(eventModel.Identities, context.Identities);
  return context.Filters.reduce(function(cur, next) {
    return cur.then(
      function(){
        return next(eventModel);
      });
    }, Promise.resolve())
    .then(function() {
      return eventModel;
    });
};

module.exports = function(eventModelWriter, rootContext) {
  return new AnalyticsDispatcher(function(name, context)
  {
    return Promise.resolve()
    .then(function () {
      return createEventModel(name,context);
    })
    .then(function (eventModel){
      return eventModelWriter(eventModel);
    });
  }, rootContext);
};

Copy identities from context to event model


import * as THREE from 'three';

import Material from '../helpers/material';
import MeshHelper from '../helpers/meshHelper';
import Helpers from '../../utils/helpers';
import Config from '../../data/config';

// Loads in a single object from the config file
export default class Model {
  constructor(scene, loader) {
    this.scene = scene;

    // Manager is passed in to loader to determine when loading done in main
    this.loader = loader;
    this.obj = null;
  }

  load() {
    // Load model with ObjectLoader
    this.loader.load(Config.model.path, obj => {
      obj.traverse((child) => {
        if (child instanceof THREE.Mesh) {
          // Create material for mesh and set its map to texture by name from preloaded textures
          // const material = new Material(0xffffff).standard;
          // child.material = material;

          // Set to cast and receive shadow if enabled
          if (Config.shadow.enabled) {
            child.receiveShadow = true;
            child.castShadow = true;
          }
        }
      });

      // Set prop to obj
      this.obj = obj;

      obj.name = 'dummyHead';

      obj.position.y = 1; // necessary for raycasting onto the zone shape
      obj.rotation.y += Math.PI;
      obj.scale.multiplyScalar(Config.model.scale);

      this.scene.add(obj);
    });
  }
}

import * as THREE from 'three';

import Material from '../helpers/material';
import MeshHelper from '../helpers/meshHelper';
import Helpers from '../../utils/helpers';
import Config from '../../data/config';

// Loads in a single object from the config file
export default class Model {
  constructor(scene, loader) {
    this.scene = scene;

    // Manager is passed in to loader to determine when loading done in main
    this.loader = loader;
    this.obj = null;
  }

  load() {
    // Load model with ObjectLoader
    this.loader.load(Config.model.path, obj => {
      obj.traverse((child) => {
        if (child instanceof THREE.Mesh) {
          // Create material for mesh and set its map to texture by name from preloaded textures
          const material = new Material(0xffffff).basic;
          child.material = material;

          // Set to cast and receive shadow if enabled
          if (Config.shadow.enabled) {
            child.receiveShadow = true;
            child.castShadow = true;
          }
        }
      });

      // Set prop to obj
      this.obj = obj;

      obj.name = 'dummyHead';

      obj.position.y = 1; // necessary for raycasting onto the zone shape
      obj.rotation.y += Math.PI;
      obj.scale.multiplyScalar(Config.model.scale);

      this.scene.add(obj);
    });
  }
}

Fix head color -- add material


/**
 *  Imports svg into items with groups
 *  Stetson Alpha - Paper.js
 *
 */

var ImportSVG = function()
{
	//initialize
	function initialize()
	{

	};

	/**
	 *
	 * Takes the svg dom obj and parses the data
	 * to create a layer with groups (if needed) with
	 * items inside. Should support nested groups.
	 *
	 * takes in a svg object (xml dom)
	 * returns Paper.js Layer
	 */
    this.importSVG = function(svg)
    {
    	return layer;
    };

	/**
	 * Creates a Paper.js Group by parsing
	 * a specific svg g node
	 *
	 * takes in a svg object (xml dom)
	 * returns Paper.js Group
	 */
    function importGroup(svg)
    {
    	return group;
    };

	/**
	 * Creates a Paper.js Path by parsing
	 * a specific svg node (rect, path, circle, polygon, etc)
	 * and creating the right path object based on the svg type.
	 *
	 * takes in a svg object (xml dom)
	 * returns Paper.js Group
	 */
    function importPath(svg)
    {
    	return path;
    };

    initialize(); // calls the init function after class is loaded
};

Convert tabs to 4 spaces