// Import libraries
import 'rxjs'
import { Provider } from 'react-redux'
import React, { PureComponent } from 'react'
import { syncHistoryWithStore } from 'react-router-redux'
import { Router, Route, browserHistory, IndexRoute } from 'react-router'

// Add CSS framework
import 'foundation-sites/dist/foundation.min.css'

// Our modules
import store from 'store'
import Container from 'shared/Container'

// Our pages
import Home from 'Home'

// Create enhanced history
const history = syncHistoryWithStore(browserHistory, store, {
  selectLocationState (state) {
    return state.get('routing').toJS()
  }
})

export default class App extends PureComponent {
  // App component never needs to update
  shouldComponentUpdate (nextProps, nextState) {
    return false
  }

  render () {
    return (
      <Provider store={store}>
        <Router history={history}>
          <Route path='/' component={Container}>
            <IndexRoute component={Home} />
          </Route>
        </Router>
      </Provider>
    )
  }
}

// Import libraries
import 'rxjs'
import { Provider } from 'react-redux'
import React, { PureComponent } from 'react'
import { syncHistoryWithStore } from 'react-router-redux'
import { Router, Route, browserHistory, IndexRoute } from 'react-router'

// Add CSS framework
import 'foundation-sites/dist/foundation.min.css'

// Our modules
import store from 'store'
import Container from 'shared/Container'

// Our pages
import Home from 'Home'
import Browse from 'SOMEWHERE'
import Upload from 'SOMEWHERE'
import Register from 'SOMEWHERE'
import Login from 'SOMEWHERE'
import User from 'SOMEWHERE'

// Create enhanced history
const history = syncHistoryWithStore(browserHistory, store, {
  selectLocationState (state) {
    return state.get('routing').toJS()
  }
})

export default class App extends PureComponent {
  // App component never needs to update
  shouldComponentUpdate (nextProps, nextState) {
    return false
  }

  render () {
    return (
      <Provider store={store}>
        <Router history={history}>
          <Route path='/' component={Container}>
            <IndexRoute component={Home} />
            <Route path='browse/:id' component={Browse} />
            <Route path='upload' component={Upload} />
            <Route path='login' component={Login} />
            <Route path='register' component={Register} />
            <Route path='user/:id' component={User} />
          </Route>
        </Router>
      </Provider>
    )
  }
}

Add routes for Aksels further development


import undoable from 'redux-undo-immutable';
import { fromJS } from 'immutable';
import { findPathByNodeId } from '../utils/vertTreeUtils';

const defaultState = fromJS([{ value: undefined, children: [], _id: 1000 }]);

const verticalTreeData = (
  state = defaultState,
  action
) => {
  let path = findPathByNodeId(action.nodeId, state);
  switch (action.type) {
    case 'UPDATE_VERT_STRUCTURE':
      return action.newState;
    case 'HIGHLIGHT_NODE':
      path.push('highlighted');
      return state.setIn(path, true);
    case 'UNHIGHLIGHT_NODE':
      path.push('highlighted');
      return state.setIn(path, false);
    case 'RESET_TO_DEFAULT':
      return defaultState;
    default:
      return state;
  }
};

const undoableVerticalTreeData = undoable(
  verticalTreeData,
  { limit: 20 }
);

export default {
  verticalTreeData: undoableVerticalTreeData,
  testableVerticalTreeData: verticalTreeData
};

import undoable from 'redux-undo-immutable';
import { fromJS } from 'immutable';
import { findPathByNodeId } from '../utils/vertTreeUtils';

const defaultState = fromJS([{ value: undefined, children: [], _id: 1000 }]);

const verticalTreeData = (
  state = defaultState,
  action
) => {
  let path = findPathByNodeId(action.nodeId, state);
  if (path) {
    path.push('highlighted');
  }
  switch (action.type) {
    case 'UPDATE_VERT_STRUCTURE':
      return action.newState;
    case 'HIGHLIGHT_NODE':
      return path ? state.setIn(path, true) : state;
    case 'UNHIGHLIGHT_NODE':
      return path ? state.setIn(path, false) : state;
    case 'RESET_TO_DEFAULT':
      return defaultState;
    default:
      return state;
  }
};

const undoableVerticalTreeData = undoable(
  verticalTreeData,
  { limit: 20 }
);

export default {
  verticalTreeData: undoableVerticalTreeData,
  testableVerticalTreeData: verticalTreeData
};

Move path logic out of switch statements


;(function($) {

    $.fn.externalLinkWarning = function() {
        $('a').on('click', function(e) {
            // create temporary anchor
            var tmpLink = document.createElement('a');
            tmpLink.href = this.href;

            // check if anchor host matches top window host
            var externalLink = (tmpLink.host !== top.location.host);

            // if this is an external link, show confirmation dialog
            if (externalLink) {
                return confirm('This link will take you to an external website. Proceed with caution.');
            }

            // if we're here just return true to allow propagation as normal
            return true;
        });
    };

})(jQuery);

;(function($) {

    $.fn.externalLinkWarning = function() {
        $('a').on('click', function(e) {
            // create temporary anchor
            var tmpLink = document.createElement('a');
            tmpLink.href = this.href;

            // check if anchor host matches top window host
            var externalLink = (tmpLink.hostname !== top.location.hostname);

            // if this is an external link, show confirmation dialog
            if (externalLink) {
                return confirm('This link will take you to an external website. Proceed with caution.');
            }

            // if we're here just return true to allow propagation as normal
            return true;
        });
    };

})(jQuery);

Change host to hostname for IE compatibility


module.exports = (provider, body, session) => {

  if (!/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test(body.id_token)) {
    return {error: 'Grant: OpenID Connect invalid id_token format'}
  }
  var [header, payload, signature] = body.id_token.split('.')

  try {
    header = JSON.parse(Buffer.from(header, 'base64').toString('binary'))
    payload = JSON.parse(Buffer.from(payload, 'base64').toString('utf8'))
  }
  catch (err) {
    return {error: 'Grant: OpenID Connect error decoding id_token'}
  }

  if (payload.aud !== provider.key) {
    return {error: 'Grant: OpenID Connect invalid id_token audience'}
  }
  else if ((payload.nonce && session.nonce) && (payload.nonce !== session.nonce)) {
    return {error: 'Grant: OpenID Connect nonce mismatch'}
  }

  return {header, payload, signature}
}

const isAudienceValid = (aud, key) => (Array.isArray(aud) && aud.indexOf(key) !== -1) || aud === key;

module.exports = (provider, body, session) => {

  if (!/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/.test(body.id_token)) {
    return {error: 'Grant: OpenID Connect invalid id_token format'}
  }
  var [header, payload, signature] = body.id_token.split('.')

  try {
    header = JSON.parse(Buffer.from(header, 'base64').toString('binary'))
    payload = JSON.parse(Buffer.from(payload, 'base64').toString('utf8'))
  }
  catch (err) {
    return {error: 'Grant: OpenID Connect error decoding id_token'}
  }

  if (!isAudienceValid(payload.aud, provider.key)) {
    return {error: 'Grant: OpenID Connect invalid id_token audience'}
  }
  else if ((payload.nonce && session.nonce) && (payload.nonce !== session.nonce)) {
    return {error: 'Grant: OpenID Connect nonce mismatch'}
  }

  return {header, payload, signature}
}

Handle audience as an array


const { DataTypes, Model } = require('sequelize');

/**
 * This class represents a barman.
 */
class Barman extends Model {

    /**
     * Initialization function.
     *
     * @param sequelize
     * @returns {Model}
     */
    static init(sequelize) {
        return super.init({
            id: {
                type: DataTypes.INTEGER,
                primaryKey: true
            },

            firstName: {
                type: DataTypes.STRING,
                allowNull: false
            },

            lastName: {
                type: DataTypes.STRING,
                allowNull: false
            },

            nickname: {
                type: DataTypes.STRING,
                allowNull: false
            },

            facebook: {
                type: DataTypes.STRING
            },

            dateOfBirth: {
                type: DataTypes.DATEONLY,
                allowNull: false
            },

            flow: {
                type: DataTypes.TEXT
            },
        }, {
            sequelize,

            // Do not delete row, even when the user delete is account
            paranoid: true
        });
    }

    /**
     * Set associations for the model.
     *
     * @param models
     */
    static associate(models) {
        this.belongsToMany(models.Kommission, { through: models.KommissionWrapper });
        this.belongsToMany(models.Role, { through: models.RoleWrapper });
        this.belongsToMany(models.Service, { through: models.ServiceWrapper });

        this.hasOne(Barman, { as: 'godFather' });

        this.hasOne(models.ConnectionInformation, { as: 'connection' });
    }
}

module.exports = {
    Barman
};

const { DataTypes, Model } = require('sequelize');

/**
 * This class represents a barman.
 */
class Barman extends Model {

    /**
     * Initialization function.
     *
     * @param sequelize
     * @returns {Model}
     */
    static init(sequelize) {
        return super.init({
            id: {
                type: DataTypes.INTEGER,
                primaryKey: true
            },

            firstName: {
                type: DataTypes.STRING,
                allowNull: false
            },

            lastName: {
                type: DataTypes.STRING,
                allowNull: false
            },

            nickname: {
                type: DataTypes.STRING,
                allowNull: false
            },

            facebook: {
                type: DataTypes.STRING
            },

            dateOfBirth: {
                type: DataTypes.DATEONLY,
                allowNull: false
            },

            flow: {
                type: DataTypes.TEXT
            },

            active: {
                type: DataTypes.BOOLEAN,
                allowNull: false,
                defaultValue: true
            }
        }, {
            sequelize,

            // Do not delete row, even when the user delete is account
            paranoid: true
        });
    }

    /**
     * Set associations for the model.
     *
     * @param models
     */
    static associate(models) {
        this.belongsToMany(models.Kommission, { through: models.KommissionWrapper });
        this.belongsToMany(models.Role, { through: models.RoleWrapper });
        this.belongsToMany(models.Service, { through: models.ServiceWrapper });

        this.hasOne(Barman, { as: 'godFather' });

        this.hasOne(models.ConnectionInformation, { as: 'connection' });
    }
}

module.exports = {
    Barman
};

Add field `active` for Barman


(function ($) {
    var settings = {},
        defaults = {
            api: "http://api.ihackernews.com/post/%s?format=jsonp",
        };

    $.fn.ycomments = function (options) {
        $.extend(settings, defaults, options);

        return this.each(init);
    };

    init = function () {
        var $this = $(this),
            url = settings.api.replace("%s", settings.id);

        $.ajax({url: url, dataType: "jsonp"})
            .success(showcomments);
    };

    showcomments = function (data) {
    };
})(jQuery);

(function ($) {
    var settings = {},
        defaults = {
            api: "http://api.ihackernews.com/post/%s?format=jsonp",
            apidatatype: "jsonp",
        };

    $.fn.ycomments = function (options) {
        $.extend(settings, defaults, options);

        return this.each(init);
    };

    init = function () {
        var $this = $(this),
            url = settings.api.replace("%s", settings.id);

        $.ajax({url: url, dataType: settings.apidatatype})
            .success(showcomments);
    };

    showcomments = function (data) {
    };
})(jQuery);

