/**
 * An example specification for the example module
 * Loads the module and runs the test suite
 */
define(['modules/module'], function (module) {
	'use strict';

	// Test suit INIT
	describe('INIT', function () {

		it('is available', function () {
			expect(module).not.toBe(null);
		});

		it('fires event on init', function () {
			var eventCalled;

			$(document).on(module.getEventName(), function () {
				eventCalled = true;
			});

			module.init();

			expect(eventCalled).toBeTruthy();
		});
	});
});

/**
 * An example specification for the example module
 * Loads the module and runs the test suite
 */
define(['modules/module'], function (module) {
	'use strict';

	// Test suite INIT
	describe('INIT', function () {

		it('is available', function () {
			expect(module).not.toBe(null);
		});

		it('fires event on init', function () {
			var eventCalled;

			$(document).on(module.getEventName(), function () {
				eventCalled = true;
			});

			module.init();

			expect(eventCalled).toBeTruthy();
		});
	});
});

Fix typo in example test spec


module.exports = {
	extends: [
		'@nextcloud',
	],
	rules: {
		'jsdoc/require-param-description': ['off'],
		'jsdoc/require-param-type': ['off'],
		'jsdoc/check-param-names': ['off'],
		'jsdoc/no-undefined-types': ['off'],
		'jsdoc/require-property-description' : ['off']
	},
}

module.exports = {
	root: true,
	extends: [
		'@nextcloud',
	],
	rules: {
		'jsdoc/require-param-description': ['off'],
		'jsdoc/require-param-type': ['off'],
		'jsdoc/check-param-names': ['off'],
		'jsdoc/no-undefined-types': ['off'],
		'jsdoc/require-property-description' : ['off']
	},
}

Make eslint stop reading configs at the root