Make API data type configurable.


/* jshint node: true */

module.exports = function(environment) {
  var ENV = {
    modulePrefix: 'dummy',
    environment: environment,
    baseURL: '/',
    locationType: 'hash',
    EmberENV: {
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    },

    contentSecurityPolicy: {
      "script-src": "'self' 'unsafe-inline'",
      "font-src": "'self'",
      "style-src": "'self' 'unsafe-inline'",
      "img-src": "'self' data:"
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.baseURL = '/';
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {
    ENV.baseURL = '/gloit-component';
  }

  return ENV;
};

/* jshint node: true */

module.exports = function(environment) {
  var ENV = {
    modulePrefix: 'dummy',
    environment: environment,
    baseURL: '/',
    locationType: 'hash',
    EmberENV: {
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    },

    contentSecurityPolicy: {
      "script-src": "'self' 'unsafe-inline'",
      "font-src": "'self'",
      "style-src": "'self' 'unsafe-inline'",
      "img-src": "'self' data:"
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;

    ENV.baseURL = '';
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.baseURL = '/';
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {
    ENV.baseURL = '/gloit-component';
  }

  return ENV;
};

Set the baseURL for development


(function () {
    var _fb = false;
    var _pc = false;
    var _inst = null;
    var app = null;

    window.fbAsyncInit = function() {
        FB.init({
            appId      : '1238816002812487',
            xfbml      : true,
            version    : 'v2.5'
        });

        _fb = true;

        if (_fb && app) {
            app.fire("fb:init");
        }
    };

    app = pc.Application.getApplication();
    app.on("start", function () {
        if (_fb) {
            app.fire("fb:init");
        }
    });

    (function(d, s, id){
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
}());

(function () {
    var _fb = false;
    var _pc = false;
    var _inst = null;
    var app = null;

    window.fbAsyncInit = function() {
        FB.init({
            appId      : '1238816002812487',
            xfbml      : true,
            version    : 'v2.5'
        });

        _fb = true;

        if (_fb && app) {
            app.fire("fb:init");
        }
    };

    app = pc.Application.getApplication();
    app.on("initialize", function () {
        if (_fb) {
            app.fire("fb:init");
        }
    });

    (function(d, s, id){
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
}());

Use `initialize` event to start up


define(function(require) {

  var test = require('../../../test')
  var n = 0

  // 404
  var a = require('./a')
  test.assert(a === null, '404 a')

  // exec error
  setTimeout(function() {
    var b = require('./b')
  }, 0)

  require.async('./c', function(c) {
    test.assert(c === null, '404 c')
    done()
  })

  require.async('./e', function(e) {
    test.assert(e === null, 'exec error e')
    done()
  })

  seajs.use('./d', function(d) {
    test.assert(d === null, '404 d')
    done()
  })

  // 404 css
  //require('./f.css')

  function done() {
    if (++n === 3) {
      test.assert(w_errors.length > 0, w_errors.length)
      test.assert(s_errors.length === 3, s_errors.length)
      test.next()
    }
  }

})

define(function(require) {

  var test = require('../../../test')
  var n = 0

  // 404
  var a = require('./a')
  test.assert(a === null, '404 a')

  // exec error
  setTimeout(function() {
    var b = require('./b')
  }, 0)

  require.async('./c', function(c) {
    test.assert(c === null, '404 c')
    done()
  })

  require.async('./e', function(e) {
    test.assert(e === null, 'exec error e')
    done()
  })

  seajs.use('./d', function(d) {
    test.assert(d === null, '404 d')
    done()
  })

  // 404 css
  //require('./f.css')

  function done() {
    if (++n === 3) {
      test.assert(w_errors.length > 0, w_errors.length)

      // 0 for IE6-8
      test.assert(s_errors.length === 0 || s_errors.length === 3, s_errors.length)
      test.next()
    }
  }

})

Fix test spec for old browsers


"use strict";

module.exports = function(config) {
  config.set({
    frameworks: [ "mocha" ],
    files: [ "dist/jsonapi-client-test.js" ],
    reporters: [ "spec" ],
    plugins: [ "karma-mocha", "karma-firefox-launcher", "karma-spec-reporter" ],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: [ "Firefox"/*, "PhantomJS"*/ ],
    singleRun: true,
    concurrency: 1,
    client: {
      captureConsole: true
    }
  });
};

"use strict";

module.exports = function(config) {
  config.set({
    frameworks: [ "mocha" ],
    files: [ "dist/jsonapi-client-test.js" ],
    reporters: [ "spec" ],
    plugins: [ "karma-mocha", "karma-firefox-launcher", "karma-spec-reporter" ],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: [ "Firefox"/*, "PhantomJS"*/ ],
    singleRun: true,
    concurrency: 1,
    client: {
      captureConsole: true,
      timeout: 10000
    }
  });
};

Extend timeout on travis Mocha tests


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

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

var questionNum = 0,
	answeredQA = [];

// Generate random number to display random QA set
function createNum() {
	questionNum = Math.floor(Math.random() * 3);
	// Recursively create random questionNum so that last QA set will not be repeated
	if (answeredQA.indexOf(questionNum) !== -1) {
		createNum();
	}
	question.innerHTML = questions[questionNum].question;
	answeredQA.push(questionNum);
}

createNum();

var revealBtn = document.getElementById('reveal-answer');

function revealAns() {
	question.innerHTML = questions[questionNum].answer;
}

function nextSet() {
	createNum();
	question.innerHTML = questions[questionNum].question;
}

revealBtn.onclick = revealAns;

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

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

var questionNum = 0,
	answeredQA = [];

// Generate random number to display random QA set
function createNum() {
	questionNum = Math.floor(Math.random() * 3);
	// Recursively create random questionNum so that last QA set will not be repeated
	if (answeredQA.indexOf(questionNum) !== -1) {
		createNum();
	}
	question.innerHTML = questions[questionNum].question;
	answeredQA.push(questionNum);
}

createNum();

var revealBtn = document.getElementById('reveal-answer');

function revealAns() {
	question.innerHTML = questions[questionNum].answer;
	revealBtn.value = "NEXT";
}

function nextSet() {
	createNum();
	question.innerHTML = questions[questionNum].question;
}

revealBtn.onclick = revealAns;

Change the value of revealBtn when clicked


Fix Tim's dumbass broken test


var tabs = document.querySelectorAll('.tab');
var allPanels = document.querySelectorAll(".schedule");

function activateTab(tab) {
  //remove active de todas as outras tabs
  tabs.forEach(function(tab) {
    tab.classList.remove('active');
  });
  //adiciona active em t
  tab.classList.add('active');
}

function openCourse(item, day) {
    for(var i=0;i<allPanels.length;i++){
        allPanels[i].style.display = 'none';
    }
    document.getElementById(day).style.display = 'block';
    activateTab(item);
}

function initMap() {
    var myLatlng = {lat: -23.482069, lng: -47.425131};
    var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 15,
    center: myLatlng,
	scrollwheel: false,
});

var marker = new google.maps.Marker({
    position: myLatlng,
    map: map,
    title: 'Click to zoom'
});

  map.addListener('center_changed', function() {
    // 3 seconds after the center of the map has changed, pan back to the
    // marker.
    window.setTimeout(function() {
      map.panTo(marker.getPosition());
    }, 3000);
  });

  marker.addListener('click', function() {
    map.setZoom(8);
    map.setCenter(marker.getPosition());
  });
}

var tabs = document.querySelectorAll('.tab');
var allPanels = document.querySelectorAll(".schedule");

function activateTab(tab) {
  //remove active de todas as outras tabs
  for (i = 0; i < tabs.length; ++i) {
    tabs[i].classList.remove('active');
  }
  //adiciona active em t
  tab.classList.add('active');
}

function openCourse(item, day) {
    for(var i=0;i<allPanels.length;i++){
        allPanels[i].style.display = 'none';
    }
    document.getElementById(day).style.display = 'block';
    activateTab(item);
}

function initMap() {
    var myLatlng = {lat: -23.482069, lng: -47.425131};
    var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 15,
    center: myLatlng,
	scrollwheel: false,
});

var marker = new google.maps.Marker({
    position: myLatlng,
    map: map,
    title: 'Click to zoom'
});

  map.addListener('center_changed', function() {
    // 3 seconds after the center of the map has changed, pan back to the
    // marker.
    window.setTimeout(function() {
      map.panTo(marker.getPosition());
    }, 3000);
  });

  marker.addListener('click', function() {
    map.setZoom(8);
    map.setCenter(marker.getPosition());
  });
}

Fix timeline tabs to work on mozilla (for instead of forEach to nodelist)


var config = require('./config')

var logStack = []

module.exports = {
  getLogStack: function () {
    return logStack
  },

  log: function (message, data) {
    var isDebugMode = config.get('debug') == 'true'
    var hasConsole = window.console

    logStack.push({
      msg: message,
      data: data
    })

    if (isDebugMode && hasConsole) {
      window.console.log(message, data)
    }

  }
}

var config = require('./config')

var logStack = []

module.exports = {
  getLogStack: function () {
    return logStack
  },

  log: function (message, data) {
    var isDebugMode = config.get('debug') === true || config.get('debug') === 'true'
    var hasConsole = window.console

    logStack.push({
      msg: message,
      data: data
    })

    if (isDebugMode && hasConsole) {
      window.console.log(message, data)
    }

  }
}

Handle of the case of debug-config being a bool


import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

export default function startApp(attrs) {
  let application;

  // use defaults, but you can override
  let attributes = Ember.assign({}, config.APP, attrs);

  Ember.run(() => {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}

import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

const merge = Ember.assign || Ember.merge;

export default function startApp(attrs) {
  let application;

  let attributes = merge({}, config.APP);
  attributes = merge(attributes, attrs); // use defaults, but you can override

  Ember.run(() => {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}

Fix startApp for older ember versions


// Show message
// ---------------------------------------------------------------------
class Message
{
	show(msg, timing, animations, new_game_btn, field)
	{
		if (new_game_btn === undefined)
		{
			new_game_btn = false;
		}

		$('#msg_new_game').off('click');

		var msg_box = $('#message_box');
		msg_box.hide();

		var msg_div = $('<div>').attr('id', "message_text").html(msg);

		msg_box.html(msg_div);

		if (new_game_btn)
		{
			$('#message_text').append('<input type="button" id="msg_new_game" value="New Game">');
			$('#msg_new_game').on('click', function() { field.initialize(field); });
		}

		if (animations)
		{
			$('#mineblaster').css({filter: 'blur(5px)'});
			msg_box.fadeIn(timing);
		}
		else
		{
			msg_box.show();
		}
	}

	// Hide message box
	// ---------------------------------------------------------------------
	hide(animations)
	{
		// Remove end message, if present
		if (animations)
		{
			$('#mineblaster').css('filter', 'none');
			$("#message_box").fadeOut();
		}
		else
		{
			$("#message_box").hide();
		}
	}

}

// Show message
// ---------------------------------------------------------------------
class Message
{
	show(msg, timing, animations, new_game_btn, field)
	{
		if (new_game_btn === undefined)
		{
			new_game_btn = false;
		}

		$('#msg_new_game').off('click');

		var msg_box = $('#message_box');
		msg_box.hide();

		var msg_div = $('<div>').attr('id', "message_text").html(msg);

		msg_box.html(msg_div);

		if (new_game_btn)
		{
			$('#message_text').append('<input type="button" id="msg_new_game" value="New Game">');
			$('#msg_new_game').on('click', function() { field.initialize(field); });
		}

		if (animations)
		{
			$('#message_box').css({backdropFilter: 'blur(5px)'});
			msg_box.fadeIn(timing);
		}
		else
		{
			msg_box.show();
		}
	}

	// Hide message box
	// ---------------------------------------------------------------------
	hide(animations)
	{
		// Remove end message, if present
		if (animations)
		{
			$('#mineblaster').css('filter', 'none');
			$("#message_box").fadeOut();
		}
		else
		{
			$("#message_box").hide();
		}
	}

}

Switch from filter to backdrop-filter to blur background


'use strict';

var assert = require('assert'),
    Selector = require('./');

describe('Selector', function () {
    it('should return an object', function () {
        var selector = new Selector('body', [ 0, 0, 0, 1 ]);
        console.log(selector);
        assert(selector);
        assert.equal(selector.text, 'body');
        assert.deepEqual(selector.spec, [ 0, 0, 0, 1 ]);
    });
});

describe('Selector.parsed', function () {
    it('should get parsed selector', function () {
        var selector = new Selector('body');
        console.log(selector.parsed());
        assert(selector.parsed());
        assert.equal(selector.parsed()['0'].tag, 'body');
        assert.equal(selector.parsed().length, 1);
    });
});

describe('Selector.specificity', function () {
    it('should get specificity', function () {
        var selector = new Selector('body');
        console.log(selector.specificity());
        assert.deepEqual(selector.specificity(), [ 0, 0, 0, 1 ]);
    });
});

/* global describe, it */

'use strict';

var assert = require('assert'),
    Selector = require('./');

describe('Selector', function () {
    it('should return an object', function () {
        var selector = new Selector('body', [ 0, 0, 0, 1 ]);
        assert(selector);
        assert.equal(selector.text, 'body');
        assert.deepEqual(selector.spec, [ 0, 0, 0, 1 ]);
    });
});

describe('Selector.parsed', function () {
    it('should get parsed selector', function () {
        var selector = new Selector('body');
        assert(selector.parsed());
        assert.equal(selector.parsed()['0'].tag, 'body');
        assert.equal(selector.parsed().length, 1);
    });
});

describe('Selector.specificity', function () {
    it('should get specificity', function () {
        var selector = new Selector('body');
        assert.deepEqual(selector.specificity(), [ 0, 0, 0, 1 ]);
    });
});

Remove logging and add globals for jshint.


Fix for active nav links when URL has hash


const defaults = {
  idField: '_id',
  as: 'userId'
};

export default function(options = {}) {
  return function(hook) {
    if (hook.type !== 'before') {
      throw new Error(`The 'associateCurrentUser' hook should only be used as a 'before' hook.`);
    }

    if (!hook.params.user) {
      throw new Error('There is no current user to associate.');
    }

    options = Object.assign({}, defaults, hook.app.get('auth'), options);

    const id = hook.params.user[options.idField];

    if (id === undefined) {
      throw new Error(`Current user is missing '${options.idField}' field.`);
    }

    hook.params.query[options.as] = id;
  };
}

const defaults = {
  idField: '_id',
  as: 'userId'
};

export default function(options = {}) {
  return function(hook) {
    if (hook.type !== 'before') {
      throw new Error(`The 'queryWithCurrentUser' hook should only be used as a 'before' hook.`);
    }

    if (!hook.params.user) {
      throw new Error('There is no current user to associate.');
    }

    options = Object.assign({}, defaults, hook.app.get('auth'), options);

    const id = hook.params.user[options.idField];

    if (id === undefined) {
      throw new Error(`Current user is missing '${options.idField}' field.`);
    }

    hook.params.query[options.as] = id;
  };
}

Fix copy paste typo in queryWithCurrentUser hook.


'use strict';

var Node = require('../node');
var dot = require('dot');

var TYPE = 'weighted-centroid';

var PARAMS = {
    source : Node.PARAM.NODE(Node.GEOMETRY.POINT),
    weight_column : Node.PARAM.STRING,
    category_column : Node.PARAM.STRING
};

var WeightedCentroid  = Node.create(TYPE, PARAMS, {cache: true});

module.exports = WeightedCentroid;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

var weightedCentroidTemplate = dot.template([
    'SELECT the_geom , class',
    'FROM cdb_crankshaft.CDB_WeightedMean($weightedmean_query${{=it.query}}$weightedmean_query$,\'{{=it.weight_column}}\',\'{{=it.category_column}}\')'
].join('\n'));

function query(it) {
    return weightedCentroidTemplate(it);
}

WeightedCentroid.prototype.sql = function(){
    return query({
        query : this.source.getQuery(),
        weight_column : this.weight_column,
        category_column : this.category_column
    });
};

'use strict';

var Node = require('../node');
var dot = require('dot');

var TYPE = 'weighted-centroid';

var PARAMS = {
    source : Node.PARAM.NODE(Node.GEOMETRY.POINT),
    weight_column : Node.PARAM.STRING,
    category_column : Node.PARAM.STRING
};

var WeightedCentroid  = Node.create(TYPE, PARAMS, {cache: true});

module.exports = WeightedCentroid;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

var weightedCentroidTemplate = dot.template([
    'SELECT the_geom, class',
    'FROM cdb_crankshaft.CDB_WeightedMean(',
    '  $weightedmean_query${{=it.query}}$weightedmean_query$,',
    '  \'{{=it.weight_column}}\',',
    '  \'{{=it.category_column}}\'',
    ')'
].join('\n'));

function query(it) {
    return weightedCentroidTemplate(it);
}

WeightedCentroid.prototype.sql = function(){
    return query({
        query : this.source.getQuery(),
        weight_column : this.weight_column,
        category_column : this.category_column
    });
};

Fix too long line issue


import { endpoint } from 'app/api';
import asyncActionCreator from './asyncActionCreator';

export const ingestDocument = asyncActionCreator(
  (collectionId, metadata, file, onUploadProgress, cancelToken) => async () => {
    const formData = new FormData();
    if (file) {
      formData.append('file', file);
    }
    formData.append('meta', JSON.stringify(metadata));
    const config = {
      onUploadProgress,
      headers: {
        'content-type': 'multipart/form-data',
      },
      params: { sync: true },
      cancelToken,
    };
    const response = await endpoint.post(
      `collections/${collectionId}/ingest`,
      formData,
      config
    );
    return { ...response.data };
  },
  { name: 'INGEST_DOCUMENT' }
);

import { endpoint } from 'app/api';
import asyncActionCreator from './asyncActionCreator';

export const ingestDocument = asyncActionCreator(
  (collectionId, metadata, file, onUploadProgress, cancelToken) => async () => {
    const formData = {
      meta: JSON.stringify(metadata),
      file: file,
    };

    const config = {
      onUploadProgress,
      params: { sync: true },
      cancelToken,
    };

    const response = await endpoint.postForm(
      `collections/${collectionId}/ingest`,
      formData,
      config
    );

    return { ...response.data };
  },
  { name: 'INGEST_DOCUMENT' }
);

Use automatic form data serialization


'use babel';

const init = () => {
  const copyEnabled = () => atom.config.get('remote-ftp.context.enableCopyFilename');
  const contextMenu = {
    '.remote-ftp-view .entries.list-tree:not(.multi-select) .directory .header': {
      enabled: copyEnabled(),
      command: [{
        label: 'Copy name',
        command: 'remote-ftp:copy-name',
      }, {
        type: 'separator',
      }],
    },
    '.remote-ftp-view .entries.list-tree:not(.multi-select) .file': {
      enabled: copyEnabled(),
      command: [{
        label: 'Copy filename',
        command: 'remote-ftp:copy-name',
      }, {
        type: 'separator',
      }],
    },
  };
  return contextMenu;
};

export default init;

'use babel';

const init = () => {
  const contextMenu = {
    '.remote-ftp-view .entries.list-tree:not(.multi-select) .directory': {
      enabled: atom.config.get('remote-ftp.context.enableCopyFilename'),
      command: [{
        label: 'Copy name',
        command: 'remote-ftp:copy-name',
      }, {
        type: 'separator',
      }],
    },
    '.remote-ftp-view .entries.list-tree:not(.multi-select) .file': {
      enabled: atom.config.get('remote-ftp.context.enableCopyFilename'),
      command: [{
        label: 'Copy filename',
        command: 'remote-ftp:copy-name',
      }, {
        type: 'separator',
      }],
    },
  };
  return contextMenu;
};

export default init;

Fix directory "Copy name" function


(function (angular) {
    "use strict";

	var module = angular.module('net.enzey.services', []);

	module.service('nzService', function ($document, $timeout) {
		// position flyout

		var getChildElems = function(elem) {
			var childElems = [];
			elem = angular.element(elem);
			var children = elem.children();
			for (var i=0; i < children.length; i++) {
				getChildElems(children[i]).forEach(function(childElem) {
					childElems.push(childElem);
				});
			}
			childElems.push(elem[0]);

			return childElems;
		};

		this.registerClickAwayAction = function(contextElem, clickAwayAction) {
			var wrappedClickAwayAction = null;
			wrappedClickAwayAction  = function(event) {
				if (getChildElems(contextElem).indexOf(event.target) === -1) {
					$document.off('click', wrappedClickAwayAction);
					clickAwayAction(event);
				}
			};
			$timeout(function() {
				$document.on('click', wrappedClickAwayAction);
			});
		};

	});

})(angular);

(function (angular) {
    "use strict";

	var module = angular.module('net.enzey.services', []);

	module.service('nzService', function ($document, $timeout) {
		// position flyout

		var getChildElems = function(elem) {
			var childElems = [];
			elem = angular.element(elem);
			var children = elem.children();
			for (var i=0; i < children.length; i++) {
				getChildElems(children[i]).forEach(function(childElem) {
					childElems.push(childElem);
				});
			}
			childElems.push(elem[0]);

			return childElems;
		};

		this.registerClickAwayAction = function(clickAwayAction) {
			var wrappedClickAwayAction = null;
			var parentElems = [];
			for (var i = 1; i < arguments.length; i++) {
				parentElems.push(arguments[i]);
			}
			wrappedClickAwayAction  = function(event) {
				var allElements = [];
				parentElems.forEach(function(parentElem) {
					getChildElems(parentElem).forEach(function (elem) {
						allElements.push(elem);
					});
				});
				if (allElements.indexOf(event.target) === -1) {
					$document.off('click', wrappedClickAwayAction);
					clickAwayAction(event);
				}
			};
			$timeout(function() {
				$document.on('click', wrappedClickAwayAction);
			});
		};

	});

})(angular);

Allow multiple elements, and their children, to be watched to determine if the clickAwayAction should be called.


module.exports = function (licenseContent, done) {
  var thisYear = (new Date()).getFullYear();
  var latestYear, originalYearInfo, updatedYearInfo, match, updatedLicenseContent;

  match = licenseContent.match(/Copyright \(c\) (\d{4})\s*[~-]\s*(\d{4})/);
  if (match) {
    latestYear = match[2];

    if (parseInt(latestYear) < thisYear) {
      originalYearInfo = match[0];
      updatedYearInfo = originalYearInfo.replace(latestYear, thisYear);

      updatedLicenseContent = licenseContent
                                  .replace(originalYearInfo, updatedYearInfo);

      done(null, updatedLicenseContent, originalYearInfo, updatedYearInfo);
      return;
    }
  } else {
    match = licenseContent.match(/Copyright \(c\) (\d{4})/);
    latestYear = match[1];

    if (parseInt(latestYear) < thisYear) {
      originalYearInfo = match[0];
      updatedYearInfo = originalYearInfo + '-' + thisYear;

      updatedLicenseContent = licenseContent
                              .replace(originalYearInfo, updatedYearInfo);

      done(null, updatedLicenseContent, originalYearInfo, updatedYearInfo);
      return;
    }
  }

  // Otherwise update is not needed
  done();
};

module.exports = function (licenseContent, done) {
  var thisYear = (new Date()).getFullYear();
  var latestYear, originalYearInfo, updatedYearInfo, match, updatedLicenseContent;

  match = licenseContent.match(/Copyright \(c\) (\d{4})\s*[~-]\s*(\d{4})/);
  if (match) {
    latestYear = match[2];

    if (parseInt(latestYear) < thisYear) {
      originalYearInfo = match[0];
      updatedYearInfo = originalYearInfo.replace(latestYear, thisYear);

      updatedLicenseContent = licenseContent
                                  .replace(originalYearInfo, updatedYearInfo);

      done(null, updatedLicenseContent, originalYearInfo, updatedYearInfo);
      return;
    }
  } else {
    match = licenseContent.match(/Copyright \(c\) (\d{4})/);
    if (match) {
      latestYear = match[1];

      if (parseInt(latestYear) < thisYear) {
        originalYearInfo = match[0];
        updatedYearInfo = originalYearInfo + '-' + thisYear;

        updatedLicenseContent = licenseContent
                                .replace(originalYearInfo, updatedYearInfo);

        done(null, updatedLicenseContent, originalYearInfo, updatedYearInfo);
        return;
      }
    }
  }

  // Otherwise update is not needed
  done();
};

Check match exists before extracting latestYear


'use strict';

/**
 * @ngdoc function
 * @name dockstore.ui.controller:NavbarCtrl
 * @description
 * # NavbarCtrl
 * Controller of the dockstore.ui
 */
angular.module('dockstore.ui')
  .controller('NavbarCtrl', [
    '$scope',
    '$rootScope',
    '$auth',
    '$location',
    'UserService',
    'NotificationService',
    function ($scope, $rootScope, $auth, $location,
                UserService, NtfnService) {

      $scope.userObj = UserService.getUserObj();

      $scope.isAuthenticated = function() {
        return $auth.isAuthenticated();
      };

      $scope.isHomePage = function() {
        return ($location.url() === '/');
      };

      $scope.logout = function() {
        UserService.logout();
      };

      $scope.$watch('searchQuery', function(newValue, oldValue) {
        $rootScope.searchQuery = newValue;
      });

      $scope.$on('$routeChangeStart', function(event, next, current) {
        if ($location.url().indexOf('/search') === -1) {
          $scope.searchQuery = '';
        }
      });

  }]).filter('shortenString', function() {
    return function (string, scope) {
      if (string.length > 10) {
        return string.substring(0,9) + '...';
      } else {
        return string;
      }
    };
  });

'use strict';

/**
 * @ngdoc function
 * @name dockstore.ui.controller:NavbarCtrl
 * @description
 * # NavbarCtrl
 * Controller of the dockstore.ui
 */
angular.module('dockstore.ui')
  .controller('NavbarCtrl', [
    '$scope',
    '$rootScope',
    '$auth',
    '$location',
    'UserService',
    'NotificationService',
    function ($scope, $rootScope, $auth, $location,
                UserService, NtfnService) {

      $scope.userObj = UserService.getUserObj();

      $scope.isAuthenticated = function() {
        return $auth.isAuthenticated();
      };

      $scope.isHomePage = function() {
        return ($location.url() === '/');
      };

      $scope.logout = function() {
        UserService.logout();
      };

      $scope.$watch('searchQuery', function(newValue, oldValue) {
        $rootScope.searchQuery = newValue;
      });

      $scope.$on('$routeChangeStart', function(event, next, current) {
        if ($location.url().indexOf('/search') === -1) {
          $scope.searchQuery = '';
        }
      });

  }]).filter('shortenString', function() {
    return function (string, scope) {
      if (string != null && string.length > 10) {
        return string.substring(0,9) + '...';
      } else {
        return string;
      }
    };
  });

Handle error case for username shortening


import {Table} from 'apache-arrow';

const RowIndex = Symbol('rowIndex');

export default function arrow(data) {
  const table = Table.from(Array.isArray(data) ? data : [data]),
        proxy = rowProxy(table),
        rows = Array(table.length);

  table.scan(i => rows[i] = proxy(i));

  return rows;
}

arrow.responseType = 'arrayBuffer';

function rowProxy(table) {
  const fields = table.schema.fields.map(d => d.name),
        Row = function(index) { this[RowIndex] = index; },
        proto = Row.prototype;

  fields.forEach(name => {
    const column = table.getColumn(name);

    // skip columns with duplicate names
    if (proto.hasOwnProperty(name)) return;

    Object.defineProperty(proto, name, {
      get: function() {
        return column.get(this[RowIndex]);
      },
      set: function() {
        throw Error('Can not overwrite Arrow data field values.');
      },
      enumerable: true
    });
  });

  return i => new Row(i);
}

import {Table} from 'apache-arrow';

const RowIndex = Symbol('rowIndex');

export default function arrow(data) {
  const table = Table.from(Array.isArray(data) ? data : [data]),
        proxy = rowProxy(table),
        rows = Array(table.length);

  table.scan(i => rows[i] = proxy(i));

  return rows;
}

arrow.responseType = 'arrayBuffer';

function rowProxy(table) {
  const fields = table.schema.fields.map(d => d.name),
        Row = function(index) { this[RowIndex] = index; },
        proto = Row.prototype;

  fields.forEach((name, index) => {
    const column = table.getColumnAt(index);

    // skip columns with duplicate names
    if (proto.hasOwnProperty(name)) return;

    Object.defineProperty(proto, name, {
      get: function() {
        return column.get(this[RowIndex]);
      },
      set: function() {
        throw Error('Arrow field values can not be overwritten.');
      },
      enumerable: true
    });
  });

  return i => new Row(i);
}

Use indices for faster column lookup.


/* jshint node:true */
'use strict';
module.exports = function (grunt) {

  var config = {
    pkg: grunt.file.readJSON('package.json'),
    srcDir: 'src',
    destDir: 'dist',
    tempDir: 'tmp',
  };

  // load plugins
  require('load-grunt-tasks')(grunt);

  // load task definitions
  grunt.loadTasks('tasks');

  // Utility function to load plugin configurations into an object
  function loadConfig(path) {
    var object = {};
    require('glob').sync('*', {cwd: path}).forEach(function(option) {
      object[option.replace(/\.js$/,'')] = require(path + option)(config);
    });
    return object;
  }

  // Merge that object with what with whatever we have here
  grunt.util._.extend(config, loadConfig('./tasks/options/'));

  // pass the config to grunt
  grunt.initConfig(config);

};

/* jshint node:true */
'use strict';
module.exports = function (grunt) {

  var config = {
    pkg: grunt.file.readJSON('package.json'),
    srcDir: 'src',
    destDir: 'dist',
    tempDir: 'tmp',
  };

  // load plugins
  require('load-grunt-tasks')(grunt);

  // load task definitions
  grunt.loadTasks('tasks');

  // Utility function to load plugin settings into config
  function loadConfig(config,path) {
    require('glob').sync('*', {cwd: path}).forEach(function(option) {
      var key = option.replace(/\.js$/,'');
      // If key already exists, extend it. It is your responsibility to avoid naming collisions
      config[key] = config[key] || {};
      grunt.util._.extend(config[key], require(path + option)(config));
    });
    // technically not required
    return config;
  }

  // Merge that object with what with whatever we have here
  loadConfig(config,'./tasks/options/');

  // pass the config to grunt
  grunt.initConfig(config);

};

Update loadConfig to allow duplicates


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

const Config = require('./Config');

class WebInterface {

  constructor(state) {
    this.state = state;
    this.port  = Config.get('webPort') || 9000;
  }

  init() {
    router.get('/', (req, res) => res.json(this.state));

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

    app.listen(this.port);
    util.log(`WEB: Web API activated and running on port ${this.port}.`);

  }

}

module.exports = WebInterface;

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

const Config = require('./Config');

class WebInterface {

  constructor(state) {
    this.state = state;
    this.port  = Config.get('webPort') || 9000;
  }

  init() {

    // Routes for the API's GET response.
    router.get('/',        (req, res) => res.json(this.state));
    router.get('/npcs',    (req, res) => res.json(this.state.MobFactory.npcs));
    router.get('/players', (req, res) => res.json(this.state.PlayerManager.players));
    router.get('/items',   (req, res) => res.json(this.state.ItemManager.items));
    router.get('/rooms',   (req, res) => res.json(this.state.RoomManager.rooms));
    router.get('/help',    (req, res) => res.json(this.state.HelpManager.helps));

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

    app.listen(this.port);
    util.log(`WEB: Web API activated and running on port ${this.port}.`);

  }

}

module.exports = WebInterface;

Add routes for various get responses.


(function (context) {
  var _SEMAPOHRES = {};

  var Semaphore = function (key) {
    this.key = key;
    if (_SEMAPOHRES[this.key] == undefined)
      _SEMAPOHRES[this.key] = false;
    return this;
  };

  Semaphore.prototype.isLocked = function() {
    return _SEMAPOHRES[this.key];
  };

  Semaphore.prototype.lock = function() {
    _SEMAPOHRES[this.key] = true;
    return this;
  };

  Semaphore.prototype.unlock = function() {
    _SEMAPOHRES[this.key] = false;
    return this;
  };

  Semaphore.wrap = function (key, callback) {
    var semaphore = new this(key);
    if (!semaphore.isLocked()) {
      semaphore.lock()
      callback(semaphore);
    }
  };

  Semaphore.wrap = function (key, callback) {
    var semaphore = new this(key);
    if (!semaphore.isLocked()) {
      semaphore.lock()
      callback(semaphore);
    }
  };

  var conflictingSemaphore = context.Semaphore;

  Semaphore.noConflict = function () {
    context.Semaphore = conflictingSemaphore;
    return Semaphore;
  };

  context.Semaphore = Semaphore;
});

(function (context) {
  var _SEMAPOHRES = {};

  var Semaphore = function (key) {
    this.key = key;
    if (_SEMAPOHRES[this.key] == undefined)
      _SEMAPOHRES[this.key] = false;
    return this;
  };

  Semaphore.prototype.isLocked = function() {
    return _SEMAPOHRES[this.key];
  };

  Semaphore.prototype.lock = function() {
    _SEMAPOHRES[this.key] = true;
    return this;
  };

  Semaphore.prototype.unlock = function() {
    _SEMAPOHRES[this.key] = false;
    return this;
  };

  Semaphore.wrap = function (key, callback) {
    var semaphore = new this(key);
    if (!semaphore.isLocked()) {
      semaphore.lock()
      callback(semaphore);
    }
  };

  var conflictingSemaphore = context.Semaphore;

  Semaphore.noConflict = function () {
    context.Semaphore = conflictingSemaphore;
    return Semaphore;
  };

  context.Semaphore = Semaphore;
})(this);

Remove second Semaphore.wrap and pass in this.


/*jshint node:true*/

var RSVP = require('rsvp');

module.exports = {
  description: 'Install ember-cli-react dependencies into your app.',

  normalizeEntityName: function() {},

  // Install react into host app
  afterInstall: function() {
    return RSVP.all([
      this.addPackageToProject("ember-browserify", "^1.1.7"),
      this.addPackageToProject("react", "^0.14.7"),
      this.addPackageToProject("react-dom", "^0.14.7")
    ]);
  }
};

/*jshint node:true*/

var RSVP = require('rsvp');
var pkg = require('../../package.json');

function getDependencyVersion(packageJson, name) {
  var dependencies = packageJson.dependencies;
  var devDependencies = packageJson.devDependencies;

  return dependencies[name] || devDependencies[name];
}

module.exports = {
  description: 'Install ember-cli-react dependencies into your app.',

  normalizeEntityName: function() {},

  // Install react into host app
  afterInstall: function() {
    return RSVP.all([
      this.addPackageToProject("ember-browserify", getDependencyVersion(pkg, "ember-browserify")),
      this.addPackageToProject("react", getDependencyVersion(pkg, "react")),
      this.addPackageToProject("react-dom", getDependencyVersion(pkg, "react-dom"))
    ]);
  }
};

Synchronize packages version in blueprint


import React, { Component, PropTypes } from 'react';
import Panel from './Panel';
import idSafeName from '../helpers/idSafeName';

class Panels extends Component {
    render () {
        const { data, selectedIndex } = this.props;

        if (!data.length) {
            return null;
        }

        return (
            <div>
                {data.map((panel, index) => {
                    const id = idSafeName(panel.label, index);

                    return (
                        <Panel
                            key={id}
                            className="tabs__panels"
                            content={panel.content}
                            id={id}
                            index={index}
                            selectedIndex={selectedIndex}
                        />
                    );
                })}
            </div>
        );
    }
}

Panels.propTypes = {
    data: PropTypes.array,
    selectedIndex: PropTypes.number
};

export default Panels;

import React, { Component, PropTypes } from 'react';
import Panel from './Panel';
import idSafeName from '../helpers/idSafeName';

class Panels extends Component {
    render () {
        const { data, selectedIndex } = this.props;

        if (!data.length) {
            return null;
        }

        return (
            <div className="tabs__panels">
                {data.map((panel, index) => {
                    const id = idSafeName(panel.label, index);

                    return (
                        <Panel
                            key={id}
                            content={panel.content}
                            id={id}
                            index={index}
                            selectedIndex={selectedIndex}
                        />
                    );
                })}
            </div>
        );
    }
}

Panels.propTypes = {
    data: PropTypes.array,
    selectedIndex: PropTypes.number
};

export default Panels;

Put .tabs__panels on correct element


import {Configure} from './configure';

export function configure(aurelia, configCallback) {
    var instance = aurelia.container.get(Configure);

    // Do we have a callback function?
    if (configCallback !== undefined && typeof(configCallback) === 'function') {
        configCallback(instance);
    }

    return new Promise((resolve, reject) => {
        instance.loadConfig().then(data => {
            instance.setAll(data);
            resolve();
        });
    }).catch(() => {
        reject(new Error('Configuration file could not be loaded'));
    });
}

export {Configure};

import {Configure} from './configure';

export function configure(aurelia, configCallback) {
    var instance = aurelia.container.get(Configure);

    // Do we have a callback function?
    if (configCallback !== undefined && typeof(configCallback) === 'function') {
        configCallback(instance);
    }

    return new Promise((resolve, reject) => {
        instance.loadConfig().then(data => {
            instance.setAll(data);

            // Gets the current pathName to determine dynamic environments (if defined)
            instance.check();
            resolve();
        });
    }).catch(() => {
        reject(new Error('Configuration file could not be loaded'));
    });
}

export {Configure};

Call the check function during configuration phase


import Component from './class/Component';
import render from './core/render';
import renderToString from './core/renderToString';
import unmountComponentAtNode from './core/unmountComponentAtNode';
import FragmentValueTypes from './enum/fragmentValueTypes';
import TemplateTypes from './enum/templateTypes';
import createFragment from './core/createFragment';
import createTemplate from './core/createTemplate';
import clearDomElement from './core/clearDomElement';
import createRef from './core/createRef';
import registerAttributes from './template/registerAttributeHandlers';
import { registerSetupHooks } from './events/hooks/createListenerArguments';
import { registerEventHooks } from './events/hooks/listenerSetup';

module.exports = {
    Component,
    render,
    renderToString,
    createFragment,
    createTemplate,
    unmountComponentAtNode,
    FragmentValueTypes,
    TemplateTypes,
    clearDomElement,
    createRef,

	/**
     * 3rd party
     */
    registerAttributes,
    registerSetupHooks,
    registerEventHooks
};

export { default as Component } from './class/Component';
export { default as render } from './core/render';
export { default as renderToString } from './core/renderToString';
export { default as unmountComponentAtNode } from './core/unmountComponentAtNode';
export { default as FragmentValueTypes } from './enum/fragmentValueTypes';
export { default as TemplateTypes } from './enum/templateTypes';
export { default as createFragment } from './core/createFragment';
export { default as createTemplate } from './core/createTemplate';
export { default as clearDomElement } from './core/clearDomElement';
export { default as createRef } from './core/createRef';
export { default as registerAttributes } from './template/registerAttributeHandlers';
export { registerSetupHooks } from './events/hooks/createListenerArguments';
export { registerEventHooks } from './events/hooks/listenerSetup';

Use ES6 export instead of CJS


import { polygonCentroid, distance } from "./math.js";

// With 8 or fewer shapes, find the best permutation
// Skip if array is huge (9+ shapes)
export default function(start, end) {
  let distances = start.map(p1 => end.map(p2 => squaredDistance(p1, p2))),
    order = bestOrder(start, end, distances);

  if (start.length > 8) {
    return start.map((d, i) => i);
  }
  return bestOrder(start, end, distances);
}

export function bestOrder(start, end, distances) {
  let min = Infinity,
    best = start.map((d, i) => i);

  function permute(arr, order = [], sum = 0) {
    for (let i = 0; i < arr.length; i++) {
      let cur = arr.splice(i, 1),
        dist = distances[cur[0]][order.length];
      if (sum + dist < min) {
        if (arr.length) {
          permute(arr.slice(), order.concat(cur), sum + dist);
        } else {
          min = sum + dist;
          best = order.concat(cur);
        }
      }
      if (arr.length) {
        arr.splice(i, 0, cur[0]);
      }
    }
  }

  permute(best);
  return best;
}

function squaredDistance(p1, p2) {
  let d = distance(polygonCentroid(p1), polygonCentroid(p2));
  return d * d;
}

import { polygonCentroid, distance } from "./math.js";

// With 8 or fewer shapes, find the best permutation
// Skip if array is huge (9+ shapes)
export default function(start, end) {
  let distances = start.map(p1 => end.map(p2 => squaredDistance(p1, p2)));
  if (start.length > 8) {
    return start.map((d, i) => i);
  }
  return bestOrder(start, end, distances);
}

export function bestOrder(start, end, distances) {
  let min = Infinity,
    best = start.map((d, i) => i);

  function permute(arr, order = [], sum = 0) {
    for (let i = 0; i < arr.length; i++) {
      let cur = arr.splice(i, 1),
        dist = distances[cur[0]][order.length];
      if (sum + dist < min) {
        if (arr.length) {
          permute(arr.slice(), order.concat(cur), sum + dist);
        } else {
          min = sum + dist;
          best = order.concat(cur);
        }
      }
      if (arr.length) {
        arr.splice(i, 0, cur[0]);
      }
    }
  }

  permute(best);
  return best;
}

function squaredDistance(p1, p2) {
  let d = distance(polygonCentroid(p1), polygonCentroid(p2));
  return d * d;
}

Remove unused call to 'bestOrder'


require('rootpath')();
const Hapi = require('hapi');
const { describe, it, expect, sinon, before, after, beforeEach, afterEach } = require('tests/helper');
const route = require('app/features/events');
const eventHandler = require('app/features/events/eventHandler');

describe('Unit | Route | Event Index ', function() {

    let server;

    beforeEach(() => {
        server = require('server').BootStrapTestHelper('events');
    });

    afterEach(() => {
        server.stop();
    });

    describe('Server', () => {

        it('should have an object, version, and name attribute', () => {
            // then
            expect(route.register.attributes).to.exist;
            expect(route.register.attributes).to.be.an('object');
            expect(route.register.attributes.name).to.equal('events-api');
            expect(route.register.attributes).to.have.property('version');
        });

    });

    describe('Route POST /api/events', () => {

        before(() => {
            sinon.stub(eventHandler, 'create').callsFake((request, reply) => reply('ok'));
        });

        after(() => {
            eventHandler.create.restore();
        });

        it('should exist', () => {
            // when
            return server.inject({
                method: 'POST',
                url: '/api/events',
                payload: {
                    username: 'Flo'
                }
            }).then((res) => {
                // then
                expect(res.statusCode).to.equal(200);
            });
        });
    });
});

require('rootpath')();
const Hapi = require('hapi');
const { describe, it, expect, sinon, before, after, beforeEach, afterEach } = require('tests/helper');
const route = require('app/features/events');
const eventHandler = require('app/features/events/eventHandler');

describe('Unit | Route | Event Index ', function() {

    let server;

    beforeEach(() => {
        server = require('server').BootStrapTestHelper('events');
    });

    afterEach(() => {
        server.stop();
    });

    describe('Server', () => {

        it('should have an object, version, and name attribute', () => {
            // then
            expect(route.register.attributes).to.exist;
            expect(route.register.attributes).to.be.an('object');
            expect(route.register.attributes.name).to.equal('events-api');
            expect(route.register.attributes).to.have.property('version');
        });

    });

    describe('Route POST /api/events', () => {

        before(() => {
            sinon.stub(eventHandler, 'create').callsFake((request, reply) => reply('ok'));
        });

        after(() => {
            eventHandler.create.restore();
        });

        it('should exist', () => {
            // when
            return server.inject({
                method: 'POST',
                url: '/api/events',
                payload: {
                    host: {},
                    event: {}
                }
            }).then((res) => {
                // then
                expect(res.statusCode).to.equal(200);
            });
        });
    });
});

Add test when error is unknown


var Timer = (function(Util) {
  'use strict';

  // Internal constants for the various timer states.
  var Waiting = 0, Inspecting = 1, Ready = 2, Running = 3, Delay = 4;

  var state = Waiting;
  var startTime = undefined, endTime = undefined, solveTime = undefined;
  var intervalID = undefined;

  function isWaiting() { return state == Waiting; }
  function isReady() { return state == Ready; }
  function isRunning() { return state == Running; }

  function runningEmitter() {
    Event.emit("timer/running");
  }

  function trigger() {
    if (isWaiting()) {
      state = Ready;
    } else if (isReady()) {
      state = Running;
      startTime = Util.getMilli();
      intervalID = setInterval(runningEmitter, 100);
    } else if (isRunning()) {
      state = Waiting;
      endTime = Util.getMilli();
      clearInterval(intervalID);
    }
  }

  function getCurrent() {
    return Util.getMill() - startTime;
  }

  return {
    trigger: trigger,
    getCurrent: getCurrent
  };
});

var Timer = (function(Util) {
  'use strict';

  // Internal constants for the various timer states.
  var Waiting = 0, Inspecting = 1, Ready = 2, Running = 3, Delay = 4;

  var state = Waiting;
  var startTime = undefined, endTime = undefined, solveTime = undefined;
  var intervalID = undefined;

  function isWaiting() { return state === Waiting; }
  function isReady() { return state === Ready; }
  function isRunning() { return state === Running; }

  function onWaiting() {
    endTime = Util.getMilli();
    clearInterval(intervalID);
  }

  function onRunning() {
    startTime = Util.getMilli();
    intervalID = setInterval(runningEmitter, 100);
  }

  function setState(new_state) {
    state = new_state;
    switch(state) {
    case Waiting: onWaiting(); break;
    case Running: onRunning(); break;
    }
  }

  function runningEmitter() {
    Event.emit("timer/running");
  }

  function trigger() {
    if (isWaiting()) {
      setState(Ready);
    } else if (isReady()) {
      setState(Running);
    } else if (isRunning()) {
      setState(Waiting);
    }
  }

  function getCurrent() {
    return Util.getMill() - startTime;
  }

  return {
    trigger: trigger,
    getCurrent: getCurrent
  };
});

Move the functionality out of trigger(), to make it do as little as possible. Also, use '===' instead of '=='.


import upload from './upload';

import express from 'express';
import logger from 'winston';

const app = express();
export default app;

app.set('port', process.env.PORT || 3000);

logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, {'timestamp':true,});

app.use((req, res, next) => {  // eslint-disable-line no-unused-vars
  res.header('Access-Control-Allow-Origin', 'angeleandgus.com');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
});

app.use('/upload', upload);

app.use((err, req, res, next) => {
  const status = err.statusCode || err.status || 500;

  res.status(status);
  const ip = req.headers['x-forwarded-for'] ||
    req.connection.remoteAddress ||
    req.socket.remoteAddress ||
    req.connection.socket.remoteAddress;
  logger.error(`ip: ${ip} err: ${err}`);

  res.end(`Error ${status}: ${err.shortMessage}`);
  next(err);
});

app.listen(app.get('port'), () => {
  logger.info(`Server started: http://localhost:${app.get('port')}/`);
});

import upload from './upload';

import express from 'express';
import logger from 'winston';

const app = express();
export default app;

app.set('port', process.env.PORT || 3000);

logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, {'timestamp':true,});

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'angeleandgus.com');
  res.header('Access-Control-Allow-Headers', 'Content-Type');

  next();
});

app.use('/upload', upload);

app.use((err, req, res, next) => {
  const status = err.statusCode || err.status || 500;

  res.status(status);
  const ip = req.headers['x-forwarded-for'] ||
    req.connection.remoteAddress ||
    req.socket.remoteAddress ||
    req.connection.socket.remoteAddress;
  logger.error(`ip: ${ip} err: ${err}`);

  res.end(`Error ${status}: ${err.shortMessage}`);
  next(err);
});

app.listen(app.get('port'), () => {
  logger.info(`Server started: http://localhost:${app.get('port')}/`);
});

Fix endless loop in server


/*
 * CS3283/4 storage.js
 * This is a facade class for other components
 */

/**
 *
 *  CS3283/4 storage.js
 *  This class acts as a facade for other developers to access to the database.
 *  The implementation is a non-SQL local storage to support the WebApp.
 *
 */

const entitiesCreator = require('./create/entitiesCreator');

class Storage {
  static constructor() {}

  static initializeDatabase() {
    entitiesCreator.createUserTable();
    entitiesCreator.createOrganizationTable();
    entitiesCreator.createFolderTable();
    entitiesCreator.createFileManagerTable();
    entitiesCreator.clearDatabase();
  }
}

Storage.initializeDatabase();

Add initializeDatabase function facade class


const express = require('express')
const ERRORS = require('../../errors')
const User = require('../../models/User')
const utils = require('../../utils')
const router = express.Router()

router.post('/', register)
function register(req, res, next) {
    const { body: { username, password } } = req
    if (!username || !password) {
        next(ERRORS.MISSING_PARAMETERS(['username', 'password']))
    } else {
        User.register(username, password)
            .then(user => ({
                id: user.id,
                username: user.username,
                token: utils.genToken(user.id)
            }))
            .then(data => {
                res.status(201)
                res.json(data)
            })
            .catch(err => next(ERRORS.REGISTRATION_FAILED(err)))
    }
}

module.exports = router

const express = require('express')
const ERRORS = require('../../errors')
const User = require('../../models/User')
const utils = require('../../utils')
const router = express.Router()

router.post('/', register)
function register(req, res, next) {
    const { body: { username, password } } = req
    if (!username || !password) {
        next(ERRORS.MISSING_PARAMETERS(['username', 'password']))
    } else {
        User.register(username, password)
            .then(user => ({
                id: user.id,
                username: user.username,
                token: utils.genToken(user.id),
                createdAt: user.createdAt
            }))
            .then(data => {
                res.status(201)
                res.json(data)
            })
            .catch(err => next(ERRORS.REGISTRATION_FAILED(err)))
    }
}

module.exports = router

Fix missing parameter to pass tests


describe("Core Bliss", function () {
	"use strict";

	before(function() {
		fixture.setBase('tests/fixtures');
	});

	beforeEach(function () {
		this.fixture = fixture.load('core.html');
		document.body.innerHTML += this.fixture[0];
	});

	// testing setup
	it("has the fixture on the dom", function () {
		expect($('#fixture-container')).to.not.be.null;
	});

	it("has global methods and aliases", function() {
		expect(Bliss).to.exist;
		expect($).to.exist;
		expect($$).to.exist;

		expect($).to.equal(Bliss);
		expect($$).to.equal($.$);
	});
});

describe("Core Bliss", function () {
	"use strict";

	before(function() {
		fixture.setBase('tests/fixtures');
	});

	beforeEach(function () {
		this.fixture = fixture.load('core.html');
	});

	// testing setup
	it("has the fixture on the dom", function () {
		expect($('#fixture-container')).to.not.be.null;
	});

	it("has global methods and aliases", function() {
		expect(Bliss).to.exist;
		expect($).to.exist;
		expect($$).to.exist;

		expect($).to.equal(Bliss);
		expect($$).to.equal($.$);
	});
});

Remove appending of fixture to dom


// This is the Link API
import Link from 'next/link'

const Index = () => (

    <Link href="/about">
      About Page
    </Link>

Hello Next.js

)

export default Index

Add style to anchor link


import hopp from 'hopp'

export const css =
  hopp([ 'src/css/*.css' ])
    .dest('dist/css')

export const js =
  hopp([ 'src/js/*.js' ]) // create fs streams
    // .babel()              // pipe to (create babel stream)
    .dest('dist/js')         // pipe to (create dest stream)

export default [
  'js',
  'css'
]

import hopp from 'hopp'

export const css =
  hopp([ 'src/css/*.css' ])
    .dest('dist/css')

export const js =
  hopp([ 'src/js/*.js' ])
    .dest('dist/js')

export const watch =
  hopp.watch([ 'js', 'css' ])

export default [
  'js',
  'css'
]

Add sample watch task to example


var irc = require('irc'); // IRC Client
require('js-yaml'); // JavaScript YAML parser (for settings)

// Import settings file
var settings = require('./config/bot.yaml');

var client = new irc.Client(settings.server, settings.nick, {
	userName: settings.username,
	realName: settings.realname,
	port: settings.port,
	channels: [settings.channel],
});

// Original IRC output to console (for debugging)
client.addListener('raw', function (message) {
	if (message.server) {
		console.log(':' + message.server + ' ' + message.command + ' ' + message.args.join(' :') );
	} else {
		console.log(':' + message.nick + '!' + message.user + '@' + message.host + ' ' +
		message.command + ' ' + message.args.join(' :') );
	}
});

var irc = require('irc'); // IRC Client
require('js-yaml'); // JavaScript YAML parser (for settings)

// Gr__dirnameab configuration files
var settings = require(__dirname + '/config/bot.yaml');
var werewolf = require(__dirname + '/config/werewolf.yaml');

var client = new irc.Client(settings.server, settings.nick, {
	userName: settings.username,
	realName: settings.realname,
	port: settings.port,
	channels: [settings.channel],
});

// Original IRC output to console (for debugging)
client.addListener('raw', function (message) {
	if (message.server) {
		console.log(':' + message.server + ' ' + message.command + ' ' + message.args.join(' :') );
	} else {
		console.log(':' + message.nick + '!' + message.user + '@' + message.host + ' ' +
		message.command + ' ' + message.args.join(' :') );
	}
});

// The Locale handler
var Locale = require(__dirname + '/components/locale.js');

var locale = Locale.createInstance(__dirname + '/locales', '.yaml');
locale.setLanguage(settings.language);

setTimeout(function() {
	console.log(locale.languages);
}, 100);

Use the new locale handler


import bunyan from 'bunyan';
import Promise from 'bluebird';
import SDC from 'statsd-client';

const logger = bunyan.createLogger({name: 'Stats'});

export default class Stats {
  constructor(config) {
    const stats = config.statsd;
    logger.info('Starting StatsD client.');
    this._statsd = new SDC({
      host: stats.host
    });
  }

  /**
   * Get the underlying stats client.
   * You should not rely on the type of this, only that it can be used
   * as a middleware for express.
   **/
  get client() {
    return this._statsd;
  }

  close() {
    this._statsd.close();
  }

  counter(name, value = 1) {
    logger.info('Updating counter %s by %s.', name, value);
    this._statsd.counter(name, value);
  }

  gauge(name, value) {
    logger.info('Gauging %s at %s.', name, value);
    this._statsd.gauge(name, value);
  }
}

import bunyan from 'bunyan';
import Promise from 'bluebird';
import SDC from 'statsd-client';

const logger = bunyan.createLogger({name: 'Stats'});

export default class Stats {
  constructor(config) {
    const stats = config.statsd;
    logger.info('Starting StatsD client.');
    this._statsd = new SDC({
      host: stats.host
    });
  }

  /**
   * Get the underlying stats client.
   * You should not rely on the type of this, only that it can be used
   * as a middleware for express.
   **/
  get client() {
    return this._statsd;
  }

  close() {
    this._statsd.close();
  }

  counter(name, value = 1) {
    logger.debug('Updating counter %s by %s.', name, value);
    this._statsd.counter(name, value);
  }

  gauge(name, value) {
    logger.debug('Gauging %s at %s.', name, value);
    this._statsd.gauge(name, value);
  }
}

Make stats quieter in logs.


import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Form, Label, Input } from 'semantic-ui-react';

class FormInput extends Component {
  componentWillReceiveProps(nextProps) {
    const {
      input: { value, onChange },
      meta: { visited },
      defaultValue
    } = nextProps;
    if (!value && !visited && defaultValue) onChange(defaultValue);
  }

  render() {
    const {
      input,
      meta: { error, touched },
      readOnly,
      width,
      label,
      defaultValue,
      required,
      errorPosition,
      inline,
      ...rest
    } = this.props;

    const hasError = touched && Boolean(error);

    if (readOnly) {
      return (

          {input && input.value && input.value.toLocaleString()}

      );
    }

    return (
      <Form.Field
        error={hasError}
        width={width}
        required={required}
        style={{ position: 'relative' }}
        inline={inline}
      >
        {label && {label}}
        <Input
          {...input}
          {...rest}
          value={input.value || ''}
          error={hasError}
        />

        {hasError && (

            {error}

        )}
      </Form.Field>
    );
  }
}

export default FormInput;

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Form, Label, Input } from 'semantic-ui-react';

class FormInput extends Component {
  componentWillReceiveProps(nextProps) {
    const {
      input: { value, onChange },
      meta: { visited },
      defaultValue
    } = nextProps;
    if (!value && !visited && defaultValue) onChange(defaultValue);
  }

  render() {
    const {
      input,
      meta: { error, touched },
      readOnly,
      width,
      label,
      defaultValue,
      required,
      inline,
      errorMessageStyle,
      ...rest
    } = this.props;

    const hasError = touched && Boolean(error);

    if (readOnly) {
      return (

          {input && input.value && input.value.toLocaleString()}

      );
    }

    return (
      <Form.Field
        error={hasError}
        width={width}
        required={required}
        inline={inline}
      >
        {label && {label}}
        <Input
          {...input}
          {...rest}
          value={input.value || ''}
          error={hasError}
        />

        {hasError && (

            {error}

        )}
      </Form.Field>
    );
  }
}

export default FormInput;

Add ability to customize error message styles


import React from 'react';

class PostsNew extends React.Component {
  render() {
    return (
      <div className='posts-new'>
        Posts new
      </div>
    );
  }
}

export default PostsNew;

import React from 'react';
import { Field, reduxForm } from 'redux-form';

class PostsNew extends React.Component {
  render() {
    return (
      <form className='posts-new'>
        <Field
          name='title'
          component={}
        />
      </form>
    );
  }
}

export default reduxForm({
  form: 'PostsNewForm'
})(PostsNew);

Add initial posts new form elements


TestHelpers.commonWidgetTests( "tooltip", {
	defaults: {
		content: function() {},
		disabled: false,
		hide: true,
		items: "[title]:not([disabled])",
		position: {
			my: "left top+15",
			at: "left bottom",
			collision: "flipfit flipfit"
		},
		show: true,
		tooltipClass: null,
		track: false,

		// callbacks
		close: null,
		create: null,
		open: null
	}
});

TestHelpers.commonWidgetTests( "tooltip", {
	defaults: {
		content: function() {},
		disabled: false,
		hide: true,
		items: "[title]:not([disabled])",
		position: {
			my: "left top+15",
			at: "left bottom",
			collision: "flipfit flip"
		},
		show: true,
		tooltipClass: null,
		track: false,

		// callbacks
		close: null,
		create: null,
		open: null
	}
});

Fix default for position option, follow-up to 1d9eab1.


var mongoose = require('mongoose');

var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;

var ORIGIN_TYPES = [
    'srv:coupledResource',
    'gmd:onLine'
];

var RESOURCE_TYPES = [
    'feature-type',
    'link',
    'atom-feed'
];

var RelatedResourceSchema = new Schema({

    type: { type: String, required: true, index: true, enum: RESOURCE_TYPES },

    updatedAt: { type: Date, required: true, index: true },
    // touchedAt: { type: Date, required: true },

    name: { type: String },

    /* Origin */
    originType: { type: String, enum: ORIGIN_TYPES, required: true, index: true },
    originId: { type: ObjectId, required: true, index: true },
    originCatalog: { type: ObjectId, ref: 'Service', index: true, sparse: true },

    /* Record */
    record: { type: String, required: true, index: true },

    /* FeatureType */
    featureType: {
        candidateName: { type: String },
        candidateLocation: { type: String },
        matchingName: { type: String, index: true, sparse: true },
        matchingService: { type: ObjectId, index: true, sparse: true }
    }

    /*  */
});

mongoose.model('RelatedResource', RelatedResourceSchema);

var mongoose = require('mongoose');

var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;

var ORIGIN_TYPES = [
    'srv:coupledResource',
    'gmd:onLine'
];

var RESOURCE_TYPES = [
    'feature-type',
    'link',
    'atom-feed'
];

var RelatedResourceSchema = new Schema({

    type: { type: String, required: true, index: true, enum: RESOURCE_TYPES },

    updatedAt: { type: Date, required: true, index: true },
    checking: { type: Boolean, index: true, sparse: true },

    name: { type: String },

    /* Origin */
    originType: { type: String, enum: ORIGIN_TYPES, required: true, index: true },
    originId: { type: ObjectId, required: true, index: true },
    originCatalog: { type: ObjectId, ref: 'Service', index: true, sparse: true },

    /* Record */
    record: { type: String, required: true, index: true },

    /* FeatureType */
    featureType: {
        candidateName: { type: String },
        candidateLocation: { type: String },
        matchingName: { type: String, index: true, sparse: true },
        matchingService: { type: ObjectId, index: true, sparse: true }
    }

});

/*
** Statics
*/
RelatedResourceSchema.statics = {

    markAsChecking: function (query, done) {
        this.update(query, { $set: { checking: true } }, { multi: true }, done);
    }

};

mongoose.model('RelatedResource', RelatedResourceSchema);

Add checking flag to RelatedResource model


var path = require('path');

module.exports = {
    /**
     * Path from which all relative webpack paths will be resolved.
     */
    context: path.resolve(__dirname),
    /**
     * Entry point to the application, webpack will bundle all imported modules.
     */
    entry: './src/index.ts',
    /**
     * Rule for which files should be transpiled via typescript loader.
     */
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: [{
                    loader: 'ts-loader'
                }]
            }
        ]
    },
    resolve: {
        /**
         * Resolve the following extensions when requiring/importing modules.
         */
        extensions: ['.ts', '.js']
    },
    /**
     * Specify output as an UMD library.
     */
    output: {
        path: 'build/dist',
        filename: 'baasic-sdk-javascript.js',
        library: 'baasicSdkJavaScript',
        libraryTarget: 'umd'
    }
}