$(document).ready(function () {

    $(".source").draggable({
        axis: "y",
        containment: "parent"
    });

    // set an interval for creating helium elements
    setInterval(function () {

        // create helium element
        var $helium = $("

")
                            .css("top", $(".source").position().top + 6);

        // append the helium to screen
        $(".screen").append($helium);

        // and animate it
        $(".helium").johnnysPath({d: 1000}, [{x: 600}]);

    }, 700);
});

$(document).ready(function () {

    $(".source").draggable({
        axis: "y",
        containment: "parent"
    });

    // set an interval for creating helium elements
    setInterval(function () {

        // create helium element
        var $helium = $("

")
                            .css("top", $(".source").position().top + 6);

        // append the helium to screen
        $(".screen").append($helium);

        // and animate it
        $(".helium").johnnysPath({d: 1000}, [{x: 600}], function () {
            $(this).remove();
        });

    }, 700);
});

Remove the elements after animated


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

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

Add react rules to eslint file


module.exports = {
  extends: "airbnb",

  env: {
    browser: true,
    jest: true,
  },

  rules: {
    "react/jsx-filename-extension": [
      1,
      {
        extensions: [
          ".js",
          ".jsx",
        ],
      },
    ],
    // Doesn't allow nested input inside label
    "jsx-a11y/label-has-for": [0],
    // Disabled until eslint-plugin-import gets proper support for webpack externals
    // https://github.com/benmosher/eslint-plugin-import/issues/479
    // https://github.com/benmosher/eslint-plugin-import/issues/605
    "import/no-extraneous-dependencies": 0,
    "import/extensions": 0,
  },

  settings: {
    "import/resolver": {
      webpack: {
        config: "webpack.config.js",
      },
    },
  },
};

module.exports = {
  extends: "airbnb",

  env: {
    browser: true,
    jest: true,
  },

  rules: {
    "react/jsx-filename-extension": [
      1,
      {
        extensions: [
          ".js",
          ".jsx",
        ],
      },
    ],
    // Doesn't allow nested input inside label
    "jsx-a11y/label-has-for": [0],
    // Disabled until eslint-plugin-import gets proper support for webpack externals
    // https://github.com/benmosher/eslint-plugin-import/issues/479
    // https://github.com/benmosher/eslint-plugin-import/issues/605
    "import/no-extraneous-dependencies": 0,
    "import/extensions": 0,
    // Allows us to reference mongodb '_id' field without whitelisting each line.
    "no-underscore-dangle": [2, { allow: ['_id'] }],
  },

  settings: {
    "import/resolver": {
      webpack: {
        config: "webpack.config.js",
      },
    },
  },
};

Make ESLint allow _id identifier for mongodb id field


import { CompositeModel } from '../../kit'

export default class MetadataModel extends CompositeModel {
  constructor (api) {
    super(api)

    this.setProperties(
      { name: 'article', model: api._getModelById('article-record') },
      { name: 'authors', model: api.getCollectionForType('author') },
      { name: 'translations', model: api.getCollectionForType('translatable') },
      { name: 'editors', model: api.getCollectionForType('editor') },
      { name: 'groups', model: api.getCollectionForType('group') },
      { name: 'organisations', model: api.getCollectionForType('organisation') },
      { name: 'awards', model: api.getCollectionForType('award') },
      { name: 'figures', model: api.getCollectionForType('figure') },
      { name: 'footnotes', model: api.getCollectionForType('footnote') },
      { name: 'references', model: api.getCollectionForType('reference') },
      { name: 'keywords', model: api.getCollectionForType('keyword') },
      { name: 'subjects', model: api.getCollectionForType('subject') }
    )
  }

  get type () { return 'metadata-matter' }
}

import { CompositeModel } from '../../kit'

export default class MetadataModel extends CompositeModel {
  constructor (api) {
    super(api)

    this.setProperties(
      { name: 'authors', model: api.getCollectionForType('author') },
      { name: 'editors', model: api.getCollectionForType('editor') },
      { name: 'groups', model: api.getCollectionForType('group') },
      { name: 'organisations', model: api.getCollectionForType('organisation') },
      { name: 'awards', model: api.getCollectionForType('award') },
      // { name: 'footnotes', model: api.getCollectionForType('footnote') },
      { name: 'references', model: api.getCollectionForType('reference') },
      { name: 'keywords', model: api.getCollectionForType('keyword') },
      { name: 'subjects', model: api.getCollectionForType('subject') },
      { name: 'translations', model: api.getCollectionForType('translatable') },
      { name: 'article', model: api._getModelById('article-record') },
      { name: 'figures', model: api.getCollectionForType('figure') }
    )
  }

  get type () { return 'metadata-matter' }
}

Change the order of sections.


'use strict';

// Load modules

var Path = require('path');
var HeapDump = require('heapdump');
var Hoek = require('hoek');
var Utils = require('./utils');

// Declare internals

var internals = {
    initialized: false,
    defaults: {
        logPath: Path.join(__dirname, '..', 'poop.log'),
        writeStreamOptions: { flags: 'w' }
    }
};

module.exports.register = function (server, options, next) {

    var settings = Hoek.applyToDefaults(internals.defaults, options || {});

    if (internals.initialized) {
        return next();
    }

    internals.initialized = true;

    process.once('uncaughtException', function (err) {

        HeapDump.writeSnapshot();
        Utils.log(err, {
            logPath: settings.logPath,
            writeStreamOptions: settings.writeStreamOptions
        }, function () {

            process.exit(1);
        });
    });

    process.on('SIGUSR1', function () {

        HeapDump.writeSnapshot();
    });

    return next();
};

module.exports.register.attributes = {
    pkg: require('../package.json')
};

'use strict';

// Load modules

var Path = require('path');
var HeapDump = require('heapdump');
var Hoek = require('hoek');
var Utils = require('./utils');

// Declare internals

var internals = {
    initialized: false,
    defaults: {
        logPath: Path.join(Path.dirname(process.mainModule.filename), 'poop.log'),
        heapdumpFolder: Path.join(Path.dirname(process.mainModule.filename)),
        writeStreamOptions: { flags: 'w' }
    }
};

module.exports.register = function (server, options, next) {

    var settings = Hoek.applyToDefaults(internals.defaults, options || {});

    if (internals.initialized) {
        return next();
    }

    internals.initialized = true;

    process.once('uncaughtException', function (err) {

        HeapDump.writeSnapshot(Path.join(settings.heapdumpFolder, Date.now() + '.heapsnapshot'));
        Utils.log(err, {
            logPath: settings.logPath,
            writeStreamOptions: settings.writeStreamOptions
        }, function () {

            process.exit(1);
        });
    });

    process.on('SIGUSR1', function () {

        HeapDump.writeSnapshot(Path.join(settings.heapdumpFolder, Date.now() + '.heapsnapshot'));
    });

    return next();
};

module.exports.register.attributes = {
    pkg: require('../package.json')
};

Add setting for heapdump folder and change default folder to the app folder (instead of plugin)


'use strict'

$(document).ready(function(){
  $('#lease_duration_custom').hide();
  $('#furnished_details').hide();

  $("#id_lease_duration").change(function() {
    let lease_duration = $(this).val();
    if (lease_duration == "other") {
      $("#lease_duration_custom").show("fast");
    } else {
      $("#lease_duration_custom").hide("fast");
    }
  })

  $("#id_furnished").change(function() {
    let furnished = $(this).val();
    if (furnished == "lightly_furnished" || furnished == "fully_furnished") {
      $("#furnished_details").show("fast");
    } else {
      $("#furnished_details").hide("fast");
    }
  })
})

'use strict'

$(document).ready(function(){
  if ($('#id_furnished').val() == 'lightly_furnished' || $('#id_lease_duration').val() == 'fully_furnished') {
    $('#furnished_details').show('fast');
  }

  if ($('#id_lease_duration').val() != 'other') {
    $('#lease_duration_custom').hide('fast');
  }

  $('#id_lease_duration').change(function() {
    let lease_duration = $(this).val();
    if (lease_duration == 'other') {
      $('#lease_duration_custom').show('fast');
    } else {
      $('#lease_duration_custom').hide('fast');
      $('#id_lease_duration_custom').val("");
    }
  })

  $('#id_furnished').change(function() {
    let furnished = $(this).val();
    if (furnished == 'lightly_furnished' || furnished == 'fully_furnished') {
      $('#furnished_details').show('fast');
    } else {
      $('#furnished_details').hide('fast');
      $('#id_furnished_details').val("");
    }
  })
})

Update javascript to clear input field after hide


/*! React Starter Kit | MIT License | http://www.reactstarterkit.com/ */

import React, { PropTypes } from 'react';
import styles from './PostPage.css';
import withStyles from '../../decorators/withStyles';
import Link from '../../utils/Link';
import marked from 'marked';

@withStyles(styles)
class PostPage {

  static propTypes = {
    post: PropTypes.object.isRequired
  };

  static contextTypes = {
    onSetTitle: PropTypes.func.isRequired
  };

  render() {
    this.context.onSetTitle(this.props.post.title);
    const nextPost = this.props.post.id % 2 + 1;
    return (

{this.props.post.title}

          post {nextPost}

    );
  }

}

export default PostPage;

/*! React Starter Kit | MIT License | http://www.reactstarterkit.com/ */

import React, { PropTypes } from 'react';
import styles from './PostPage.css';
import withStyles from '../../decorators/withStyles';
import Link from '../Link';
import marked from 'marked';

@withStyles(styles)
class PostPage {

  static propTypes = {
    post: PropTypes.object.isRequired
  };

  static contextTypes = {
    onSetTitle: PropTypes.func.isRequired
  };

  render() {
    this.context.onSetTitle(this.props.post.title);
    const nextPost = this.props.post.id % 2 + 1;
    return (

{this.props.post.title}

          post {nextPost}

    );
  }

}

export default PostPage;

Use link as real component


"use strict";

require(['jquery', 'messages', 'jquery.cookie', 'jquery.jeditable'], function($, messages) {
    if (!$.ajaxSettings.headers)
        $.ajaxSettings.headers = {};

    $.ajaxSettings.headers['X-CSRFToken'] = $.cookie('csrftoken');

    $.fn.csrfEditable = function(url) {
        var self = this;

        function error(xhr, status, error) {
            if (status == 403) {
                self.css("background-color", "#fcc");
            }
        }

        self.editable(url, { ajaxoptions: { error: error },
                             data: function(string, settings) {
                                 return $.trim(string, settings);
                             }});
        self.addClass("editable");
    };

    $(document).ready(function() {
        // Make the login link activatable.
        $("#login_link").click(function(event) {
            $(this).toggleClass('selected');
            $("#login_popup_form").slideToggle();
            return false;
        });

        $('#submit-ajax').click(function() {
            var $elem = $(this);

            var df = $.ajax({ url: $elem.data('url'),
                              type: 'POST' });
            df.done(function() {
                messages.addInfo("Your extension has been locked.").hide().slideDown();
                $elem.attr('disabled', true);
                $('h3, p.description').csrfEditable('disable').removeClass('editable');
            });

            return false;
        });

        if (window._SW)
            try {
                window._SW();
            } catch(e) {
                console.error(e);
            }
    });
});

"use strict";

require(['jquery', 'messages', 'jquery.cookie', 'jquery.jeditable'], function($, messages) {
    if (!$.ajaxSettings.headers)
        $.ajaxSettings.headers = {};

    $.ajaxSettings.headers['X-CSRFToken'] = $.cookie('csrftoken');

    $.fn.csrfEditable = function(url) {
        var self = this;

        function error(xhr, status, error) {
            if (status == 403) {
                self.css("background-color", "#fcc");
            }
        }

        self.editable(url, { select: true,
                             ajaxoptions: { error: error },
                             data: function(string, settings) {
                                 return $.trim(string, settings);
                             }});
        self.addClass("editable");
    };

    $(document).ready(function() {
        // Make the login link activatable.
        $("#login_link").click(function(event) {
            $(this).toggleClass('selected');
            $("#login_popup_form").slideToggle();
            return false;
        });

        $('#submit-ajax').click(function() {
            var $elem = $(this);

            var df = $.ajax({ url: $elem.data('url'),
                              type: 'POST' });
            df.done(function() {
                messages.addInfo("Your extension has been locked.").hide().slideDown();
                $elem.attr('disabled', true);
                $('h3, p.description').csrfEditable('disable').removeClass('editable');
            });

            return false;
        });

        if (window._SW)
            try {
                window._SW();
            } catch(e) {
                console.error(e);
            }
    });
});

Select inline editable fields by default.


import React, {PropTypes} from 'react'
import Component from 'hyper/component'
import SvgIcon from '../../utils/svg-icon'

export default class Draining extends Component {
  static propTypes() {
    return {
      percentage: PropTypes.number
    }
  }

  calculateChargePoint(percent) {
    const base = 3.5,
      val = Math.round((100 - percent) / 4.5),
      point = base + (val / 2)

    return val > 0 ? `M5,3 L11,3 L11,${point} L5,${point} L5,3 Z` : ''
  }

  styles() {
    return {
      'cpu-discharging-icon': {
        fill: '#fff'
      }
    }
  }

  template(css) {
    const chargePoint = this.calculateChargePoint(this.props.percentage)
    return (
      <SvgIcon>
        <g fillRule="evenodd">
          <g className={css('cpu-discharging-icon')}>
            <path d={`M7,1 L9,1 L9,2 L7,2 L7,1 Z M4,2 L12,2 L12,15 L4,15 L4,2 Z ${chargePoint}`}></path>
          </g>
        </g>
      </SvgIcon>
    )
  }
}

import React from 'react'
import PropTypes from 'prop-types'
import Component from 'hyper/component'
import SvgIcon from '../../utils/svg-icon'

export default class Draining extends Component {
  static propTypes() {
    return {
      percentage: PropTypes.number
    }
  }

  calculateChargePoint(percent) {
    const base = 3.5,
      val = Math.round((100 - percent) / 4.5),
      point = base + (val / 2)

    return val > 0 ? `M5,3 L11,3 L11,${point} L5,${point} L5,3 Z` : ''
  }

  styles() {
    return {
      'cpu-discharging-icon': {
        fill: '#fff'
      }
    }
  }

  template(css) {
    const chargePoint = this.calculateChargePoint(this.props.percentage)
    return (
      <SvgIcon>
        <g fillRule="evenodd">
          <g className={css('cpu-discharging-icon')}>
            <path d={`M7,1 L9,1 L9,2 L7,2 L7,1 Z M4,2 L12,2 L12,15 L4,15 L4,2 Z ${chargePoint}`}></path>
          </g>
        </g>
      </SvgIcon>
    )
  }
}

Switch to PropTypes because Hyper's React got rid of it


import React, {Component} from 'react';

export default class ReportAnalysisArea extends Component {

    render() {
        const {customFeatureTitle} = this.props.params;
        // This will be useful later when we do have have multiple titles to display in the Analysis ReportAnalysisArea.
        const titlesArray = customFeatureTitle.split(',');
        return (

                    AREA OF ANALYSIS

                        {titlesArray.map((title, index) => <li key={`analysis-area-${index}`}className="analysis-area-list-item">{title}
)}

        );
    }
}

import React, {Component} from 'react';

export default class ReportAnalysisArea extends Component {

    render() {
        const {customFeatureTitle} = this.props.params;
        // This will be useful later when we do have have multiple titles to display in the Analysis ReportAnalysisArea.
        const titlesArray = customFeatureTitle.split(',');
        return (

                    AREA OF ANALYSIS

                        {titlesArray && titlesArray.map((title, index) => <li key={`analysis-area-${index}`}className="analysis-area-list-item">{title}
)}

        );
    }
}

Add extra check to make sure there is a titlesArray


ui = {
}

ui.player = {
   update: function(trackURI) {
        spotify.getTrackInfo(trackURI)
                .then(function(track) {
                     document.getElementById('player-title').innerHTML = track.title
                     document.getElementById('player-artist').innerHTML = track.artist
                     document.getElementById('player-album').innerHTML = track.album
                     document.getElementById('player-img').src = track.cover
                });
   },

   displayQueue: function(queue) {
        console.log(queue);
        var queueElement =  document.getElementById('queue');

        // empty the old queue
       while (queueElement.firstChild) {
           queueElement.removeChild(queueElement.firstChild);
       }

        for (i in queue) {
           var uri = queue[i]["uri"];

           var div = document.createElement("div");
           queueElement.appendChild(div);

           spotify.getTrackInfo(uri)
                  .then(function(track) {
                      var text = document.createTextNode(track.artist + " - " +  track.title);
                      div.appendChild(text);
                      div.appendChild(document.createElement("br"));
                  });

        }
   }

};

ui.uriSelection = {
   getUri: function() {
      return document.getElementById("uri-to-add").value;
   },

   clear: function() {
      document.getElementById("uri-to-add").value = '';
   }
}

ui = {
}

ui.player = {
   update: function(trackURI) {
        spotify.getTrackInfo(trackURI)
                .then(function(track) {
                     document.getElementById('player-title').innerHTML = track.title
                     document.getElementById('player-artist').innerHTML = track.artist
                     document.getElementById('player-album').innerHTML = track.album
                     document.getElementById('player-img').src = track.cover
                });
   },

   displayQueue: function(queue) {
        var queueElement =  document.getElementById('queue');

        // empty the old queue
       while (queueElement.firstChild) {
           queueElement.removeChild(queueElement.firstChild);
       }

        for (i in queue) {
           var uri = queue[i]["uri"];

           var div = document.createElement("div");
           queueElement.appendChild(div);

           spotify.getTrackInfo(uri)
                  .then(function(track) {
                      var text = document.createTextNode(track.artist + " - " +  track.title);
                      div.appendChild(text);
                      div.appendChild(document.createElement("br"));
                  });

        }
   }

};

ui.uriSelection = {
   getUri: function() {
      return document.getElementById("uri-to-add").value;
   },

   clear: function() {
      document.getElementById("uri-to-add").value = '';
   }
}

Remove debug output in queue display function


function getRestaurants (latitude, longitude) {
  if (latitude && longitude) {
    var center = {lat: latitude, lng: longitude}
    var map = new google.maps.Map(document.getElementsByClassName('map')[0], {
      center: center,
      zoom: 15
    })
    var service = new google.maps.places.PlacesService(map)
    service.nearbySearch({
      location: center,
      radius: 500,
      type: ['restaurant']
    }, callback)
  }
}

function callback (results, status) {
  if (status === google.maps.places.PlacesServiceStatus.OK) {
    var collection = '

Restaurants

'
    for (var i = 0; i < results.length; i++) {
      let restaurantName
      let url = 'https://www.google.com/maps/place/' + restaurantName.replace(/\s/g, '+')
      collection += ('
' + '' + restaurantName + '
')
    }
    $('.restaurants-list').html(collection)
  }
}

function getRestaurants (latitude, longitude) {
  if (latitude && longitude) {
    var center = {lat: latitude, lng: longitude}
    var map = new google.maps.Map(document.getElementsByClassName('map')[0], {
      center: center,
      zoom: 15
    })
    var service = new google.maps.places.PlacesService(map)
    service.nearbySearch({
      location: center,
      radius: 500,
      type: ['restaurant']
    }, callback)
  }
}

function callback (results, status) {
  if (status === google.maps.places.PlacesServiceStatus.OK) {
    var collection = '

Restaurants

'
    for (var i = 0; i < results.length; i++) {
      let restaurantName = results[i].name
      let url = 'https://www.google.com/maps/place/' + restaurantName.replace(/\s/g, '+')
      collection += ('
' + '' + restaurantName + '
')
    }
    $('.restaurants-list').html(collection)
  }
}

Create variable to store restaurant name


"use strict";

module.exports = function(imports) {

    let express = imports.modules.express;
    let Promise = imports.modules.Promise;
    let util = imports.util;
    let NormalGroup = imports.models.NormalGroup;
    let Group = imports.models.Group;

    let handler = util.handler;
    let requireLogin = util.requireLogin;
    let requireAdmin = util.requireAdmin;

    let router = express.Router();

    router.post("/groups", handler(function*(req, res) {
        let group = {
            users: req.body.users,
            groups: req.body.groups
        }

        group = yield NormalGroup.create(group);

        res.json(group);

    }));

    router.get("/groups", requireLogin, handler(function*(req, res) {

        let groups = yield Group.find({
            members: req.user._id
        });

        res.json(groups);

    }));

    router.put("/groups/:id", handler(function*(req, res) {

        let group = yield NormalGroup.update({
            _id: req.params._id
        }, {
            users: req.body.users,
            groups: req.body.groups
        });

        res.json(group);

    }));

    return router;
};

"use strict";

module.exports = function(imports) {

    let express = imports.modules.express;
    let Promise = imports.modules.Promise;
    let util = imports.util;
    let NormalGroup = imports.models.NormalGroup;
    let Group = imports.models.Group;

    let handler = util.handler;
    let requireLogin = util.requireLogin;
    let requireAdmin = util.requireAdmin;

    let router = express.Router();

    router.post("/groups", handler(function*(req, res) {
        let group = {
            users: req.body.users,
            groups: req.body.groups
        }

        group = yield NormalGroup.create(group);

        res.json(group);

    }));

    router.get("/groups", requireLogin, handler(function*(req, res) {

        let groups = yield Group.find({
            members: req.user._id
        });

        res.json(groups);

    }));

    router.put("/groups/id/:id", requireLogin, handler(function*(req, res) {

        let group = yield NormalGroup.update({
            _id: req.params._id
        }, {
            users: req.body.users,
            groups: req.body.groups
        });

        res.json(group); // TODO: add permissions?

    }));

    return router;
};

Add requireLogin and Fix params


module.exports = function(DocumentService) {

    this.reload = function(message='**') {
        if (DocumentService.kind() == 'asciidoctor-latex') {
            MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
            console.log(message + ": reloadMathJax called");
        } else {
            console.log(message + ": skipping MathJax reload");
        }

    }

}

module.exports = function(DocumentService) {

    this.reload = function(message='**') {
        if (DocumentService.kind() == 'asciidoc-latex') {
            MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
            console.log(message + ": reloadMathJax called");
        } else {
            console.log(message + ": skipping MathJax reload");
        }

    }

}

Use 'asciidoc-latex' instead of 'asciidoctor-latex' in document kinds


var os = require('os');
var fs = require('fs-extra');
var path = require('path');
var exec = require('child_process').exec;

const PROJECT_DIRECTORY = path.join(__dirname, '..');
const OS_TEMP_LOCATION = path.join(os.tmpdir(), 'node-static-site-generator-tests');

console.log('1) Setting up environment for testing');
console.log('2) Copying source files to OS temp directory');

fs.copy(PROJECT_DIRECTORY, OS_TEMP_LOCATION, {
    clobber: true,
    filter: function(directory) {
        //exclude specific directories (mainly node_modules) from being copied over
        return directory.indexOf('karma') === -1 && directory.indexOf('phantom') === -1 && directory.indexOf('express') === -1 && directory.indexOf('build') === -1 && directory.indexOf('release') === -1 && directory.indexOf('_source') === -1;
    }
}, function (err) {

    if (err) {
        console.error('3) Unable to copy source files');
        return console.error(err)
    }

    console.log('3) Source files copied - Test setup complete');

    exec('mocha', function(err, stdout, stderr) {
        console.log(stdout);
    });
})

var os = require('os');
var fs = require('fs-extra');
var path = require('path');
var exec = require('child_process').exec;

const PROJECT_DIRECTORY = path.join(__dirname, '..');
const OS_TEMP_LOCATION = path.join(os.tmpdir(), 'node-static-site-generator-tests');

console.log('1) Setting up environment for testing');
console.log('2) Copying source files to OS temp directory');

fs.copy(PROJECT_DIRECTORY, OS_TEMP_LOCATION, {
    clobber: true,
    filter: function(directory) {
        //exclude specific directories (mainly node_modules) from being copied over
        return directory.indexOf('karma') === -1 && directory.indexOf('phantom') === -1 && directory.indexOf('express') === -1 && directory.indexOf('build') === -1 && directory.indexOf('release') === -1 && directory.indexOf('_source') === -1;
    }
}, function (err) {

    if (err) {
        console.error('3) Unable to copy source files');
        return console.error(err)
    }

    process.chdir(path.join(OS_TEMP_LOCATION ,'generatorTests'));

    exec('mocha', function(err, stdout, stderr) {
        console.log(stdout);
    });
})

Change test setup script to change working directory to temp dir


// Define history model and handlers

NetVisHistory = function() {
	BaseNetVisModel.apply(this); // History class inherits from baseModel

	this.loadEvent = function(obj, momentTime) {
		log.console('loading event ', obj);
		obj._t = momentTime;
		obj.time = momentTime.toISOString();
		var isoTime = momentTime.toISOString();
		var i=0;
		var eventID = isoTime;
		// eventID to be unique and contain timestamp
		// of form "<timestamp>#3" where 3 is count of events with
		// the same timestamp
		log.console(eventID);
		while (this.asObject[eventID]){
			i++;
			eventID = isoTime + "#" + i;
		}
		obj.id = eventID;
		this.load(obj);
	};
	// add default time margin moments
	this.loadEvent({"tag":"start"},moment("1970-01-01"));
	this.loadEvent({"tag":"end"},moment("3000-01-01"));
};

// Define history model and handlers

NetVisHistory = function() {
	BaseNetVisModel.apply(this); // History class inherits from baseModel

	this.loadEvent = function(obj, momentTime) {
		obj._t = momentTime;
		obj.time = momentTime.toISOString();
		// eventID to be unique and contain timestamp
		// of form "<timestamp>#3" where 3 is count of events with
		// the same timestamp
		var i=1,
			obj.id = obj.time;
		while(this._asObject[obj.id]){
			i++;
			obj.id = obj.time + "#" + i;
		}
		obj.id = obj.time;
		this.load(obj);
	};
	// add default time margin moments
	this.loadEvent({"tag":"start"},moment("1970-01-01"));
	this.loadEvent({"tag":"end"},moment("3000-01-01"));
};

Fix bug asObject --> _asObject


import 'lint-tests'; // eslint-disable-line

import assert from 'assert';
import Client from '../src/client';

suite('manual-lint-test', () => {
  const config = {
    domain: 'sendmecats.myshopify.com',
    storefrontAccessToken: 'abc123'
  };

  test('it ensures that all Connections include pageInfo', () => {
    const client = Client.buildClient(config);
    const objectTypes = client.graphQLClient.typeBundle.types;

    for (const key in objectTypes) {
      if (objectTypes.hasOwnProperty(key) && key.includes('Connection')) {
        assert.equal(objectTypes[key].fieldBaseTypes.pageInfo, 'PageInfo');
      }
    }
  });
});

import 'lint-tests'; // eslint-disable-line

import assert from 'assert';
import Client from '../src/client';

suite('manual-lint-test', () => {
  const config = {
    domain: 'sendmecats.myshopify.com',
    storefrontAccessToken: 'abc123'
  };

  test('it has pageInfo on all relay connection types', () => {
    const client = Client.buildClient(config);
    const objectTypes = client.graphQLClient.typeBundle.types;

    Object.keys(objectTypes)
      .filter((key) => key.includes('Connection'))
      .forEach((key) => {
        assert.equal(objectTypes[key].fieldBaseTypes.pageInfo, 'PageInfo');
      });
  });
});

Clean up the manual lint test syntax


import test from "ava";

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

const localesPath = path.join(__dirname, "..", "locales");
const filenameRegex = /^[a-z][a-z](_[A-Z]+)*\.json$/;

test("locale files are valid", t => {
  const filenames = fs.readdirSync(localesPath);
  filenames.forEach(filename => {
    /* test filename */
    if (!filenameRegex.test(filename)) t.fail(`locale filename "${filename}" is invalid`);

    /* test file json */
    const content = fs.readFileSync(path.join(localesPath, filename), { encoding: "utf8" });
    let valid = false;
    try {
      JSON.parse(content);
      valid = true;
    } catch (e) {}
    if (!valid) t.fail(`locale file "${filename}" is invalid`);
  });

  t.pass(); // if nothing has failed so far
});

import test from "ava";

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

const localesPath = path.join(__dirname, "..", "locales");
const filenameRegex = /^[a-z][a-z](_[A-Z]+)*\.json$/;

test("locale files are valid", t => {
  const filenames = fs.readdirSync(localesPath);
  filenames.forEach(filename => {
    /* test filename */
    if (!filenameRegex.test(filename)) t.fail(`locale filename "${filename}" is invalid`);

    /* test file json */
    const content = fs.readFileSync(path.join(localesPath, filename), { encoding: "utf8" });
    let json;
    try {
      json = JSON.parse(content);
    } catch (e) {
      t.fail(`locale file "${filename}" contains invalid JSON`);
    }

    /* test file contents */
    t.truthy(json["__redirect__"] || json["__locale_name__"], `locale file "${filename}" is missing both "__locale_name__" and "__redirect__"`);
  });

  t.pass(); // if nothing has failed so far
});

Add test for certain required locale keys


/*
 *  https://github.com/svaarala/duktape/issues/111
 */

/*---
{
    "custom": true
}
---*/

/*===
65534
Error
Error
Error
===*/

function test(n) {
    var res = [];
    var i;
    var fn;

    res.push('(function func() { ');
    for (i = 0; i < n; i++) {
        res.push('    var arg' + i + ' = ' + i + ';');
    }
    res.push('    return arg' + (i - 1) + ';');
    res.push('})');

    res = res.join('\n');

    fn = eval(res);
    return fn();
}

try {
    print(test(65535));  // should work
} catch (e) {
    print(e.name);
}

try {
    print(test(65536));  // should be rejected with internal error now
} catch (e) {
    print(e.name);
}

try {
    print(test(262143));  // should be rejected with internal error now
} catch (e) {
    print(e.name);
}

try {
    print(test(262144));  // should be rejected with internal error now
} catch (e) {
    print(e.name);
}

/*
 *  https://github.com/svaarala/duktape/issues/111
 */

/*---
{
    "custom": true
}
---*/

/*===
65531
Error
Error
Error
===*/

function test(n) {
    var res = [];
    var i;
    var fn;

    res.push('(function func() { ');
    for (i = 0; i < n; i++) {
        res.push('    var arg' + i + ' = ' + i + ';');
    }
    res.push('    return arg' + (i - 1) + ';');
    res.push('})');

    res = res.join('\n');

    fn = eval(res);
    return fn();
}

try {
    print(test(65535 - 3));  // should work, -3 for shuffle regs
} catch (e) {
    print(e.name);
}

try {
    print(test(65536 - 3));  // should be rejected with internal error now
} catch (e) {
    print(e.name);
}

try {
    print(test(262143 - 3));  // should be rejected with internal error now
} catch (e) {
    print(e.name);
}

try {
    print(test(262144 - 3));  // should be rejected with internal error now
} catch (e) {
    print(e.name);
}

Fix testcase to match reg shuffle fix


'use strict';

var RedisCommands = require('../js/service/redis-commands'),
    should         = require('should');

describe('RedisCommands', function () {

    // TODO: fix RedisCommands to fit these tests
    describe('To tree', function () {

        var redisCommands = new RedisCommands();

        it('Should convert basic keys to a tree', function () {
            var keys = [
                'abc:xyz',
                'abc:ijk',
                'lmn:opq'
            ];

            var tree = redisCommands.toTree(keys);

            tree.should.have.ownProperty('isLeaf');
            tree.should.have.ownProperty('children');

            tree.children.should.have.ownProperty('abc');
            tree.children.should.have.ownProperty('lmn');
            tree.isLeaf.should.not.be.ok;
        });

        it('Should mark some nodes as leaves', function () {
            var keys = [
                'abc',
                'abc:xyz',
                'abc:ijk',
                'abc:ijk:lmn',
                'lmn:opq'
            ];

            var tree = redisCommands.toTree(keys);

            tree.isLeaf.should.not.be.ok;
            tree.children.abc.isLeaf.should.be.ok;
            tree.children.abc.children.xyz.isLeaf.should.be.ok;
            tree.children.abc.children.ijk.isLeaf.should.be.ok;
            tree.children.abc.children.ijk.children.lmn.isLeaf.should.be.ok;
            tree.children.lmn.isLeaf.should.not.be.ok;
            tree.children.lmn.children.opq.isLeaf.should.be.ok;
        });

    });

});

'use strict';

var RedisCommands = require('../js/service/redis-commands'),
    should         = require('should');

describe('RedisCommands', function () {

    // TODO: fix RedisCommands to fit these tests
    describe('To tree', function () {

        var redisCommands = new RedisCommands();

        it('Should convert basic keys to a tree', function () {
            var keys = [
                'abc:xyz',
                'abc:ijk',
                'lmn:opq'
            ];

            var tree = redisCommands.toTree(keys);

            tree.should.have.ownProperty('abc');
            tree.should.have.ownProperty('lmn');

            tree.abc.should.have.ownProperty('isLeaf');
            tree.abc.should.have.ownProperty('children');

            tree.abc.isLeaf.should.not.be.ok;
        });

        it('Should mark some nodes as leaves', function () {
            var keys = [
                'abc',
                'abc:xyz',
                'abc:ijk',
                'abc:ijk:lmn',
                'lmn:opq'
            ];

            var tree = redisCommands.toTree(keys);

            tree.abc.isLeaf.should.be.ok;
            tree.abc.children.xyz.isLeaf.should.be.ok;
            tree.abc.children.ijk.isLeaf.should.be.ok;
            tree.abc.children.ijk.children.lmn.isLeaf.should.be.ok;
            tree.lmn.isLeaf.should.not.be.ok;
            tree.lmn.children.opq.isLeaf.should.be.ok;
        });

    });

});

Update redis commands toTree tests


'use strict';
var util = require('util');
var events = require('events');
var EventEmitter = events.EventEmitter || events;

/**
 * Mock for SerialPort
 */
var SerialPortMock = function(path, options, openImmediately, callback) {
    EventEmitter.call(this);
    this._openFlag = openImmediately;
    if (callback) {
        callback(null);
    }
};
util.inherits(SerialPortMock, EventEmitter);

SerialPortMock.prototype.open = function (callback) {
    this._openFlag = true;
    if (callback) {
        callback(null);
    }
    this.emit('open');
};

SerialPortMock.prototype.isOpen = function() {
    return this._openFlag;
};

SerialPortMock.prototype.write = function(buffer, callback) {
    this._data = buffer;
    if (callback) {
        callback(null);
    }
};

SerialPortMock.prototype.close = function (callback) {
    this._openFlag = false;
    if (callback) {
        callback(null);
    }
    this.emit('close');
};

SerialPortMock.prototype.receive = function (buffer) {
    this.emit('data', buffer);
};

module.exports.SerialPort = SerialPortMock;

'use strict';
var util = require('util');
var events = require('events');
var EventEmitter = events.EventEmitter || events;

/**
 * Mock for SerialPort
 */
var SerialPortMock = function(path, options, callback) {
    EventEmitter.call(this);
    this._openFlag = false;
    if (callback) {
        callback(null);
    }
};
util.inherits(SerialPortMock, EventEmitter);

SerialPortMock.prototype.open = function (callback) {
    this._openFlag = true;
    if (callback) {
        callback(null);
    }
    this.emit('open');
};

SerialPortMock.prototype.isOpen = function() {
    return this._openFlag;
};

SerialPortMock.prototype.write = function(buffer, callback) {
    this._data = buffer;
    if (callback) {
        callback(null);
    }
};

SerialPortMock.prototype.close = function (callback) {
    this._openFlag = false;
    if (callback) {
        callback(null);
    }
    this.emit('close');
};

SerialPortMock.prototype.receive = function (buffer) {
    this.emit('data', buffer);
};

module.exports = SerialPortMock;

Move tests to v4 version Serial API


import test from 'ava';
import whenDomReady from '../';

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

test('whenDomReady returns a Promise', t => {
	t.true(whenDomReady() instanceof Promise);
});

test('whenDomReady.resume is a function', t => {
	t.is(typeof whenDomReady.resume, 'function');
});

test('whenDomReady.resume returns a function that returns a promise', t => {
	const returnValue = whenDomReady.resume();
	t.is(typeof returnValue, 'function');
	t.true(returnValue() instanceof Promise);
});

Add type test for whenDomReady.resume


//= require vue
//= require d3
//= require scrollmagic
//= require vue/charts/HorizontalBarChart
//= require vue/charts/interactive_multiline/TabTitle
//= require vue/charts/interactive_multiline/InteractiveMultiline
//= require vue/charts/Sunburst
//= require vue/charts/Treemap
//= require vue/components/Counter
//= require vue/components/horizontal_bars/HorizontalBar
//= require vue/components/horizontal_bars/HorizontalBars
//= require vue/components/InteractiveTreemap
//= require vue/components/rectangles/Rectangle
//= require vue/components/rectangles/Rectangles
//= require vue/components/StickyNav
//= require 'require'
//= require jquery
//= require 'map'
//= require modules/marine/base
//= require modules/maps/base

//= require 'jquery.tablesorter.min'
//= require 'async-img.min'
//= require 'modules/ui_state'
//= require 'modules/search/autocompletion'
//= require 'modules/search/query_control'
//= require 'modules/dropdown'
//= require 'modules/navbar'
//= require 'modules/modal'
//= require 'modules/modals/download_generation_modal'
//= require 'modules/downloads/base'
//= require 'modules/protected_areas/factsheet_handler'
//= require 'modules/expandable_section'
//= require 'modules/dismissable'
//= require 'modules/resizable'
//= require_tree './modules/downloads/'
//= require common

Add back in js files that are required in the base.js file so that the main navigation works again


var require("sdk/tabs");
var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var domain, reqest, response ;

var icons =

var button = buttons.ActionButton({
  id: "contribute",
  label: "How to contribute!",
    icon: {
      "16": "./icon-16.png",
      "32": "./icon-32.png",
      "64": "./icon-64.png"
      },
      onClick: dealWithIt;
});

functon dealWithIt() {
    console.log("");

};

function toggleIcon(state) {
    if(state == true){
        button.icon.16 = "./

tab.on('ready', function(tab){
  req = require("sdk/request").Request({
      url: window.location.protocol + window.location.host + "/contribute.json",
      onComplete: function(resp){
      if(req.status == 200){
        toggleIcon(true);
        console.log(url + " - Contribute.json available!");
      } else {
        toggleIcon(false);
        console.log(url + " - Contribute.json unavailable, humbug.");
   });
});

var require("sdk/tabs");
var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var domain, reqest, response ;

var icons = {
  "inactive": {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  }
  "active": {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  }
}

var button = buttons.ActionButton({
  id: "contribute",
  label: "How to contribute!",
    icon: icons.inactive,
      onClick: dealWithIt;
});

functon dealWithIt() {
    console.log("");

};

function toggleIcon(state) {
    if(state == true){
      button.icon = icons.active;
    }
}

tab.on('ready', function(tab){
  req = require("sdk/request").Request({
      url: new URL("/contribute.json", window.location),
      onComplete: function(resp){
      if(resp.status >= 200 && resp.status < 300 && resp.json != null){
        toggleIcon(true);
        console.log(url + " - Contribute.json available!");
      } else {
        toggleIcon(false);
        console.log(url + " - Contribute.json unavailable, humbug.");
   });
});

Add some cleanup. * Move the icons into their own dictionary. * Use a url object to do the parsing. * Check for all 200-level statuses. * Check that the response was JSON.


require([ 'config' ], function() {
  var getUrlArgs = function() {
    var search = document.location.search || '';
    if (search.indexOf('?') === 0) {
      search = search.substring(1);
    }
    return search;
  };
  require.config({
    deps : [ 'js/app' ],
    paths : {
      'js/app' : 'app'
    },
    urlArgs : getUrlArgs()
  });
});

require([ 'config' ], function() {
  var getUrlArgs = function() {
    if (window.jsVersion === undefined) {
      return '';
    }
    return 'v=' + window.jsVersion;
  };
  require.config({
    deps : [ 'js/app' ],
    paths : {
      'js/app' : 'app'
    },
    urlArgs : getUrlArgs()
  });
});

Update urlArgs support for production build


(function() {
  // properties

  const fs = require("fs");

  // entry
  module.exports = {
    addHeaderPaths: addHeaderPaths
  };

  // updates the platforms/ios/cordova/build.xcconfig file with Branch's Header Paths
  // some plugins still use the old CocoaPods way to resolve config dirs or other obscure
  // ways that modify CocoaPods config. That causes the Branch plugin to fail on iOS build.
  function addHeaderPaths() {
    const filePath = "platforms/ios/cordova/build.xcconfig";
    let config = readBuildXcconfig(filePath);

    config = updateHeaderPaths(config);
    writeBuildXcconfig(filePath, config);
  }

  // update build.xcconfig with Branch's Header Paths
  function updateHeaderPaths(config) {
    config = config.split("\n")
      .map(function (line) {
        if (line.indexOf("HEADER_SEARCH_PATHS") > -1 && line.indexOf("Branch-SDK") === -1) {
          line += ' "${PODS_ROOT}/Branch/Branch-SDK/Branch-SDK" "${PODS_ROOT}/Branch/Branch-SDK/Branch-SDK/Networking" "${PODS_ROOT}/Branch/Branch-SDK/Branch-SDK/Networking/Requests"';
        }
        return line;
      });

    return config.join("\n");
  }

  function readBuildXcconfig(filePath) {
    return fs.readFileSync(filePath, "utf8");
  }

  function writeBuildXcconfig(filePath, config) {
    return fs.writeFileSync(filePath, config, { encoding: "utf8" });
  }
})();

(function() {
  // properties

  const fs = require("fs");

  // entry
  module.exports = {
    addHeaderPaths: addHeaderPaths
  };

  // updates the platforms/ios/cordova/build.xcconfig file with Branch's Header Paths
  // some plugins still use the old CocoaPods way to resolve config dirs or other obscure
  // ways that modify CocoaPods config. That causes the Branch plugin to fail on iOS build.
  function addHeaderPaths() {
    const filePath = "platforms/ios/cordova/build.xcconfig";
    let config = readBuildXcconfig(filePath);

    config = updateHeaderPaths(config);
    writeBuildXcconfig(filePath, config);
  }

  // update build.xcconfig with Branch's Header Paths
  function updateHeaderPaths(config) {
    config = config.split("\n")
      .map(function (line) {
        if (line.indexOf("HEADER_SEARCH_PATHS") > -1 && line.indexOf("Branch-SDK") === -1) {
          line += ' "${PODS_ROOT}/Branch/Branch-SDK"';
        }
        return line;
      });

    return config.join("\n");
  }

  function readBuildXcconfig(filePath) {
    return fs.readFileSync(filePath, "utf8");
  }

  function writeBuildXcconfig(filePath, config) {
    return fs.writeFileSync(filePath, config, { encoding: "utf8" });
  }
})();

Update header search paths to match new iOS folder structure


import assert from 'assert';
import uakari from '../lib';

describe('uakari', function () {
  it('should determine the version of the local packge', function () {
    assert.equal(uakari.version, '0.0.4', 'expect the current version to be earliest.');
  });
});

import assert from 'assert';
import uakari from '../lib';

describe('uakari', function () {
  it('should determine the version of the local packge', function () {
    assert.notEqual(uakari.version, '0.0.4', 'expect the current version to be earliest.');
  });
});

Update current test to alway succeed


/*
 * hub.js
 *
 * Copyright (c) 2012-2014 Maximilian Antoni <mail@maxantoni.de>
 *
 * @license MIT
 */
'use strict';

var inherits     = require('inherits');
var Filter       = require('glob-filter').Filter;
var AsyncEmitter = require('async-glob-events').AsyncEmitter;

function defaultCallback(err) {
  if (err) {
    throw err;
  }
}

function Hub() {
  AsyncEmitter.call(this);
  Filter.call(this, { reverse : true });
}

inherits(Hub, AsyncEmitter);

var emit   = Filter.prototype.emit;
var invoke = AsyncEmitter.prototype.invoke;

Hub.prototype.invoke = function (iterator, scope, callback) {
  emit.call(this, scope, function (cb) {
    invoke.call(this, iterator, scope, cb);
  }, callback || defaultCallback);
};

Object.keys(Filter.prototype).forEach(function (key) {
  if (key !== 'emit') {
    Hub.prototype[key] = Filter.prototype[key];
  }
});

Hub.prototype.removeAll = function (event) {
  this.removeAllFilters(event);
  this.removeAllListeners(event);
};

exports.Hub = Hub;

/*
 * hub.js
 *
 * Copyright (c) 2012-2014 Maximilian Antoni <mail@maxantoni.de>
 *
 * @license MIT
 */
'use strict';

var inherits     = require('inherits');
var Filter       = require('glob-filter').Filter;
var AsyncEmitter = require('async-glob-events').AsyncEmitter;

function defaultCallback(err) {
  if (err) {
    throw err;
  }
}

function Hub() {
  AsyncEmitter.call(this);
  Filter.call(this, { reverse : true });
}

inherits(Hub, AsyncEmitter);

Object.keys(Filter.prototype).forEach(function (key) {
  if (key !== 'emit') {
    Hub.prototype[key] = Filter.prototype[key];
  }
});

var emit   = Filter.prototype.emit;
var invoke = AsyncEmitter.prototype.invoke;

Hub.prototype.invoke = function (iterator, scope, callback) {
  emit.call(this, scope, function (cb) {
    invoke.call(this, iterator, scope, cb);
  }, callback || defaultCallback);
};

Hub.prototype.removeAll = function (event) {
  this.removeAllFilters(event);
  this.removeAllListeners(event);
};

exports.Hub = Hub;

Move filter inheritance code below `inherits` call


'use strict';

const Account = require('../../models/account');
const createError = require('http-errors');
const bcrypt = require('bcrypt-as-promised');
const jwt = require('jsonwebtoken-as-promised');

function createToken (req, res, next) {
  Account.findOne({ email: req.body.email })
    .then(ensureAccount)
    .then(compareHashes)
    .then(generateToken)
    .then(sendResponse)
    .catch(next)
  ;

  function ensureAccount (account) {
    if (!account) {
      throw new createError.Forbidden();
    }

    return account;
  }

  function compareHashes (account) {
    return bcrypt.compare(req.body.password, account.passwordHash);
  }

  function generateToken (account) {
    const payload = {
      id: account.id,
      email: account.email,
      profile: account.profile,
    };

    return jwt.sign(payload, req.app.locals.configuration.jwt.secret, req.app.locals.configuration.jwt.options);
  }

  function sendResponse (token) {
    const jwt = {
      access_token: token,
      token_type: 'bearer'
    };

    res.status(201).json(jwt);
  }
}

module.exports = createToken;

'use strict';

const Account = require('../../models/account');
const createError = require('http-errors');
const bcrypt = require('bcrypt-as-promised');
const jwt = require('jsonwebtoken-as-promised');

function createToken (req, res, next) {
  Account.findOne({ email: req.body.email })
    .then(ensureAccount)
    .then(compareHashes)
    .then(generateToken)
    .then(sendResponse)
    .catch(onError)
  ;

  function ensureAccount (account) {
    if (!account) {
      throw new createError.Forbidden();
    }

    return account;
  }

  function compareHashes (account) {
    return bcrypt.compare(req.body.password, account.passwordHash);
  }

  function generateToken (account) {
    const payload = {
      id: account.id,
      email: account.email,
      profile: account.profile,
    };

    return jwt.sign(payload, req.app.locals.configuration.jwt.secret, req.app.locals.configuration.jwt.options);
  }

  function sendResponse (token) {
    const jwt = {
      access_token: token,
      token_type: 'bearer'
    };

    res.status(201).json(jwt);
  }

  function onError (err) {
    if (err && err.name === 'MismatchError') {
      return next(new createError.Forbidden(err));
    }

    next(err);
  }
}

module.exports = createToken;

Add forbidden error if mismatch


const should = require('should');
const sinon = require('sinon');
require('should-sinon');

const proxyquire = require('proxyquire');
const httpMocks = require('node-mocks-http');

// Mock Service
const mockObj = {
    getAllUsers() {
        return Promise.resolve(['item 1', 'item 2']);
    }
};

const userController = proxyquire('../../app/controllers/user-controller', {
    '../services/user-service': mockObj
});

describe('User controller tests', function () {
    it('should not fail and send a JSON parsed data', async function () {
        // Given

        const res = httpMocks.createResponse();
        const req = httpMocks.createRequest({
            method: 'GET',
            url: '/user/',
            params: {}
        });

        // When
        await userController.getAllUsers(req, res);

        // Then
        res._isEndCalled().should.be.true();
        res._isJSON().should.be.true();
        res._getData().should.be.equal('["item 1","item 2"]');
    });

    it('should fail correctly if there is a problem in service', async function () {
        // Given

        const res = httpMocks.createResponse();
        const req = httpMocks.createRequest({
            method: 'GET',
            url: '/user/',
            params: {}
        });

        const serviceStub = sinon.stub(mockObj, 'getAllUsers');
        serviceStub.throws();

        // When
        await userController.getAllUsers(req, res);

        // Then
        res._isEndCalled().should.be.true();
        res.statusCode.should.be.equal(500);

        serviceStub.restore();
    });
});

const should = require('should');
const sinon = require('sinon');
require('should-sinon');

const proxyquire = require('proxyquire');
const httpMocks = require('node-mocks-http');

// Mock Service
const mockObj = {
    getAllUsers() {
        return Promise.resolve(['item 1', 'item 2']);
    }
};

const userController = proxyquire('../../app/controllers/user-controller', {
    '../services/user-service': mockObj
});

describe('User controller tests', function () {
    it('should not fail and send a JSON parsed data', async function () {
        // Given

        const res = httpMocks.createResponse();
        const req = httpMocks.createRequest({
            method: 'GET',
            url: '/user/',
            params: {}
        });

        // When
        await userController.getAllUsers(req, res);

        // Then
        res._isEndCalled().should.be.true();
        res._isJSON().should.be.true();
        res._getData().should.be.equal('["item 1","item 2"]');
    });
});

Remove test for fail case (handled by express)


// Before I start the game
// If someone's browser doesn't support console, then make a dummy object
console = window.console || { log: function(s){} };

// Start my game!
var game = new Phaser.Game('90','90',Phaser.CANVAS);
var gameScreen = new GameScreen();
game.state.add("GameScreen", gameScreen);
game.state.start("GameScreen");

// Before I start the game
// If someone's browser doesn't support console, then make a dummy object
console = window.console || { log: function(s){} };

// Start my game!
var game = new Phaser.Game('100','100',Phaser.AUTO);
var gameScreen = new GameScreen();
game.state.add("GameScreen", gameScreen);
game.state.start("GameScreen");

Change canvas size and render mode


'use babel'

import Path from 'path'

export function requireDependency(name, rootDirectory) {
  if (name.indexOf('rollup-plugin-') === -1) {
    name = 'rollup-plugin-' + name
  }

  try {
    return require(Path.join(rootDirectory, 'node_modules', name))
  } catch (_) {}
  try {
    require(name)
  } catch (_) {}

  throw new Error(`Rollup plugin '${name}' not found in '${rootDirectory}'`)
}

'use babel'

import Path from 'path'

export function requireDependency(name, rootDirectory) {
  if (name.indexOf('rollup-plugin-') === -1) {
    name = 'rollup-plugin-' + name
  }

  try {
    return require(Path.join(rootDirectory, 'node_modules', name))
  } catch (_) {}
  try {
    return require(name)
  } catch (_) {}

  throw new Error(`Rollup plugin '${name}' not found in '${rootDirectory}'`)
}

Fix a typo in requireDependencies


var fold = /<div class='fold'/;

export default function getPreFoldContent(content) {
  const match = fold.exec(content);
  if (match) {
    return content.slice(0, match.index);
  }
  return content;
};

var prefix = /<p>(<em>)?\[[^\]]+\](<\/em>)?<\/p>/m;
var fold = /<div class='fold'/;

export default function getPreFoldContent(content) {
  const foldMatch = fold.exec(content);
  if (foldMatch) {
    content = content.slice(0, foldMatch.index);
  }

  content = content.replace(prefix, '');

  return content;
};

Remove post prefix from preFold content


#!/usr/bin/env node

var args = process.argv.slice(2);

console.log(args);

#!/usr/bin/env node

var cli = {
  'new': function() {
    console.log("This will make a new project by cloning it from git and installing dependencies.");
  },
  'run': function() {
    console.log("This will start a gulp task using a locally-installed instance of gulp.");
  },
  'help': function() {
    console.log("This will print out help stuff.");
  },
  '-v': function() {
    console.log("This will print out a version.");
  }
}

var command = process.argv[2];
var args = process.argv.slice(3);

// Print the help stuff if no command is given
if (typeof command === 'undefined') command = 'help';

cli[command].apply(this, args);
console.log(args);

Add placeholders for CLI tasks


/**
 * @flow
 */

jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
import path from 'path';
import uuid from 'uuid';
import rimraf from 'rimraf';
import {
  clearXDLCacheAsync,
  downloadTemplateApp,
  extractTemplateApp,
} from '../Exp';

describe('Template Apps', () => {
  it('should download the starter app template and extract it', async () => {
    process.env.UNSAFE_EXPO_HOME_DIRECTORY = path.join(
      '/',
      'tmp',
      `.expo-${uuid.v1()}`
    );

    await clearXDLCacheAsync();
    let dir = path.join('/', 'tmp', `.expo-${uuid.v1()}`);
    let templateDownload = await downloadTemplateApp('tabs', dir, {
      name: `test-template-${new Date().valueOf()}`,
      progressFunction: () => {},
      retryFunction: () => {},
    });
    expect(templateDownload).not.toBeNull();
    // Extract the template we just downloaded
    let projectRoot = await extractTemplateApp(
      templateDownload.starterAppPath,
      templateDownload.name,
      templateDownload.root
    );

    rimraf.sync(process.env.UNSAFE_EXPO_HOME_DIRECTORY);
    rimraf.sync(dir);
  });
});

/**
 * @flow
 */

jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
import path from 'path';
import uuid from 'uuid';
import rimraf from 'rimraf';
import {
  clearXDLCacheAsync,
  downloadTemplateApp,
  extractTemplateApp,
} from '../Exp';

describe('Template Apps', () => {
  it('should download the starter app template and extract it', async () => {
    // This was working locally but failing on the mac ci machine

    /*
    process.env.UNSAFE_EXPO_HOME_DIRECTORY = path.join(
      '/',
      'tmp',
      `.expo-${uuid.v1()}`
    );

    await clearXDLCacheAsync();
    let dir = path.join('/', 'tmp', `.expo-${uuid.v1()}`);
    let templateDownload = await downloadTemplateApp('tabs', dir, {
      name: `test-template-${new Date().valueOf()}`,
      progressFunction: () => {},
      retryFunction: () => {},
    });
    expect(templateDownload).not.toBeNull();
    // Extract the template we just downloaded
    let projectRoot = await extractTemplateApp(
      templateDownload.starterAppPath,
      templateDownload.name,
      templateDownload.root
    );

    rimraf.sync(process.env.UNSAFE_EXPO_HOME_DIRECTORY);
    rimraf.sync(dir);
    */
  });
});

Disable template test for now


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

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('login', {error: req.flash('error')});
});

router.get('/app/:page', function (req, res, next) {
  res.render('index', {title: req.page});
});

router.get("/api/name", function(req,res){
  res.json({
    name: 'YEP'
  });
});

router.get("/partials/view1", function(req,res){
  res.render('partials/partial1',{
    pretty: true
  });
});

router.get("/partials/view2", function(req,res){
  res.render('partials/partial2',{
    pretty: true
  });
});

router.get("/partials/cc", function(req,res){
  res.render('partials/contentcontrol',{
    pretty: true
  });
});

router.get("/partials/admin", function(req,res){
  res.render('partials/admincontrol',{
    pretty: true
  });
});

module.exports = router;

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

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('login', {error: req.flash('error')});
});

router.get('/app/:page?', function (req, res, next) {
  res.render('index', {title: req.page});
});

router.get("/api/name", function(req,res){
  res.json({
    name: 'YEP'
  });
});

router.get("/partials/view1", function(req,res){
  res.render('partials/partial1',{
    pretty: true
  });
});

router.get("/partials/view2", function(req,res){
  res.render('partials/partial2',{
    pretty: true
  });
});

router.get("/partials/cc", function(req,res){
  res.render('partials/contentcontrol',{
    pretty: true
  });
});

router.get("/partials/admin", function(req,res){
  res.render('partials/admincontrol',{
    pretty: true
  });
});

module.exports = router;

Make page param of the /app/:page route optional


/*jslint node: true */
'use strict';

var Player = require('./lib/server/Player').Player,
	player;

exports.listen = function (app) {
	var io = require('socket.io').listen(app),
		room = io.of('/room');

	room.on('connection', function (user) {
		// Player joins room
		user.emit('identify-player', { id: user.id });
		user.on('identify-player', function (data) {
			// Create player with new data
			player = new Player(data);
			console.log(player.get('all'));
			user.emit('server-message', { text: 'Välkommen ' + player.get('name') + '!' });
		});

		// Player sends message
		user.on('user-message', function (data) {
			// Send the message to all player in room
			room.emit('user-message', { text: data, player: player.get('all') });
		});

		// Player disconnect
		user.on('disconnect', function () {
			room.emit('server-message', { text: player.get('name') + ' har lämnat spelet.' });
		});
	});

	return io;
};

/*jslint node: true */
'use strict';

var Player = require('./lib/server/Player').Player,
	players = [];

exports.listen = function (app) {
	var io = require('socket.io').listen(app),
		room = io.of('/room');

	room.on('connection', function (user) {
		var player;

		// Player joins room
		user.emit('identify-player', { id: user.id });

		// Browser send player data
		user.on('identify-player', function (data) {
			// Create player with new data
			player = new Player(data);

			// Remove player from array
			players = players.filter(function (p) { return p.getSocketID !== user.id; });

			// Add player to array
			players.push(player);

			// Welcome player
			user.emit('server-message', { text: 'Välkommen ' + player.get('name') + '!' });
		});

		// Player sends message
		user.on('user-message', function (data) {
			// Send the message to all player in room
			room.emit('user-message', { text: data, player: player.get('all') });
		});

		// Player disconnect
		user.on('disconnect', function () {
			room.emit('server-message', { text: player.getFullName() + ' har lämnat spelet.' });
		});
	});

	return io;
};

Save players in array on server


var request = require('request');
let finalResult

module.exports = function(app, db) {
  app.get('/number', (req, res) => {
    console.log(req.query.name);
    request('https://api.coin-hive.com/user/balance?secret='+ process.env.KEY_PRIVATE +'&name='+ req.query.name, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        finalResult = body
      }
      else{
        console.log(error);
      }
    })
    // You'll create your note here.
    res.send(finalResult)
  });
};

var request = require('request');

module.exports = function(app, db) {
  app.get('/number', (req, res) => {
    request('https://api.coin-hive.com/user/balance?secret='+ process.env.KEY_PRIVATE +'&name='+ req.query.name, function (error, response, body) {
      if (!error && response.statusCode == 200) {
      let BodyParsed = JSON.parse(body)
      let hashesMined = BodyParsed.balance
        request('https://www.cryptocompare.com/api/data/coinsnapshot/?fsym=XMR&tsym=USD', function (error, response, body) {
          if (!error && response.statusCode == 200) {
            BodyParsed = JSON.parse(body)
            let netHashesSecond = BodyParsed.Data.NetHashesPerSecond
            let blockReward = BodyParsed.Data.BlockReward
            request('https://min-api.cryptocompare.com/data/price?fsym=XMR&tsyms=USD', function (error, response, body) {
              if (!error && response.statusCode == 200) {
                BodyParsed = JSON.parse(body)
                let price = BodyParsed.USD
                price = parseFloat(price)
                netHashesSecond = parseFloat(netHashesSecond)
                blockReward = parseFloat(blockReward)
                hashesMined = parseFloat(hashesMined)
                let hashesSecondBlockDay = netHashesSecond / (720 * blockReward)
                let moneyMade = hashesMined * price / (hashesSecondBlockDay * 24 * 3600)
                res.send('TotalHashes:'+hashesMined + ',TotalMoney:'+ moneyMade)
              }
              else{
                console.log(error);
              }
            })
          }
          else{
            console.log(error);
          }
        })
      }
      else{
        console.log(error);
      }
    })
  });
};

Add dollar capabilities to API


const dir = __dirname
const webpack = require('webpack')

module.exports = {
    entry: "./build/main.js",
    output: {
        filename: "build/out/out.js"
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /(node_modules|forge.bundle.js)/,
                loader: 'babel-loader'
            }
            ]

    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        })
    ]
}

const dir = __dirname
const webpack = require('webpack')

module.exports = {
    entry: "./build/main.js",
    output: {
        filename: "build/out/main.js"
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /(node_modules|forge.bundle.js)/,
                loader: 'babel-loader'
            }
            ]

    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        })
    ]
}

Rename out.js to main.js to reflect README


var View = require('./View'),
	Button = require('../Button'),
	List = require('../lists/List'),
	TextView = require('../TextView')

module.exports = Class(View, function(supr) {

	this._createHeader = function() {
		new Button('New Task')
			.appendTo(this._header)
			.subscribe('Click', this, '_createTask')
	}

	this._createBody = function() {
		new List(function (task) { return new TextView(task.title) })
			.reflect(global.user.tasks)
			.appendTo(this._body)
			.subscribe('Select', this, function(task) {
				models.local.currentTaskID.set(task._id)
			})
	}

	this._createTask = function() {
		var task = new models.Task({ title:"I need to...", owner:global.user }).create()
		global.user.tasks.add(task)
	}
})

var View = require('./View'),
	Button = require('../Button'),
	List = require('../lists/List'),
	TextView = require('../TextView')

module.exports = Class(View, function(supr) {

	this._createHeader = function() {
		new Button('New Task')
			.appendTo(this._header)
			.subscribe('Click', this, '_createTask')
	}

	this._createBody = function() {
		new List(function (task) { return new TextView(task.title) })
			.reflect(global.user.tasks)
			.appendTo(this._body)
			.subscribe('Select', this, function(task) {
				models.local.currentTaskID.set(task._id)
			})
	}

	this._createTask = function() {
		var task = new models.Task({ title:"I need to...", owner:global.user })
		global.user.tasks.add(task)
		task.create(function(taskID) {
			models.local.currentTaskID.set(taskID)
		})
	}
})