var path = require('path');
var rootDir = path.resolve(__dirname);

function getRootPath(args) {
    args = Array.prototype.slice.call(arguments, 0);
    return path.join.apply(path, [rootDir].concat(args));
}

module.exports = {
    /**
     * Path from which all relative webpack paths will be resolved.
     */
    context: path.resolve(__dirname),
    /**
     * Entry point to the application, webpack will bundle all imported modules.
     */
    entry: './src/index.ts',
    /**
     * Rule for which files should be transpiled via typescript loader.
     */
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: [{
                    loader: 'ts-loader'
                }]
            }
        ]
    },
    resolve: {
        /**
         * Resolve the following extensions when requiring/importing modules.
         */
        extensions: ['.ts', '.js'],
        /**
         * Resolve modules using following folders.
         */
        modules: [getRootPath('src'), getRootPath('node_modules')]
    },
    /**
     * Specify output as an UMD library.
     */
    output: {
        path: 'build/dist',
        filename: 'baasic-sdk-javascript.js',
        library: 'baasicSdkJavaScript',
        libraryTarget: 'umd'
    }
}

Add module loading from src to webpack configuration.


import React from 'react';
import PropTypes from 'prop-types';
import * as action from '../../action/';
import Switch from '@material-ui/core/Switch';
import Typography from '@material-ui/core/Typography';
import { connect } from 'react-redux';