Select a task when it's been created


Package.describe({
  name: "practicalmeteor:google-translate",
  summary: "Server side synchronous google translate.",
  git: "https://github.com/practicalmeteor/meteor-google-translate.git",
  version: '0.9.0-rc0'
});

Npm.depends({'googleapis': '1.0.21'});

Package.onUse(function (api) {
  api.versionsFrom('0.9.3');

  api.use('coffeescript', 'server');
  api.use(['practicalmeteor:loglevel@1.1.0_2', 'practicalmeteor:chai@1.9.2_3'], 'server');

  // Uncomment once we upgrade to loglevel v2, with package specific loggers
  // api.addFiles('src/lib/log.js');

  api.addFiles([
    'src/server/GoogleTranslate.coffee'
  ], "server");

  //api.export('GoogleTranslate', 'server');
});

Package.onTest(function (api) {
  api.use([
    'coffeescript',
    'practicalmeteor:google-translate',
    'practicalmeteor:loglevel@1.1.0_2',
    'spacejamio:chai',
    'tinytest'], 'server');

  api.addFiles('tests/server/GoogleTranslateTest.coffee', 'server');
});

Package.describe({
  name: "practicalmeteor:google-translate",
  summary: "Server side synchronous google translate.",
  git: "https://github.com/practicalmeteor/meteor-google-translate.git",
  version: '0.9.0-rc0'
});

Npm.depends({'googleapis': '1.0.21'});

Package.onUse(function (api) {
  api.versionsFrom('0.9.3');

  api.use('coffeescript', 'server');
  api.use(['practicalmeteor:loglevel@1.1.0_2', 'practicalmeteor:chai@1.9.2_3'], 'server');

  // Uncomment once we upgrade to loglevel v2, with package specific loggers
  // api.addFiles('src/lib/log.js');

  api.addFiles([
    'src/server/GoogleTranslate.coffee'
  ], "server");

  //api.export('GoogleTranslate', 'server');
});

Package.onTest(function (api) {
  api.use([
    'coffeescript',
    'practicalmeteor:google-translate',
    'practicalmeteor:loglevel@1.1.0_2',
    'practicalmeteor:chai',
    'tinytest'], 'server');

  api.addFiles('tests/server/GoogleTranslateTest.coffee', 'server');
});

Use practicalmeteor:chai and not spacejamio:chai


import fs from 'fs';
import path from 'path';
import {makeId, removePrefix} from '../common';

const romExtName = '.nes';
const thumbExtNames = ['.png', '.git', '.jpg', '.jpeg'];

export function isRomFile(file) {
  return path.extname(file).toLowerCase() === romExtName;
}

export function getRomId(romFile) {
  const extName = path.extname(romFile);
  const baseName = path.basename(romFile, extName);
  return makeId(baseName);
}