class SwitchResource extends React.Component {

  handleChange = (field, value) => {
    if (this.props.isWriteable === true) {
      this.props.toggleSwitch(this.props.objectID, this.props.instanceID, this.props.resource.resourceID, value);
    }
  };

  render () {
    return (
      <div>
        <Typography variant='subheading' align='center'>{this.props.resource.name}</Typography>
          <Switch
            checked={this.props.currentValue}
            onChange={this.handleChange.bind(this, 'switch')}
          />
      </div>
    );
  }
}

SwitchResource.propTypes = {
  currentValue: PropTypes.any,
  instanceID: PropTypes.number,
  isWriteable: PropTypes.bool,
  objectID: PropTypes.number,
  resource: PropTypes.object,
  toggleSwitch: PropTypes.func.isRequired
};

const mapStateToProps = (state) => {
  return {
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    toggleSwitch: (objectID, instanceID, resourceID, value) => dispatch(action.sendRequest(objectID, instanceID, resourceID, value))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(SwitchResource);

import React from 'react';
import PropTypes from 'prop-types';
import * as action from '../../action/';
import Switch from '@material-ui/core/Switch';
import Typography from '@material-ui/core/Typography';
import { connect } from 'react-redux';

class SwitchResource extends React.Component {

  handleChange = (field, value) => {
    if (this.props.isWriteable === true) {
      this.props.toggleSwitch(this.props.objectID, this.props.instanceID, this.props.resource.resourceID, this.props.currentValue);
    }
  };

  render () {
    return (
      <div>
        <Typography variant='subheading' align='center'>{this.props.resource.name}</Typography>
          <Switch
            checked={this.props.currentValue}
            onChange={this.handleChange.bind(this, 'switch')}
          />
      </div>
    );
  }
}

SwitchResource.propTypes = {
  currentValue: PropTypes.any,
  instanceID: PropTypes.number,
  isWriteable: PropTypes.bool,
  objectID: PropTypes.number,
  resource: PropTypes.object,
  toggleSwitch: PropTypes.func.isRequired
};

const mapStateToProps = (state) => {
  return {
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    toggleSwitch: (objectID, instanceID, resourceID, value) => dispatch(action.sendRequest(objectID, instanceID, resourceID, !value))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(SwitchResource);

Fix bug with unresponsive switch due to new framework


var DocsParser = require("../docsparser");
var xregexp = require('../xregexp').XRegExp;

function RustParser(settings) {
    DocsParser.call(this, settings);
}

RustParser.prototype = Object.create(DocsParser.prototype);

RustParser.prototype.setup_settings = function() {
    this.settings = {
        'curlyTypes': false,
        'typeInfo': false,
        'typeTag': false,
        'varIdentifier': '.*',
        'fnIdentifier':  '.*',
        'fnOpener': '^\\s*fn',
        'commentCloser': ' */',
        'bool': 'Boolean',
        'function': 'Function'
    };
};

RustParser.prototype.parse_function = function(line) {
    var regex = xregexp('\\s*fn\\s+(?P<name>\\S+)');
    var matches = xregexp.exec(line, regex);
    if(matches === null)
        return null;
    var name = matches.name || '';
    return [ name, []];
};

RustParser.prototype.parse_var = function(line) {
    return null;
};

RustParser.prototype.format_function = function(name, args) {
    return name;
};

module.exports = RustParser;

var DocsParser = require("../docsparser");
var xregexp = require('../xregexp').XRegExp;

function RustParser(settings) {
    DocsParser.call(this, settings);
}

RustParser.prototype = Object.create(DocsParser.prototype);

RustParser.prototype.setup_settings = function() {
    this.settings = {
        'curlyTypes': false,
        'typeInfo': false,
        'typeTag': false,
        'varIdentifier': '.*',
        'fnIdentifier': '[a-zA-Z_][a-zA-Z_0-9]*',
        'fnOpener': '^\\s*fn',
        'commentCloser': ' */',
        'bool': 'Boolean',
        'function': 'Function'
    };
};

RustParser.prototype.parse_function = function(line) {
    // TODO: add regexp for closures syntax
    // TODO: parse params
    var regex = xregexp('\\s*fn\\s+(?P<name>' + this.settings.fnIdentifier + ')');

    var matches = xregexp.exec(line, regex);
    if(matches === null || matches.name === undefined) {
        return null;
    }
    var name = matches.name;
    return [name, null];
};

RustParser.prototype.parse_var = function(line) {
    return null;
};

RustParser.prototype.format_function = function(name, args) {
    return name;
};

module.exports = RustParser;

Improve Rust function parser (Use correct identifier)


"use strict";

const file = require("./file");

module.exports = function testExecutions(data, formatForSonar56 = false) {
  const aTestExecution = [{ _attr: { version: "1" } }];
  const testResults = data.testResults.map(file);

  return formatForSonar56
    ? { unitTest: aTestExecution.concat(testResults) }
    : { testExecutions: aTestExecution.concat(testResults) };
};

'use strict'

const file = require('./file')

module.exports = function testExecutions(data, formatForSonar56 = false) {
  const aTestExecution = [{_attr: {version: '1'}}]
  const testResults = data.testResults.map(file)

  return formatForSonar56
    ? { unitTest: aTestExecution.concat(testResults) }
    : { testExecutions: aTestExecution.concat(testResults) };
};

Undo changes done by prettier


export function onConnect(respond, connections = {}, tab, error) {
  chrome.runtime.onConnect.addListener(function(port) {
    function extensionListener(message) {
      if (message.name === 'init') {
        connections[message.tabId] = port;

        if (tab && message.tabId !== tab.id) {
          error(port);
          return;
        }
        connections[message.tabId].postMessage(respond());
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      Object.keys(connections).forEach(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
        }
      });
    });

  });
}

export const connect = chrome.runtime.connect;

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
}

export const sendToBg = chrome.runtime.sendMessage;

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function onConnect(respond, connections = {}, tab, error) {
  chrome.runtime.onConnect.addListener(function(port) {
    function extensionListener(message) {
      if (message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;

        if (tab && message.tabId !== tab.id) {
          error(port);
          return;
        }
        port.postMessage(respond());
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      Object.keys(connections).forEach(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
        }
      });
    });

  });
}