export function getRomName(romFile) {
  return path.basename(romFile).trim();
}

export function compareRomsByName(rom1, rom2) {
  const name1 = removePrefix(rom1.name, 'the ', true);
  const name2 = removePrefix(rom2.name, 'the ', true);
  return name1.localeCompare(name2);
}

export function findRomThumbFile(romFile) {
  const dirName = path.dirname(romFile);
  const extName = path.extname(romFile);
  const baseName = path.basename(romFile, extName);

  for (const thumbExtName of thumbExtNames) {
    const thumbFileName = baseName + thumbExtName;
    const thumbFile = path.join(dirName, thumbFileName);

    if (fs.existsSync(thumbFile)) {
      return thumbFile;
    }
  }

  return null;
}

import fs from 'fs';
import path from 'path';
import {makeId, removePrefix} from '../common';

const romExtName = '.nes';
const thumbExtNames = ['.png', '.git', '.jpg', '.jpeg'];

export function isRomFile(file) {
  return path.extname(file).toLowerCase() === romExtName;
}

export function getRomId(romFile) {
  const extName = path.extname(romFile);
  const baseName = path.basename(romFile, extName);
  return makeId(baseName);
}

export function getRomName(romFile) {
  const extName = path.extname(romFile);
  return path.basename(romFile, extName).trim();
}

export function compareRomsByName(rom1, rom2) {
  const name1 = removePrefix(rom1.name, 'the ', true);
  const name2 = removePrefix(rom2.name, 'the ', true);
  return name1.localeCompare(name2);
}