export const connect = chrome.runtime.connect;

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
}

export const sendToBg = chrome.runtime.sendMessage;

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

Allow not to specify sender tab id. Detect it implicitly


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

module.exports = class Artist {
    constructor(artistObject) {
        this.id = artistObject.id;
        this.name = artistObject.name;
        this.tracks = [];
        this.artistObject = artistObject;
        this.artId = artistObject.picture;
    }

    async updateTracks(tidalApi) {
        this.tracks = await tidalApi.getArtistTopTracks(this);
    }

    updateArt(tidalApi) {
        return new Promise((resolve, reject) => {
            this.mkdirSync("/tmp/tidal-cli-client");
            this.artURL = tidalApi.getArtURL(this.artId, 750, 750);
            this.artSrc = "/tmp/tidal-cli-client/" + this.artId + ".jpg";
            let artFile = fs.createWriteStream(this.artSrc);
            https.get(this.artURL, response => {
                response.pipe(artFile);
                resolve();
            });
        });
    }

    mkdirSync(dirPath) {
        try {
            fs.mkdirSync(dirPath)
        } catch (err) {
            if (err.code !== "EXIST") throw err;
        }
    }

};

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

module.exports = class Artist {
    constructor(artistObject) {
        this.id = artistObject.id;
        this.name = artistObject.name;
        this.tracks = [];
        this.artistObject = artistObject;
        this.artId = artistObject.picture;
    }

    async updateTracks(tidalApi) {
        this.tracks = await tidalApi.getArtistTopTracks(this);
    }

    updateArt(tidalApi) {
        return new Promise((resolve, reject) => {
            this.mkdirSync("/tmp/tidal-cli-client");
            this.artURL = tidalApi.getArtURL(this.artId, 750, 750);
            this.artSrc = "/tmp/tidal-cli-client/" + this.artId + ".jpg";
            let artFile = fs.createWriteStream(this.artSrc);
            https.get(this.artURL, response => {
                response.pipe(artFile);
                resolve();
            });
        });
    }

    mkdirSync(dirPath) {
        if(!fs.existsSync(dirPath)) {
            try {
                fs.mkdirSync(dirPath)
            } catch (err) {
                if (err.code !== "EEXIST") throw err;
            }
        }
    }

};

Check if directory exists before creating


'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('compile', function () {
  return gulp.src('./scss/*.scss')
    .pipe(gulp.dest('./dist/'));
});

gulp.task('watch', function () {
  gulp.watch('./scss/*.scss', ['compile']);
});

'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('compile', function () {
  return gulp.src('./scss/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('./dist/'));
});

gulp.task('watch', function () {
  gulp.watch('./scss/*.scss', ['compile']);
});

Add sass compilation back to gulp file, tweaked output


'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var minifycss = require('gulp-minify-css');
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps = require('gulp-sourcemaps');

var paths = {
    sass: 'wye/static/sass/*.scss',
    css: 'wye/static/css'
};

gulp.task('css', function() {
    return gulp.src(paths.sass)
        .pipe(sourcemaps.init())
            .pipe(sass()
                .on('error', sass.logError))
            .pipe(autoprefixer({
                browsers: ['> 1%']
            }))
            .pipe(minifycss({
                debug: true
            }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(paths.css));
});

gulp.task('watch', function() {
    gulp.watch(paths.sass, ['css']);
});

gulp.task('default', ['watch']);

'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var minifycss = require('gulp-minify-css');
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps = require('gulp-sourcemaps');

var paths = {
    sass: 'wye/static/sass/**/*.scss',
    css: 'wye/static/css'
};

gulp.task('css', function() {
    return gulp.src(paths.sass)
        .pipe(sourcemaps.init())
            .pipe(sass()
                .on('error', sass.logError))
            .pipe(autoprefixer({
                browsers: ['> 1%']
            }))
            .pipe(minifycss({
                debug: true
            }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(paths.css));
});

gulp.task('watch', function() {
    gulp.watch(paths.sass, ['css']);
});

gulp.task('default', ['watch']);

Include all sass dirs to compile


var gulp = require('gulp'),
    gulpCopy = require('gulp-file-copy');

gulp.task('copy', function() {
  gulp.src('./bower_components/jquery/jquery.min.js')
      .pipe(gulp.dest('./js/lib/'));

  gulp.src('./jquery-mobile/jquery.mobile-1.4.5.js')
       .pipe(gulp.dest('./js/lib/'));

  gulp.src('./bower_components/moment/min/moment-with-locales.min.js')
       .pipe(gulp.dest('./js/lib/'));

  gulp.src('./bower_components/local-storage/src/LocalStorage.js')
       .pipe(gulp.dest('./js/lib/'));

  gulp.src('./jquery-mobile/jquery.mobile-1.4.5.css')
       .pipe(gulp.dest('./css/lib/'));
});

var gulp = require('gulp'),
    gulpCopy = require('gulp-file-copy');

gulp.task('copy', function() {
  gulp.src('./bower_components/jquery/jquery.min.js')
      .pipe(gulp.dest('./js/lib/'));

  gulp.src('./jquery-mobile/jquery.mobile-1.4.5.js')
       .pipe(gulp.dest('./js/lib/'));

  gulp.src('./bower_components/moment/min/moment-with-locales.min.js')
       .pipe(gulp.dest('./js/lib/'));

  gulp.src('./bower_components/local-storage/src/LocalStorage.js')
       .pipe(gulp.dest('./js/lib/'));

  gulp.src('./jquery-mobile/jquery.mobile-1.4.5.css')
       .pipe(gulp.dest('./css/lib/'));

  gulp.src('./jquery-mobile/images/ajax-loader.gif')
      .pipe(gulp.dest('./js/lib/images/'));
});

Add copy image in gulp


/**
 * Parse task and return task info if
 * the task is valid, otherwise throw
 * error.
 * @param  {string} query  Enetered task
 * @return {object}        Task info containing
 *                         task text, start time
 *                         and dealine
 */
function parse(query) {
  /**
   * Day, week or month coefficient
   * @type {Object}
   */
  const dwm = {
    d: 1,
    '': 1,
    w: 7,
    m: 30,
  };
  const regex = /@(\d+)([dwmDWM]?)(\+(\d+)([dwmDWM]?))?\s?(!{0,2})$/;
  const regexResult = regex.exec(query);
  const text = query.slice(0, regexResult.index);
  let start = Date.now();
  if (regexResult[3]) {
    start += 86400000 * regexResult[4] * dwm[regexResult[5]];
  }
  const end = start + (86400000 * regexResult[1] * dwm[regexResult[2]]);
  const importance = regexResult[6].length + 1;
  const status = 0;
  return {
    text: text.trim(),
    start,
    end,
    importance,
    status,
  };
}

module.exports = parse;

/**
 * Parse task and return task info if
 * the task is valid, otherwise throw
 * error.
 * @param  {string} query  Enetered task
 * @return {object}        Task info containing
 *                         task text, start time
 *                         and dealine
 */
function parse(query) {
  /**
   * Day, week or month coefficient
   * @type {Object}
   */
  const dwm = {
    d: 1,
    '': 1,
    w: 7,
    m: 30,
  };
  const regex = /@(\d+)([dwmDWM]?)(\+(\d+)([dwmDWM]?))?\s?(!{0,2})$/;
  const regexResult = regex.exec(query);
  const text = query.slice(0, regexResult.index);
  let start = Date.now() - ((Date.now() % 86400000) + (new Date().getTimezoneOffset() * 60000));
  if (regexResult[3]) {
    start += 86400000 * regexResult[4] * dwm[regexResult[5]];
  }
  const end = start + (86400000 * regexResult[1] * dwm[regexResult[2]]);
  const importance = regexResult[6].length + 1;
  const status = 0;
  return {
    text: text.trim(),
    start,
    end,
    importance,
    status,
  };
}

module.exports = parse;

Move task starting and ending points to start of days