export function findRomThumbFile(romFile) {
  const dirName = path.dirname(romFile);
  const extName = path.extname(romFile);
  const baseName = path.basename(romFile, extName);

  for (const thumbExtName of thumbExtNames) {
    const thumbFileName = baseName + thumbExtName;
    const thumbFile = path.join(dirName, thumbFileName);

    if (fs.existsSync(thumbFile)) {
      return thumbFile;
    }
  }

  return null;
}

Fix /api/roms/ returning names with .nes extension


(function () {
    var Ext = window.Ext4 || window.Ext;

    Ext.define('Rally.apps.roadmapplanningboard.PlaceholderColumn', {
        extend: 'Ext.Component',
        alias: 'widget.cardboardplaceholdercolumn',

        requires: [
            'Rally.ui.cardboard.ColumnHeader'
        ],

        afterRender: function () {
            this.drawHeader();

            this.fireEvent('ready', this);
        },

        drawHeader: function () {
            var config = {
                renderTo: Ext.get(this.headerCell)
            };

            Ext.fly(this.headerCell).addCls('planning-column');
            this.columnHeader = Ext.widget(Ext.merge(config, this.columnHeaderConfig));

            // Add a couple of containers to match the structure of the timeframe planning column header
            this.columnHeader.add({
                xtype: 'container',
                tpl: [
                    '

'
                ],
                data: {}
            });
            this.columnHeader.add({
                xtype: 'container',
                tpl: [
                    '

'
                ],
                data: {}
            });
        },

        getColumnHeader: function() {
            return this.columnHeader;
        },

        getColumnHeaderCell: function () {
            return Ext.get(this.headerCell);
        },

        getContentCell: function () {
            return Ext.get(this.contentCell);
        },

        getCards: function () {
            return [];
        },

        getHeaderTitle: function () {
            return this.columnHeader.down('#headerTitle');
        }

    });

})();

(function () {
    var Ext = window.Ext4 || window.Ext;

    Ext.define('Rally.apps.roadmapplanningboard.PlaceholderColumn', {
        extend: 'Ext.Component',
        alias: 'widget.cardboardplaceholdercolumn',

        requires: [
            'Rally.ui.cardboard.ColumnHeader'
        ],

        afterRender: function () {
            this.drawHeader();

            this.fireEvent('ready', this);
        },

        drawHeader: function () {
            var config = {
                renderTo: Ext.get(this.headerCell)
            };

            Ext.fly(this.headerCell).addCls('planning-column');
            this.columnHeader = Ext.widget(Ext.merge(config, this.columnHeaderConfig));

            // Add a couple of containers to match the structure of the timeframe planning column header
            this.columnHeader.add({
                xtype: 'container',
                tpl: [
                    '

'
                ],
                data: {}
            });
            this.columnHeader.add({
                xtype: 'container',
                tpl: [
                    '

'
                ],
                data: {}
            });
        },

        getColumnHeader: function() {
            return this.columnHeader;
        },

        getColumnHeaderCell: function () {
            return Ext.get(this.headerCell);
        },

        getContentCell: function () {
            return Ext.get(this.contentCell);
        },

        getCards: function () {
            return [];
        },

        findCardInfo: function () {
            return null;
        },

        isMatchingRecord: function () {
            return false;
        },

        refresh: function () {
            return null;
        },

        getHeaderTitle: function () {
            return this.columnHeader.down('#headerTitle');
        }

    });

})();

Fix errors with placeholder columns


//  ListPicker.js
//
// Created by Robert Hovhannisyan on 2014-06-12
//
// Copyright 2014 Robert Hovhannisyan. All rights reserved.
// MIT Licensed
var exec = require('cordova/exec');

var ListPicker = function() {}

ListPicker.prototype.showPicker = function(options, callback, error_callback) {
    options || (options = {});
    var scope = options.scope || null;

    var config = {
        title: options.title || ' ',
        selectedValue: options.selectedValue || '',
        items: options.items || {},
        style: options.style || 'default',
        doneButtonLabel: options.doneButtonLabel || 'Done',
        cancelButtonLabel: options.cancelButtonLabel || 'Cancel'
    };

    var _callback = function() {
        if(typeof callback == 'function') {
          callback.apply(scope, arguments);
        }
    };

    var _error_callback = function() {
        if(typeof error_callback == 'function') {
          error_callback.apply(scope, arguments);
        }
    };
    cordova.exec(_callback, _error_callback, 'ListPicker', 'showPicker', [config]);
}
module.exports = new ListPicker();

//  ListPicker.js
//
// Created by Robert Hovhannisyan on 2014-06-12
//
// Copyright 2014 Robert Hovhannisyan. All rights reserved.
// MIT Licensed
var exec = require('cordova/exec');

var ListPicker = function() {}

ListPicker.prototype.showPicker = function(options, callback, error_callback) {
    options || (options = {});
    var scope = options.scope || null;

    var config = {
        title: options.title || ' ',
        selectedValue: options.selectedValue || [],
        items: options.items || {},
        style: options.style || 'default',
        doneButtonLabel: options.doneButtonLabel || 'Done',
        cancelButtonLabel: options.cancelButtonLabel || 'Cancel'
    };

    var _callback = function() {
        if(typeof callback == 'function') {
          callback.apply(scope, arguments);
        }
    };

    var _error_callback = function() {
        if(typeof error_callback == 'function') {
          error_callback.apply(scope, arguments);
        }
    };
    cordova.exec(_callback, _error_callback, 'ListPicker', 'showPicker', [config]);
}
module.exports = new ListPicker();

Set default value of selected value to empty array


function WebbitSocket(path, target) {
    var self = this;
    var ws = new WebSocket('ws://' + document.location.host + path);
    ws.onclose = function() {
        target.onclose && target.onclose();
    };
    ws.onmessage = function(e) {
        var msg = JSON.parse(e.data);
        if (msg.exports) {
            msg.exports.forEach(function(name) {
                self[name] = function() {
                    var outgoing = {
                        action: name,
                        args: Array.prototype.slice.call(arguments)
                    };
                    ws.send(JSON.stringify(outgoing));
                };
            })
            target.onopen && target.onopen();
        } else {
            var action = target[msg.action];
            if (typeof action === 'function') {
                action.apply(target, msg.args);
            } else {
                // TODO: ?
            }
        }
    };
}

function WebbitSocket(path, target) {
    var self = this;
    var ws = new WebSocket('ws://' + document.location.host + path);
    ws.onclose = function() {
        target.onclose && target.onclose();
        self.onclose && self.onclose();
    };
    ws.onerror = function() {
        target.onerror && target.onerror();
        self.onerror && self.onerror();
    };
    ws.onmessage = function(e) {
        target.onmessage && target.onmessage(e);
        self.onmessage && self.onmessage(e);
        var msg = JSON.parse(e.data);
        if (msg.exports) {
            msg.exports.forEach(function(name) {
                self[name] = function() {
                    var outgoing = {
                        action: name,
                        args: Array.prototype.slice.call(arguments)
                    };
                    ws.send(JSON.stringify(outgoing));
                };
            })
            target.onopen && target.onopen();
            self.onopen && self.onopen();
        } else {
            var action = target[msg.action];
            if (typeof action === 'function') {
                action.apply(target, msg.args);
            } else {
                // TODO: ?
            }
        }
    };
}

Allow WebbitSocket.on{error,close,open} to be hooked up.


import path from 'path';
import express from 'express';
import logger from 'morgan';
import bodyParser from 'body-parser';

require('dotenv').config();

const app = express();
const appPath = path.join(__dirname, '..', 'client/build');
console.log(appPath);

app.use(logger('dev'));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static('client/build'));
app.use(express.static('public'));

app.set('json spaces', 4);

require('./routes')(app);

app.get('*', (req, res) => {
  res.send({ message: 'Route does not exist. Check your url.' });
});

app.get('*', (req, res) => {
  res.sendFile(path.join(appPath, 'index.html'));
});

module.exports = app;

import path from 'path';
import express from 'express';
import logger from 'morgan';
import bodyParser from 'body-parser';

require('dotenv').config();

const app = express();
const appPath = path.join(__dirname, '..', 'client/build');
console.log(appPath);

app.use(logger('dev'));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static('client/build'));
app.use(express.static('public'));

app.set('json spaces', 4);

require('./routes')(app);

app.get('*', (req, res) => {
  res.sendFile(path.join(appPath, 'index.html'));
});

module.exports = app;

Fix issue with homepage on deployment


/*
 Copyright 2017 Google Inc. All Rights Reserved.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

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

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

/**
 * Warns users that an old property is deprecated in favor of a new property
 * and aliases the old name to the new name.
 * @param {Object} obj The object containing the methods.
 * @param {string} oldName The method to deprecate.
 * @param {string} newName The new method replacing the deprecated method.
 * @param {string} ctx The context project/object to identify the method names.
 */
export default (obj, oldName, newName, ctx) => {
  if (Object.prototype.hasOwnProperty.call(obj, oldName)) {
    /* eslint-disable no-console */
    console.warn(`In ${ctx}: ` +
        `${oldName} is deprecated, use ${newName} instead`);
    /* eslint-enable no-console */

    obj[newName] = obj[oldName];
  }
};

/*
 Copyright 2017 Google Inc. All Rights Reserved.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

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

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

import logHelper from './log-helper';

/**
 * Warns users that an old property is deprecated in favor of a new property
 * and aliases the old name to the new name.
 * @param {Object} obj The object containing the methods.
 * @param {string} oldName The method to deprecate.
 * @param {string} newName The new method replacing the deprecated method.
 * @param {string} ctx The context project/object to identify the method names.
 */
export default (obj, oldName, newName, ctx) => {
  if (Object.prototype.hasOwnProperty.call(obj, oldName)) {
    logHelper.warn(
        `${oldName} is deprecated; use ${newName} instead`, {Context: ctx});

    obj[newName] = obj[oldName];
  }
};

Use logHelper instead of console.warn


#!/usr/bin/env node

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

var surkuConfig={
    maxMutations:20,
    minMutations:1,
    chunkSize:3000
};
var surku=new S(surkuConfig);

function init(config){
    surkuConfig.tempDirectory=config.tempDirectory;
}

function generateTestCase(getSample,callback){
        //console.log('surku')
        var prefix=new Date().getTime()+Math.random().toString().split('.')[1];
        var sampleFile=getSample(1)[0];
        if(sampleFile){
            var fileName=surkuConfig.tempDirectory+'/samples/'+prefix;
            var fileContent=fs.readFileSync(sampleFile);
            var chunkSize=Math.ceil(fileContent.length/100);
            if(chunkSize>3000){
                surku.config.chunkSize=3000;
            }else if(chunkSize<500){
                surku.config.chunkSize=500;
            }
            else{
                surku.config.chunkSize=chunkSize;
            }
            var testCase=surku.generateTestCase(fileContent);
            fs.writeFile(fileName,testCase,function(){
                //console.log(fileName)
                //console.log("New length: "+testCase.length+ " Original length: "+fileContent.length)
                callback({type:"file",data:fileName});
            });
        }
        else{
            callback();
        }
}

module.exports={
    init,
    generateTestCase
};

#!/usr/bin/env node

var S=require('surku');
var fs=require('fs');

var surkuConfig={
    maxMutations:20,
    minMutations:1,
    chunkSize:3000
};
var surku=new S(surkuConfig);

function init(config){
    surkuConfig.tempDirectory=config.tempDirectory;
}

function generateTestCase(getSample,callback){
        var prefix=new Date().getTime()+Math.random().toString().split('.')[1];
        var sampleFile=getSample(1)[0];
        if(sampleFile){
            var fileName=surkuConfig.tempDirectory+'/samples/'+prefix;
            var fileContent=fs.readFileSync(sampleFile);
            var chunkSize=Math.ceil(fileContent.length/100);
            if(chunkSize>3000){
                surku.config.chunkSize=3000;
            }else if(chunkSize<500){
                surku.config.chunkSize=500;
            }
            else{
                surku.config.chunkSize=chunkSize;
            }
            var testCase=surku.generateTestCase(fileContent);
            fs.writeFile(fileName,testCase,function(){
                callback({type:"file",data:fileName});
            });
        }
        else{
            callback();
        }
}

module.exports={
    init,
    generateTestCase
};

Remove unused and commented code


var path 		= require('path');
var rootPath 	= path.normalize(__dirname + '/../../');

module.exports 	= {
    local: {
        baseUrl: 'http://localhost:3051',
        db: 'mongodb://localhost/rp_local',
        rootPath: rootPath,
        port: process.env.PORT || 3051
    },
    staging : {
        baseUrl: 'http://dev.resourceprojects.org',
        //db: '@aws-us-east-1-portal.14.dblayer.com:10669/rp_dev?ssl=true',
        db: '@aws-us-east-1-portal.14.dblayer.com:10669,aws-us-east-1-portal.13.dblayer.com:10499/rp_dev?ssl=true',
        rootPath: rootPath,
        port: process.env.PORT || 80
    }
};

var path 		= require('path');
var rootPath 	= path.normalize(__dirname + '/../../');

module.exports 	= {
    local: {
        baseUrl: 'http://localhost:3030',
        db: 'mongodb://localhost/rp_local',
        rootPath: rootPath,
        port: process.env.PORT || 3016
    },
    staging : {
        baseUrl: 'http://dev.resourceprojects.org',
        //db: '@aws-us-east-1-portal.14.dblayer.com:10669/rp_dev?ssl=true',
        db: '@aws-us-east-1-portal.14.dblayer.com:10669,aws-us-east-1-portal.13.dblayer.com:10499/rp_dev?ssl=true',
        rootPath: rootPath,
        port: process.env.PORT || 80
    }
};

Add to download links ng-csv


import React from 'react';

const UserButton = ({ thumbnail, onShow }) => {
    return(

            <div className="thumbnail" style={{backgroundImage: `${thumbnail ? url(${thumbnail}): url('/user_thumb.jpg')}` }}>

    );
};

export default UserButton;

import React from 'react';

const UserButton = ({ thumbnail, onShow }) => {
    return(

            <div className="thumbnail" style={{backgroundImage: `${thumbnail ? url(thumbnail): url('/user_thumb.jpg')}` }}>

    );
};

export default UserButton;

Fix an error on thumbnail val


module.exports = Backbone.View.extend({

  className: 'main_price main_wrap',

  initialize: function(){

    var self = this

    self.$el.html(ss.tmpl['main-pairing'].render()).appendTo('.dash .main').addClass('animated fadeInUp')

    self.display_qr();
  },

  clear: function(){

    var self = this

    self.$el.removeClass('animated fadeInUp')
    self.$el.addClass('animatedQuick fadeOutUp')

    setTimeout(function(){

      self.$el.remove()

    }, 500)
  },

  display_qr: function(){
    var self = this

    self.user.create_pairing_token(function(err, token){
      if (err) return alert('Pairing failed: ' + err.message)

      self.user.get_server_address(function(err, address){
        new QRCode(document.getElementById('qrcode'), JSON.stringify({
          token: token,
          trader: address
        }))
      })
    })
  }

})

module.exports = Backbone.View.extend({

  className: 'main_price main_wrap',

  initialize: function(){

    var self = this

    self.$el.html(ss.tmpl['main-pairing'].render()).appendTo('.dash .main').addClass('animated fadeInUp')

    self.display_qr();
  },

  clear: function(){

    var self = this

    self.$el.removeClass('animated fadeInUp')
    self.$el.addClass('animatedQuick fadeOutUp')

    setTimeout(function(){

      self.$el.remove()

    }, 500)
  },

  display_qr: function(){
    var self = this

    self.user.get_server_address(function(err, address){
      if (err) return alert('Getting server address failed: ' + err.message)

      self.user.create_pairing_token(function(err_, token){
        if (err_) return alert('Pairing failed: ' + err_.message)

        new QRCode(document.getElementById('qrcode'), JSON.stringify({
          token: token,
          trader: address
        }))
      })
    })
  }

})

Fix error handling and call order


const config = require('../../../config')
const authorisedRequest = require('../../lib/authorised-request')

const Order = {
  save (token, data) {
    return authorisedRequest(token, {
      url: `${config.apiRoot}/v3/omis/order`,
      method: 'POST',
      body: data,
    })
  },

  update (token, id, data) {
    return authorisedRequest(token, {
      url: `${config.apiRoot}/v3/omis/order/${id}`,
      method: 'PATCH',
      body: data,
    })
  },

  getById (token, id) {
    return authorisedRequest(token, `${config.apiRoot}/v3/omis/order/${id}`)
  },
}

module.exports = {
  Order,
}

const config = require('../../../config')
const authorisedRequest = require('../../lib/authorised-request')

const Order = {
  save (token, data) {
    return authorisedRequest(token, {
      url: `${config.apiRoot}/v3/omis/order`,
      method: 'POST',
      body: data,
    })
  },

  update (token, id, data) {
    return authorisedRequest(token, {
      url: `${config.apiRoot}/v3/omis/order/${id}`,
      method: 'PATCH',
      body: data,
    })
  },

  saveSubscribers (token, id, body) {
    return authorisedRequest(token, {
      url: `${config.apiRoot}/v3/omis/order/${id}/subscriber-list`,
      method: 'PUT',
      body,
    })
  },

  getById (token, id) {
    return authorisedRequest(token, `${config.apiRoot}/v3/omis/order/${id}`)
  },
}

module.exports = {
  Order,
}

Add saveSubscribers method to OMIS Order model


'use strict';

var EventEmitter = require('events').EventEmitter,
    util = require('util'),
    _ = require('lodash'),
    logger = require('log4js').getLogger('Network');

/*
 * Network
 */
function Network(networkName, options) {
  var props = this.properties = this.constructor.properties;

  if (networkName) {
    this.sensorNetwork = networkName;
  } else {
    if (props && props.sensorNetwork) {
      this.sensorNetwork = props.sensorNetwork;
    }
  }
  this.options = options;

  EventEmitter.call(this);
}

util.inherits(Network, EventEmitter);

Network.properties = {sensorNetwork: 'none'};

Network.prototype.discover = function (options, cb) {
  if (typeof options === 'function') {
    cb = options;
  }
  return cb && cb(new Error('NOT IMPLEMENTED'));
};

Network.prototype.getDevice = function (addr, options, cb) {
  if (typeof options === 'function') {
    cb = options;
  }
  return cb && cb(new Error('NOT IMPLEMENTED'));
};

Network.getLogger = function () {
  return logger;
};

Network.prototype.close = function () {};

Network.getStatus = function () {
  return undefined;
};

module.exports = Network;

'use strict';

var EventEmitter = require('events').EventEmitter,
    util = require('util'),
    _ = require('lodash'),
    logger = require('log4js').getLogger('Network');

/*
 * Network
 */
function Network(networkName, options) {
  var props = this.properties = this.constructor.properties;

  if (networkName) {
    this.sensorNetwork = networkName;
  } else {
    if (props && props.sensorNetwork) {
      this.sensorNetwork = props.sensorNetwork;
    }
  }
  this.options = options;

  EventEmitter.call(this);
}

util.inherits(Network, EventEmitter);

Network.properties = { sensorNetwork: 'none' };

Network.prototype.discover = function(driverOfModel, options, cb) {
  if (typeof driverOfModel === 'function') {
    cb = driverOfModel;
  } else if (typeof options === 'function') {
    cb = options;
  }
  return cb && cb(new Error('NOT IMPLEMENTED'));
};

Network.prototype.getDevice = function(addr, options, cb) {
  if (typeof options === 'function') {
    cb = options;
  }
  return cb && cb(new Error('NOT IMPLEMENTED'));
};

Network.getLogger = function() {
  return logger;
};

Network.prototype.close = function() {};

Network.getStatus = function() {
  return undefined;
};

module.exports = Network;

Modify the parameters of network.discover()


define([
	'jquery',
	'underscore',
	'backbone',

	'backendServiceM',
	'helpers',

	'json!vingtilesD'
],
function ($, _, Backbone, backendServiceM, helpers, vingtiles) {
	'use strict';

	var LocatingChartM = Backbone.Model.extend({
		code: null,
		defaults: {
			data: null,
			vingtiles: null,
		},
		initialize: function(options) {
			this.code = options.code;
			this.listenTo(backendServiceM, 'change:apiData', this.parseApiData);
		},
		parseApiData: function() {
			this.set({
				data: helpers.findDeep(backendServiceM.get('apiData').value, {code: this.code}),
				vingtiles: _.findWhere(vingtiles, {id: this.code}),
			});
		},
	});

	return LocatingChartM;
});

define([
	'jquery',
	'underscore',
	'backbone',

	'backendServiceM',
	'helpers',

	'json!vingtilesD'
],
function ($, _, Backbone, backendServiceM, helpers, vingtiles) {
	'use strict';

	var LocatingChartM = Backbone.Model.extend({
		code: null,
		defaults: {
			data: null,
			vingtiles: null,
		},
		initialize: function(options) {
			this.code = options.code;
			this.set('vingtiles', _.findWhere(vingtiles, {id: this.code}));
			this.listenTo(backendServiceM, 'change:apiData', this.parseApiData);
		},
		parseApiData: function() {
			this.set('data',
				backendServiceM.get('simulationStatus') === 'done' ?
					helpers.findDeep(backendServiceM.get('apiData').value, {code: this.code}) :
					null
			);
		},
	});

	return LocatingChartM;
});

Set model vingtiles on initialization.


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

var inquirer = require('inquirer');
var generator = Object.freeze(require('./generator'));
var questions = Object.freeze(require('./cli.config.json').questions);

/*
 * - Removes trailing slash
 * - Converts to lower case
 * - Trims
 */
// TODO: Add test for this
var formatString = function (val) {
    if (val.charAt(val.length - 1) === '/')
        val = val.substring(0, val.length - 1);
    return val.toLowerCase().trim();
};

var questionsWithFilter = questions.map(function(questionsObj) {
    if (questionsObj.filter === 'formatDist') {
        questionsObj.filter = formatString;
    }
    return questionsObj;
});

inquirer.prompt(questionsWithFilter).then(function(answers) {
    generator(answers);
});

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

var inquirer = require('inquirer');
var list = require('cli-list');
var generator = Object.freeze(require('./generator'));
var questions = Object.freeze(require('./cli.config.json').questions);
var args = list(process.argv.slice(2));

var cliArguments = {};
if (args[0].indexOf('-n') !== -1)
    cliArguments.dryRun = true;

/*
 * - Removes trailing slash
 * - Converts to lower case
 * - Trims
 */
// TODO: Add test for this
var formatString = function (val) {
    if (val.charAt(val.length - 1) === '/')
        val = val.substring(0, val.length - 1);
    return val.toLowerCase().trim();
};

var questionsWithFilter = questions.map(function(questionsObj) {
    if (questionsObj.filter === 'formatDist') {
        questionsObj.filter = formatString;
    }
    return questionsObj;
});

inquirer.prompt(questionsWithFilter).then(function(answers) {
    if (!cliArguments.dryRun)
        generator(answers);
});

Add dry run argument to CLI (-n)