$(document).ready(

$.getJSON('https://reps.mozilla.org/api/v1/rep/?offset=0&limit=0&group=council&callback=?',
    function(data) {
        console.log('got it!');
        $('body').append(JSON.stringify(data));
    })
);

$(document).ready(
	$.getJSON('https://reps.mozilla.org/api/v1/rep/?offset=0&limit=0&group=council&callback=?',
		function (data) {
			$('body').append(
				JSON.stringify(
					data.objects[Math.floor(Math.random() * data.objects.length)]
				)
			);
		},
		function (error) {
			console.log(error);
		}
	)
);

Return one Rep from the list, randomly


/*
Copyright 2016 ElasticBox All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

class ChartController {
    constructor($filter, chartsNavigationActionCreator) {
        'ngInject';

        this.lastModified = $filter('ekHumanizeDate')(this.chart.committed_date, 'epoch');
        this._chartsNavigationActionCreator = chartsNavigationActionCreator;
        this.maintainer = this.chart.maintainers[0].split('<')[0];
    }

    deploy() {
        this._chartsNavigationActionCreator.deployChart(this.chart);
    }
}

export default ChartController;

/*
Copyright 2016 ElasticBox All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

class ChartController {
    constructor($filter, chartsNavigationActionCreator) {
        'ngInject';

        this.lastModified = $filter('ekHumanizeDate')(this.chart.committed_date, 'epoch');
        this._chartsNavigationActionCreator = chartsNavigationActionCreator;
        this.maintainer = _.isEmpty(this.chart.maintainers) ? 'Last modified' : _.first(this.chart.maintainers).split('<')[0];
    }

    deploy() {
        this._chartsNavigationActionCreator.deployChart(this.chart);
    }
}

export default ChartController;

Fix UI when there is not chart maintainer defined


module.exports = Entity = function(entity) {

	var name = entity.name,
		coordinate = entity.coordinate,
		width = entity.width,
		height = entity.height,
		type = entity.type,
		properties = {
			WALKABLE: false,
			DAMAGEABLE: true,
		};

	switch(entity.type) {
		case 'STRUCTURE':
			properties.DAMAGEABLE = false;
			break;
		default:
			break;
	}

	this.getCoordinate = function() {
		return coordinate || new Array();
	}

	this.isWalkable = function() {
		return properties.WALKABLE;
	}

	this.isDamageable = function() {
		return properties.DAMAGEABLE;
	}
}

module.exports = Entity = function(entity) {

	var name = entity.name,
		coordinate = entity.coordinate,
		width = entity.width,
		height = entity.height,
		type = entity.type,
		properties = {
			WALKABLE: false,
			DAMAGEABLE: true,
		};

	switch(entity.type) {
		case 'STRUCTURE':
			properties.DAMAGEABLE = false;
			break;
		default:
			break;
	}

	this.getCoordinate = function() {
		return coordinate || new Array();
	}

	this.getWidth = function() {
		return width;
	}

	this.getHeight = function() {
		return height;
	}

	this.isWalkable = function() {
		return properties.WALKABLE;
	}

	this.isDamageable = function() {
		return properties.DAMAGEABLE;
	}
}

Add entity getWidth and getHeight.


var lodash = require('lodash'),
    knife = require('../knife'),
    Issue = require('../issue');

module.exports = {
    name: 'id-class-style',
    on: ['attr'],
    filter: ['id', 'class']
};

module.exports.lint = function (attr, opts) {
    var format = opts[this.name];
    if (!format) {
        return [];
    }

    var v = attr.value;
    // Breaks if there is an SOH character in your class or id name.
    // Don't do that.
    var ignore = opts['id-class-ignore-regex'];
    if (ignore) { v = v.replace(new RegExp(ignore), '\u0001'); }

    var verify = knife.getFormatTest(format);
    var cssclasses = v.split(' ');

    return lodash.flatten(cssclasses.map(function(c) {
        return (c.indexOf('\u0001') !== -1 || verify(c)) ? [] :
            new Issue('E011', attr.valueLineCol, { format: format });
    }));
};

var lodash = require('lodash'),
    knife = require('../knife'),
    Issue = require('../issue');

module.exports = {
    name: 'id-class-style',
    on: ['attr'],
    filter: ['id', 'class']
};

module.exports.lint = function (attr, opts) {
    var format = opts[this.name];
    if (!format) {
        return [];
    }

    var v = attr.value;
    // Breaks if there is an SOH character in your class or id name.
    // Don't do that.
    var ignore = opts['id-class-ignore-regex'];
    if (ignore) { v = v.replace(new RegExp(ignore), '\u0001'); }

    var verify = knife.getFormatTest(format);
    var cssclasses = v.split(/\s+/);

    return lodash.flatten(cssclasses.map(function(c) {
        return (c.indexOf('\u0001') !== -1 || verify(c)) ? [] :
            new Issue('E011', attr.valueLineCol, { format: format });
    }));
};

Break on any amount of whitespace instead of on one space only


const path = require('path');
const model = require(path.resolve('src/model/pokemon'));

const dao = {

	create: function(pokemon) {
		return model.create(pokemon);
	},

	findOne: function(query) {
		query = query || {};
		return model.find({
			where: query
		});
	},

	findAll: function () {
		return model.findAll();
	}

};

module.exports = dao;

const path = require('path');
const model = require(path.resolve('src/model/pokemon'));

const dao = {

	create: function(pokemon) {
		return model.create(pokemon);
	},

	findOne: function(query) {
		query = query || {};
		return model.find({
			where: query
		});
	},

	findAll: function () {
		return model.findAll();
	},

	deleteOne: function(query) {
		return dao.destroy({where: query});
	}

};

module.exports = dao;

ADD delete method on DAO .


/*
 * A color scheme for the application. All non-trivial colors should
 * reference this module (e.g., using 'black' or '#000' is okay, but
 * something like '#ccc' should instead be `Colors.gray.medium`).
 */

export default {
    primary: '#121316',
    primaryLight: '#2a2d34',
    gray: {
        dark: '#6e6e6e',
        medium: '#cecece',
        light: '#ececec',
        lightest: '#efefef',
    },
    accentBlue: {
        lightest: '#4ca080',
        light: '#2a899b',
        base: '#0a7f96',
        dark: '#046375',
        darkest: '#024d5c',
    },
};

/*
 * A color scheme for the application. All non-trivial colors should
 * reference this module (e.g., using 'black' or '#000' is okay, but
 * something like '#ccc' should instead be `Colors.gray.medium`).
 *
 * This module also exports a function `hexWithAlpha` for alpha-adjusted
 * generating CSS color expressions from hex color codes. It is
 * guaranteed that the colors in the default-exported palette will be
 * valid first arguments to `hexWithAlpha`.
 */

/*
 * Note: it's an internal invariant of this file that all colors be
 * represented as six-digit hex codes. (This is needed for
 * `hexWithAlpha` to work with these colors.)
 */
export default {
    primary: '#121316',
    primaryLight: '#2a2d34',
    gray: {
        dark: '#6e6e6e',
        medium: '#cecece',
        light: '#ececec',
        lightest: '#efefef',
    },
    accentBlue: {
        lightest: '#4ca080',
        light: '#2a899b',
        base: '#0a7f96',
        dark: '#046375',
        darkest: '#024d5c',
    },
};

/*
 * Given a hex color string, return a CSS color expression representing
 * the same base color but with the specified alpha value.
 *
 * @param {string} hex
 *     the hex color string, which should contain exactly six
 *     hexadecimal digits (and may contain other stuff, like a leading
 *     hash)
 * @return {string} a CSS color expression
 */
export function hexWithAlpha(hex, alpha) {
    const hexNumber = hex.replace(/[^0-9A-Fa-f]/g, '');
    if (hexNumber.length !== 6) {
        throw new Error(
            `expected string to have exactly six hex digits, but found: ` +
            `${hex}`);
    }
    const r = parseInt(hexNumber.substring(0, 2), 16);
    const g = parseInt(hexNumber.substring(2, 4), 16);
    const b = parseInt(hexNumber.substring(4, 6), 16);
    return `rgba(${r},${g},${b},${alpha})`;
}

Add `hexWithAlpha`, which outputs CSS colors


Mixer = function () {
	this.mix = []
	this.target
}

//Sets target for later manipulation(ie. volume, filter)
Mixer.prototype.assignTarget = function (position) {
	this.target = position
}

//Adds a track to the mix. Takes args = {urls: sound.aws.com, divId: 1}
Mixer.prototype.addTrack = function (args) {
	console.log(args['url'])
	var newTrack = new Howl({
		urls: [args['urls']]
	});
	this.mix[args['divId']] = newTrack;
}

//Removes a track from the mix array
Mixer.prototype.removeTrack = function (position) {
	this.mix[position] = null;
}

//Plays all items in mix array
Mixer.prototype.globalPlay = function () {
	for (var i = 0; i < 6; i++) {
		if (this.mix[i] != null) {
			this.mix[i].play()
		}
	}
}

//Pauses all items in mix array
Mixer.prototype.globalPause = function () {
	for (var i = 0; i < 6; i++) {
		if (this.mix[i] != null) {
			this.mix[i].pause()
		}
	}
}

//Assigns target volume
Mixer.prototype.targetVolume = function (volumeLevel) {
	this.mix[this.target].volume(volumeLevel)
}

Mixer = function () {
	this.mix = []
	this.target
}

//Sets target for later manipulation(ie. volume, filter)
Mixer.prototype.assignTarget = function (position) {
	this.target = position
}

//Adds a track to the mix. Takes args = {urls: sound.aws.com, divId: 1}
Mixer.prototype.addTrack = function (args) {
	console.log(args['url'])
	var newTrack = new Howl({
		urls: [args['urls']]
	});
	this.mix[args['divId']] = newTrack;
}

//Removes a track from the mix array
Mixer.prototype.removeTrack = function (position) {
	this.mix[position] = null;
}

//Plays all items in mix array
Mixer.prototype.globalPlay = function () {
	for (var i = 0; i < 6; i++) {
		if (this.mix[i] != null) {
			this.mix[i].play()
		}
	}
}

//Pauses all items in mix array
Mixer.prototype.globalPause = function () {
	for (var i = 0; i < 6; i++) {
		if (this.mix[i] != null) {
			this.mix[i].pause()
		}
	}
}

//Assigns target volume
Mixer.prototype.assignTargetVolume = function (volumeLevel) {
	this.mix[this.target].volume(volumeLevel)
}

Change name of assignVolume to assignTargetVolume


(function(){
  "use strict";
  var POLLING_INTERVAL = 3 * 1000;
  var POLLING_URL = "/polling/alerts";

  $(function(){
    if($('#vue-notification').length === 0) return;

    var alert = new Vue({
      el: "#vue-notification",
      data: {
        "alerts": []
      },

      created: function(){
        var self = this;
        var fetch = function(){
          self.fetchAlertsData().then(function(alerts){
            self.alerts = alerts;
          })["catch"](function(xhr){
            if(xhr.status === 401) {
              clearInterval(timer); // signed out
            }
            if(xhr.status === 0) {
              clearInterval(timer); // server unreachable (maybe down)
            }
          });
        };
        fetch();
        var timer = setInterval(fetch, POLLING_INTERVAL);
      },

      computed: {
        alertsCount: {
          $get: function(){ return this.alerts.length; }
        },
        hasAlerts: {
          $get: function(){ return this.alertsCount > 0; }
        }
      },

      methods: {
        fetchAlertsData: function() {
          return new Promise(function(resolve, reject) {
            $.getJSON(POLLING_URL, resolve).fail(reject);
          });
        }
      }
    });
  });
})();

(function(){
  "use strict";
  var POLLING_INTERVAL = 3 * 1000;
  var POLLING_URL = "/polling/alerts";

  $(function(){
    if($('#vue-notification').length === 0) return;

    var alert = new Vue({
      el: "#vue-notification",
      data: {
        "alerts": []
      },

      created: function(){
        var self = this;
        var currentInterval = POLLING_INTERVAL;
        var fetch = function(){
          self.fetchAlertsData().then(function(alerts){
            if(self.alerts.toString() == alerts.toString()) {
              currentInterval *= 1.1;
            } else {
              currentInterval = POLLING_INTERVAL;
            }
            self.alerts = alerts;
            setTimeout(fetch, currentInterval);
          })["catch"](function(xhr){
            if(xhr.status === 401) {
              // signed out
            }
            if(xhr.status === 0) {
              // server unreachable (maybe down)
            }
          });
        };
        fetch();
      },

      computed: {
        alertsCount: {
          $get: function(){ return this.alerts.length; }
        },
        hasAlerts: {
          $get: function(){ return this.alertsCount > 0; }
        }
      },

      methods: {
        fetchAlertsData: function() {
          return new Promise(function(resolve, reject) {
            $.getJSON(POLLING_URL, resolve).fail(reject);
          });
        }
      }
    });
  });
})();

Reduce polling access by exponential backoff like strategy


import { configure } from 'enzyme'; // eslint-disable-line import/no-extraneous-dependencies
import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; // eslint-disable-line import/no-extraneous-dependencies
import '@testing-library/jest-dom'; // eslint-disable-line import/no-extraneous-dependencies

// necessary due to https://github.com/facebook/create-react-app/issues/7539
jest.mock('retranslate', () => jest.requireActual('../__mocks__/retranslate'));
jest.mock('mixpanel-browser', () => ({
  identify: jest.fn(),
  track: jest.fn(),
  register: jest.fn(),
  people: { set: jest.fn() },
}));

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

import { configure } from 'enzyme'; // eslint-disable-line import/no-extraneous-dependencies
import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; // eslint-disable-line import/no-extraneous-dependencies
import '@testing-library/jest-dom'; // eslint-disable-line import/no-extraneous-dependencies

// necessary due to https://github.com/facebook/create-react-app/issues/7539
jest.mock('retranslate', () => jest.requireActual('../__mocks__/retranslate'));

jest.mock('react-intl', () => {
  const reactIntl = jest.requireActual('react-intl');
  const intl = reactIntl.createIntl({
    locale: 'en',
  });

  return {
    ...reactIntl,
    useIntl: () => intl,
  };
});

jest.mock('mixpanel-browser', () => ({
  identify: jest.fn(),
  track: jest.fn(),
  register: jest.fn(),
  people: { set: jest.fn() },
}));

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

Add react-intl mock for tests


const path = require('path')

const fileType = require('file-type')
const contentType = require('content-type')
const mime = require('mime-types')

async function parseType(token, options) {
  if (token.parsed) return false

  // First, we read a chunk and try to infer the type with it
  const chunk = await new Promise((resolve, reject) => {
    const handle = setTimeout(
      () => reject(new Error('Timeout when trying to get first chunk')),
      options.fetchTimeout
    )
    token.response.body.once('data', firstChunk => {
      token.response.body.pause()
      clearTimeout(handle)
      token.response.body.unshift(firstChunk)
      resolve(firstChunk)
    }).resume()
  })

  const type = fileType(chunk)
  if (type) {
    token.fileType = type
    return
  }

  // Then, we try to extract the extension from the filename
  if (token.fileName) {
    const ext = path.extname(token.fileName).substring(1)

    token.fileType = {
      ext,
      mime: mime.lookup(ext)
    }
    return
  }

  // Finally, we retrieve the type from the content-type header
  const ct = contentType.parse(token.response)
  if (ct) {
    token.fileType = {
      ext: mime.extension(ct.type),
      mime: ct.type
    }
  }
}

module.exports = parseType

const path = require('path')

const fileType = require('file-type')
const contentType = require('content-type')
const mime = require('mime-types')

async function parseType(token, options) {
  if (token.parsed) return false

  // First, we read a chunk and try to infer the type with it
  const chunk = await new Promise((resolve, reject) => {
    const handle = setTimeout(
      () => reject(new Error('Timeout when trying to get first chunk')),
      options.fetchTimeout
    )
    token.response.body.once('data', firstChunk => {
      token.response.body.pause()
      clearTimeout(handle)
      token.response.body.unshift(firstChunk)
      resolve(firstChunk)
    }).read(4100)
    token.response.body.resume()
  })

  const type = fileType(chunk)
  if (type) {
    token.fileType = type
    return
  }

  // Then, we try to extract the extension from the filename
  if (token.fileName) {
    const ext = path.extname(token.fileName).substring(1)

    token.fileType = {
      ext,
      mime: mime.lookup(ext)
    }
    return
  }

  // Finally, we retrieve the type from the content-type header
  const ct = contentType.parse(token.response)
  if (ct) {
    token.fileType = {
      ext: mime.extension(ct.type),
      mime: ct.type
    }
  }
}

module.exports = parseType

Read only 4100 first bytes from response stream


import Ember from 'ember';

export default Ember.Route.extend({
  setupController(controller, session) {
    this._super(controller, session);
    controller.set('experiment', this.controllerFor('participate.survey').get('experiment'));
    controller.set('session', session);
    controller.set('pastSessions', []);
  },
  actions: {
    willTransition(transition) {
      this._super(transition);
      var frameIndex = this.controllerFor('participate.survey.index').get('frameIndex');
      var framePage = this.controllerFor('participate.survey.index').get('framePage');
      if (frameIndex !== 0) {
        this.replaceWith('participate.survey.index');
        // Disable back button in qsort page 2, and rating-form page 1
        if (!(frameIndex === 2 && framePage === 1) && frameIndex !== 3) {
          this.controllerFor('participate.survey.index').set('frameIndex', frameIndex - 1);
        }
        // Update pages within the rating-form
        if (frameIndex === 3 && framePage !== 0) {
          this.controllerFor('participate.survey.index').set('framePage', framePage - 1);
        }
      }
    }
  }
});

import Ember from 'ember';

export default Ember.Route.extend({
  setupController(controller, session) {
    this._super(controller, session);
    controller.set('experiment', this.controllerFor('participate.survey').get('experiment'));
    controller.set('session', session);
    controller.set('pastSessions', []);
  },
  actions: {
    willTransition(transition) {
      this._super(transition);

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

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

Fix transitioning to results page


var TopicChartsView = Backbone.View.extend({

  initialize: function() {
    this.$el = $("#charts-container");
    this.template = JST["templates/topic-charts/topicChartsTemplate"];
  },

  render: function() {
    this.$el.html(this.template({ charts: this.collection }));
    if (this.collection.topicId == 1) {
      drawDatamap(this.collection[0].attributes[0]);
      InitLineGraph(this.collection[1].attributes.responses);
      $("#line-graph-container").hide();
      var timeSlider = new TimeSlider();
      timeSlider.render();
      this.$el.find("#slider").on("slide", this.updateChartData.bind(this));
      this.$el.find(".ui-tabs-panel").on("click", this.toggleTab)
    }
    else {
      candidateLineGraph(this.collection);
    }
  },

  updateChartData: function(event, ui) {
    $("#map-container").html("");
    drawDatamap(this.collection[0].attributes[30 - ui.value].attributes);
  },

  toggleTab: function(event, ui) {
    event.preventDefault();
    $("div ul a li").removeClass("active");
    $(".charts").hide()
    var link = $(this.parentElement).attr("href")
    $(this).addClass("active");
    $(link).show();
  }

})

var TopicChartsView = Backbone.View.extend({

  initialize: function() {
    this.$el = $("#charts-container");
    this.template = JST["templates/topic-charts/topicChartsTemplate"];
  },

  render: function() {
    this.$el.html(this.template({ charts: this.collection }));
    if (this.collection[0].collection.options.topicId == 1) {
      drawDatamap(this.collection[0].attributes[0]);
      InitLineGraph(this.collection[1].attributes.responses);
      $("#line-graph-container").hide();
      var timeSlider = new TimeSlider();
      timeSlider.render();
      this.$el.find("#slider").on("slide", this.updateChartData.bind(this));
      this.$el.find(".ui-tabs-panel").on("click", this.toggleTab)
    }
    else {
      candidateLineGraph(this.collection);
    }
  },

  updateChartData: function(event, ui) {
    $("#map-container").html("");
    drawDatamap(this.collection[0].attributes[30 - ui.value]);
  },

  toggleTab: function(event, ui) {
    event.preventDefault();
    $("div ul a li").removeClass("active");
    $(".charts").hide()
    var link = $(this.parentElement).attr("href")
    $(this).addClass("active");
    $(link).show();
  }

})

Resolve some issues bringing the new candidates chart into master


import S from '@sanity/desk-tool/structure-builder'
import RefreshIcon from 'part:@sanity/base/sync-icon'
import JsonDocumentDump from './components/JsonDocumentDump'

// For testing. Bump the timeout to introduce som lag
const delay = val => new Promise(resolve => setTimeout(resolve, 10, val))

export default () =>
  S.list()
    .id('root')
    .title('Content')
    .items([
      S.listItem()
        .id('docList')
        .title('Anything with a title')
        .child(() =>
          delay(
            S.documentList({
              id: 'title-list',
              title: 'Titles!',
              options: {
                filter: 'defined(title)'
              }
            })
          )
        ),

      S.listItem()
        .id('circular')
        .title('Singleton?')
        .child(delay(S.editor({id: 'editor', options: {id: 'circular', type: 'referenceTest'}}))),

      S.documentListItem()
        .id('grrm')
        .schemaType('author')
        .child(
          S.component()
            .id('dump')
            .component(JsonDocumentDump)
            .menuItems([
              S.menuItem()
                .title('Reload')
                .action('reload')
                .icon(RefreshIcon)
                .showAsAction(true)
            ])
        ),

      ...S.documentTypeListItems()
    ])

import React from 'react'
import S from '@sanity/desk-tool/structure-builder'
import RefreshIcon from 'part:@sanity/base/sync-icon'
import JsonDocumentDump from './components/JsonDocumentDump'

// For testing. Bump the timeout to introduce som lag
const delay = val => new Promise(resolve => setTimeout(resolve, 10, val))

export default () =>
  S.list()
    .id('root')
    .title('Content')
    .items([
      S.listItem()
        .id('docList')
        .title('Anything with a title')
        .icon(() => T)
        .child(() =>
          delay(
            S.documentList({
              id: 'title-list',
              title: 'Titles!',
              options: {
                filter: 'defined(title)'
              }
            })
          )
        ),

      S.listItem()
        .id('circular')
        .title('Singleton?')
        .child(delay(S.editor({id: 'editor', options: {id: 'circular', type: 'referenceTest'}}))),

      S.documentListItem()
        .id('grrm')
        .schemaType('author')
        .child(
          S.component()
            .id('dump')
            .component(JsonDocumentDump)
            .menuItems([
              S.menuItem()
                .title('Reload')
                .action('reload')
                .icon(RefreshIcon)
                .showAsAction(true)
            ])
        ),

      ...S.documentTypeListItems()
    ])

Add example of using custom icon for list item


import { createAction } from 'redux-actions';
import { createThunkAction } from 'utils/redux';
import isEmpty from 'lodash/isEmpty';

export const fetchCountriesDocumentsInit = createAction(
  'fetchCountriesDocumentsInit'
);
export const fetchCountriesDocumentsReady = createAction(
  'fetchCountriesDocumentsReady'
);
export const fetchCountriesDocumentsFail = createAction(
  'fetchCountriesDocumentsFail'
);

export const fetchCountriesDocuments = createThunkAction(
  'fetchCountriesDocuments',
  location => (dispatch, state) => {
    const { countriesDocuments } = state();
    if (
      !countriesDocuments.loading &&
      (isEmpty(countriesDocuments.data) ||
        (!!location && isEmpty(countriesDocuments.data[location])))
    ) {
      const url = `/api/v1/ndcs/countries_documents${
        location ? `?location=${location}` : ''
      }`;
      dispatch(fetchCountriesDocumentsInit());
      fetch(url)
        .then(response => {
          if (response.ok) return response.json();
          throw Error(response.statusText);
        })
        .then(data => {
          dispatch(fetchCountriesDocumentsReady(data.data));
        })
        .catch(error => {
          console.warn(error);
          dispatch(fetchCountriesDocumentsFail());
        });
    }
  }
);

export default {
  fetchCountriesDocuments,
  fetchCountriesDocumentsInit,
  fetchCountriesDocumentsReady,
  fetchCountriesDocumentsFail
};

import { createAction } from 'redux-actions';
import { createThunkAction } from 'utils/redux';
import isEmpty from 'lodash/isEmpty';

export const fetchCountriesDocumentsInit = createAction(
  'fetchCountriesDocumentsInit'
);
export const fetchCountriesDocumentsReady = createAction(
  'fetchCountriesDocumentsReady'
);
export const fetchCountriesDocumentsFail = createAction(
  'fetchCountriesDocumentsFail'
);

export const fetchCountriesDocuments = createThunkAction(
  'fetchCountriesDocuments',
  location => (dispatch, state) => {
    const { countriesDocuments } = state();
    if (
      !countriesDocuments.loading &&
      (!location ||
        !countriesDocuments.data || isEmpty(countriesDocuments.data[location]))
    ) {
      const url = `/api/v1/ndcs/countries_documents${
        location ? `?location=${location}` : ''
      }`;
      dispatch(fetchCountriesDocumentsInit());
      fetch(url)
        .then(response => {
          if (response.ok) return response.json();
          throw Error(response.statusText);
        })
        .then(data => {
          dispatch(fetchCountriesDocumentsReady(data.data));
        })
        .catch(error => {
          console.warn(error);
          dispatch(fetchCountriesDocumentsFail());
        });
    }
  }
);

export default {
  fetchCountriesDocuments,
  fetchCountriesDocumentsInit,
  fetchCountriesDocumentsReady,
  fetchCountriesDocumentsFail
};

FIx Document provider not refetching


/*
 * $Id$
 * (c) Copyright 2002-2013 by authors of the Tiki Wiki CMS Groupware Project
 *
 * All Rights Reserved. See copyright.txt for details and a complete list of authors.
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
 *
 * Ckeditor templates definition for Tiki 6
 *
 * TODO: Needs tying in to the content templates somehow - placeholder here for now...
 */

// Register a template definition set named "default".
CKEDITOR.addTemplates('default',
{
    // Not used. The name of the subfolder that contains the preview images of the templates.
    // imagesPath: '', // CKEDITOR.getUrl(''),

    // Template definitions.
    templates: getContentTemplates()
})

function getContentTemplates() {

    var myTitle = 'Hello world';
    var myDescription = 'This is a dummy template. Collecting the wiki content templates is pending';
    var myHTML = '<b>Hello world! This is a dummy.</b>';
    return [{
        title: myTitle,
        html: myHTML,
	    description: myDescription,
    }];
}

/*
 * $Id$
 * (c) Copyright 2002-2013 by authors of the Tiki Wiki CMS Groupware Project
 *
 * All Rights Reserved. See copyright.txt for details and a complete list of authors.
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
 *
 * Ckeditor templates definition for Tiki
 */

// Register a template definition set named "default".
CKEDITOR.addTemplates('default',
{
    // Not used. The name of the subfolder that contains the preview images of the templates.
    // imagesPath: '', // CKEDITOR.getUrl(''),

    // Template definitions.
    templates: getContentTemplates()
})

function getContentTemplates() {

    // Do a synchronous call, to be able to fill the listbox.
    // Can lockup the GUI a bit. Especially if the are many, large content templates defined.
    //  Updating the element "on success" would be better, but I am not sure how at the moment...Arild
    var result = $.ajax({
        type: 'GET',
        url: 'tiki-ajax_services.php?',
        dataType: 'json',
        data: {
            controller: 'contenttemplate',
            action: 'list'
            },
        async: false,       // Synchronous call
        success: function(data) {

		    var content = data["data"];
		    var cant = data["cant"];

            result = [];
            for (var i = 0; i < cant; i++) {
                result.push(
                    [{
                        title: content[i]['title'],
                        html: content[i]['html'],
                    }]);
            }
            return result;
        }
    });

    if(result.status == 200) {
        var ret = $.parseJSON(result.responseText);
        return ret['data'];
    } else {
        return [];
    }
}

Load content templates when "templates" ckeditor toolbar button is pressed.


;(function(){
  var app = angular.module('Communicant', []);
  // app.controller('ListOfMessages', ['$scope', '$http', function($scope, $http){
  //   $http.get("")
  console.log("inside angular")
  }]);

})(); // END IIFE

;(function(){
  var app = angular.module('Communicant', []);

  app.controller('ListOfMessagesController', ['$scope', '$http', function($scope, $http){
    $http.get("/messages.json")
    .then(function(response){
      $scope.messages = response.data;
    })

  }]); // END ListOfMessagesController

  app.controller('SendMessageController', ['$scope', '$http', function($scope, $http){
    // console.log("Hello?");
    $scope.newMessage = { };
    $scope.submit = function(){
      $http.post("/messages.json", $scope.newMessage);
    };
    $http.get("/messages.json")
    .then(function(response){
      $scope.messages = response.data;
    })
  }]); // END SendMessageController

})(); // END IIFE

Structure angular to both get and give messages


var _ = require('underscore'),
  Vector = require("./vector"),
  path = require("path");

'use strict';

var IndexScene = function(file){
  var self = this;

  self.xml = "<scene><spawn position='0 0 10' /><skybox style='color: linear-gradient(#fff, #99f);' />";

  var i = 0;

  _.each(file, function(filename){
    var v = new Vector(i * 3,1,0),
      name = path.basename(filename, '.xml'),
      pathname = path.basename(filename);

    self.xml += "<billboard position='" + v.toString() + "'>
" + name +"
</billboard>";
    v.z += 0.28;
    self.xml += "<link position='" + v.toString() + "' href='/" + pathname + "' scale='0.25 0.25 0.25' />";

    i++;
  });

  self.xml += "</scene>";
}

IndexScene.prototype.toXml = function(){
  return this.xml;
};

module.exports = IndexScene;

var _ = require('underscore'),
  Vector = require("./vector"),
  path = require("path");

'use strict';

var IndexScene = function(file){
  var self = this;

  self.xml = "<scene><spawn position='0 0 10' /><skybox style='color: linear-gradient(#fff, #99f);' />";

  var i = 0;

  _.each(file, function(filename){
    var v = new Vector(i * 3,1,0),
      name = path.basename(filename, '.xml'),
      pathname = path.basename(filename);

    self.xml += "<billboard position='" + v.toString() + "'><![CDATA[
" + name +"
]]></billboard>";
    v.z += 0.28;
    self.xml += "<link position='" + v.toString() + "' href='/" + pathname + "' scale='0.25 0.25 0.25' />";

    i++;
  });

  self.xml += "</scene>";
}

IndexScene.prototype.toXml = function(){
  return this.xml;
};

module.exports = IndexScene;

Add missing cdata tags to index scene.


var Context = require('./context');

var agi = function (handler, optionsIn) {

  var server;
  var options = optionsIn || {};

  var settings = {
    port: options.port || 3000,
    debug: options.debug || false
  };

  var handle = function (stream) {
    var context = new Context(stream, settings.debug);
    handler(context);
  };

  var start = function (portIn) {
    var port = portIn || settings.port;
    return require('net').createServer(handle).listen(port);
  };

  return {
    start: start
  };
};

module.exports = agi;

var Context = require('./context');

var agi = function (handler, optionsIn) {

  var server;
  var options = optionsIn || {};

  var settings = {
    port: options.port || 3000,
    debug: options.debug || false,
    host: options.host,
  };

  var handle = function (stream) {
    var context = new Context(stream, settings.debug);
    handler(context);
  };

  var start = function (portIn, hostIn) {
    var port = portIn || settings.port;
    var host = hostIn || settings.host;
    return require('net').createServer(handle).listen(port, host);
  };

  return {
    start: start
  };
};

module.exports = agi;

Allow binding AGI server to specified host


var MongoClient = require('mongodb').MongoClient;
module.exports = {
  init: function(expressConfig, session, cb) {
    var self = this;
    var MongoStore = require('connect-mongo')(session);
    MongoClient.connect(expressConfig.config.url, function(err, mongo) {
      if (err) {
        return cb(err);
      }
      self.store = new MongoStore({db: mongo});
      self.db = mongo;
      return cb(null);
    });
  },
  verifySession: function(token, cb) {
    //For a given session token, there should only be a maximum of 1
    this.db.collection('sessions').findOne({
      '_id': token
    }, function(err, foundSession) {
      //For the session to be valid, the expiry date must be greater than now.
      var valid = !err && foundSession && new Date() < new Date(foundSession.expires);
      foundSession.isValid = valid;
      return cb(err, foundSession);
    });
  },
  revokeSession: function(token, cb) {
    this.db.collection('sessions').deleteOne({
      '_id': token
    }, cb);
  },
  defaultConfig: {
    url: 'mongodb://localhost:27017/raincatcher-demo-auth-session-store'
  }
};

var MongoClient = require('mongodb').MongoClient;
module.exports = {
  init: function(expressConfig, session, cb) {
    var self = this;
    var MongoStore = require('connect-mongo')(session);
    MongoClient.connect(expressConfig.config.url, function(err, mongo) {
      if (err) {
        return cb(err);
      }
      self.store = new MongoStore({
        db: mongo,
        ttl: expressConfig.config.ttl || 14 * 24 * 60 * 60 // = 14 days. Default
      });
      self.db = mongo;
      return cb(null);
    });
  },
  verifySession: function(token, cb) {
    //For a given session token, there should only be a maximum of 1
    this.db.collection('sessions').findOne({
      '_id': token
    }, function(err, foundSession) {
      //For the session to be valid, the expiry date must be greater than now.
      var valid = !err && foundSession && new Date() < new Date(foundSession.expires);
      foundSession.isValid = valid;
      return cb(err, foundSession);
    });
  },
  revokeSession: function(token, cb) {
    this.db.collection('sessions').deleteOne({
      '_id': token
    }, cb);
  },
  defaultConfig: {
    url: 'mongodb://localhost:27017/raincatcher-demo-auth-session-store'
  }
};

Allow the session expiration length to be configurable


// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

module.exports = function(landscape) {
  let thingToDo = [];

  return {
    "tick": () => new Promise(function(resolve, reject) {
      try {
        if (thingToDo.length > 0) {
          let thing = thingToDo.pop();
          landscape[thing.method].apply(landscape, thing.args);
        }

        resolve();

      } catch(error) {
        reject(error);
      }
    }),

    "at": function(when, method) {
      thingToDo.push({
        "when": when,
        "method": method,
        "args": [...arguments].slice(2)
      });
    }
  };
};

// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

module.exports = function(landscape) {
  let actions = new Map();
  let tickCount = 0;
  let thingToDo = [];

  return {
    "tick": () => new Promise(function(resolve, reject) {
      try {
        tickCount += 1;

        if (thingToDo.length > 0) {
          let thing = thingToDo.pop();
          landscape[thing.method].apply(landscape, thing.args);
        }

        resolve();

      } catch(error) {
        reject(error);
      }
    }),

    "at": function(when, method) {
      thingToDo.push({
        "when": when,
        "method": method,
        "args": [...arguments].slice(2)
      });

      actions.set(when, {
        "when": when,
        "method": method,
        "args": [...arguments].slice(2)
      });
    }
  };
};

Add code for Map() instead of Array()


var os = Npm.require('os');
var uvmon = Npm.require('nodefly-uvmon');

SystemModel = function () {
  var self = this;
  this.lastGetData = (new Date).getTime();
  // need to call this here and clean the older data
  uvmon.getData();
}

_.extend(SystemModel.prototype, ApmModel.prototype);

SystemModel.prototype.getEventLoopData = function() {
  var data = uvmon.getData();
  var time = (new Date).getTime();
  data.time = time - this.lastGetData;
  this.lastGetData = time;
  return data;
};

SystemModel.prototype.buildPayload = function() {
  var metrics = {};
  metrics.startTime = this.lastGetData;
  var uvData = this.getEventLoopData();
  metrics.endTime = this.lastGetData;
  metrics.sessions = _.keys(Meteor.default_server.sessions).length;
  metrics.rssBytes = process.memoryUsage().rss;
  metrics.loadAverage = os.loadavg()[0];
  metrics.eventLoopTime = uvData.sum_ms;
  metrics.eventLoopCount = uvData.count;
  metrics.totalTime = uvData.time;
  return {systemMetrics: [metrics]};
};

var os = Npm.require('os');
var uvmon = Npm.require('nodefly-uvmon');

SystemModel = function () {
  var self = this;
  this.lastGetData = (new Date).getTime();
  // need to call this here and clean the older data
  uvmon.getData();
}

_.extend(SystemModel.prototype, ApmModel.prototype);

SystemModel.prototype.getEventLoopData = function() {
  var data = uvmon.getData();
  var time = (new Date).getTime();
  data.time = time - this.lastGetData;
  this.lastGetData = time;
  return data;
};

SystemModel.prototype.buildPayload = function() {
  var metrics = {};
  metrics.startTime = this.lastGetData;
  var uvData = this.getEventLoopData();
  metrics.endTime = this.lastGetData;
  metrics.sessions = _.keys(Meteor.default_server.sessions).length;
  metrics.rssBytes = process.memoryUsage().rss / (1024*1024);
  metrics.loadAverage = os.loadavg()[0];
  metrics.eventLoopTime = uvData.sum_ms;
  metrics.eventLoopCount = uvData.count;
  metrics.totalTime = uvData.time;
  return {systemMetrics: [metrics]};
};

Convert memory usage to megabytes


'use strict';

module.exports = {

    // Thingme config
    // see: https://github.com/rowanmanning/thingme#configuration
    singular: 'fed',
    plural: 'feds',

    // FED image URLs
    things: [
        'http://i.imgur.com/Tfq7Bi7.gif'
    ]

};

'use strict';

module.exports = {

    // Thingme config
    // see: https://github.com/rowanmanning/thingme#configuration
    singular: 'fed',
    plural: 'feds',

    // FED image URLs
    things: [
        'http://i.imgur.com/1IpgJ8j.jpg',
        'http://i.imgur.com/873UUyQ.jpg',
        'http://i.imgur.com/aZNXXDQ.jpg',
        'http://i.imgur.com/bdW4hXx.jpg',
        'http://i.imgur.com/khW3ahU.jpg',
        'http://i.imgur.com/pPGuifS.jpg',
        'http://i.imgur.com/s5fHyVW.jpg',
        'http://i.imgur.com/Tfq7Bi7.gif',
        'http://i.imgur.com/UZyrj3N.jpg',
        'http://i.imgur.com/wKnaB4C.jpg',
        'http://i.imgur.com/zRclqdO.jpg',
        'http://kil.gr/sandbox/secret/fedbot/jude.jpg',
        'http://kil.gr/sandbox/secret/fedbot/judepad.jpg',
        'http://kil.gr/sandbox/secret/fedbot/perrycheese.gif',
        'http://www.gyford.com/images/jude.jpg'
    ]

};

Add a bunch of FED images


var diffSteer = require('./diff_steer');

function explicate(motorSpeed) {
  var motorDirection = motorSpeed < 0 ? motorControl.revMethod : motorControl.fwdMethod;
  return [motorDirection, Math.abs(motorSpeed)];
}

function motorControl(wheels, leftRightAxis, upDownAxis, maxAxis, minAxis, maxSpeed, axisFlip) {
  var leftMotor;
  var leftMotorDirection;
  var leftMotorSpeed = 0;
  var motorSpeeds;
  var rightMotor;
  var rightMotorDirection;
  var rightMotorSpeed = 0;

  // Map differential steering values to motor commands
  motorSpeeds = diffSteer(leftRightAxis, upDownAxis, maxAxis, minAxis, maxSpeed, axisFlip);
  leftMotor = explicate(motorSpeeds[0]);
  leftMotorDirection = leftMotor[0];
  leftMotorSpeed = leftMotor[1];
  rightMotor = explicate(motorSpeeds[1]);
  rightMotorDirection = rightMotor[0];
  rightMotorSpeed = rightMotor[1];

  wheels[0][leftMotorDirection](leftMotorSpeed);
  wheels[1][rightMotorDirection](rightMotorSpeed);

  return [
    {
      direction: leftMotorDirection,
      speed: leftMotorSpeed
    },
    {
      direction: rightMotorDirection,
      speed: rightMotorSpeed
    }
  ];
}
motorControl.fwdMethod = 'fwd';
motorControl.revMethod = 'rev';

module.exports = motorControl;

var diffSteer = require('./diff_steer');

function explicate(motorSpeed) {
  var motorDirection = motorSpeed < 0 ? motorControl.revMethod : motorControl.fwdMethod;
  return [motorDirection, Math.abs(motorSpeed)];
}

function motorControl(wheels, leftRightAxis, upDownAxis, maxAxis, minAxis, maxSpeed, axisFlip) {
  var leftMotor;
  var leftMotorDirection;
  var leftMotorSpeed = 0;
  var motorSpeeds;
  var rightMotor;
  var rightMotorDirection;
  var rightMotorSpeed = 0;

  // Map differential steering values to motor commands
  motorSpeeds = diffSteer(leftRightAxis, upDownAxis, maxAxis, minAxis, maxSpeed, axisFlip);
  leftMotor = explicate(motorSpeeds[0]);
  leftMotorDirection = leftMotor[0];
  leftMotorSpeed = leftMotor[1];
  rightMotor = explicate(motorSpeeds[1]);
  rightMotorDirection = rightMotor[0];
  rightMotorSpeed = rightMotor[1];

  if(wheels) {
    wheels[0][leftMotorDirection](leftMotorSpeed);
    wheels[1][rightMotorDirection](rightMotorSpeed);
  }

  return [
    {
      direction: leftMotorDirection,
      speed: leftMotorSpeed
    },
    {
      direction: rightMotorDirection,
      speed: rightMotorSpeed
    }
  ];
}
motorControl.fwdMethod = 'fwd';
motorControl.revMethod = 'rev';

module.exports = motorControl;

Add branch to allow opt-out of automatic motor control


'use strict';

const process = require('process');
const JsonDB = require('node-json-db');

let instance = null;
let app = null;

/* To make the util runnable in both main and renderer process */
if (process.type === 'renderer') {
	app = require('electron').remote.app;
} else {
	app = require('electron').app;
}

class ConfigUtil {
	constructor() {
		if (instance) {
			return instance;
		} else {
			instance = this;
		}

		this.db = new JsonDB(app.getPath('userData') + '/config.json', true, true);
		return instance;
	}

	getConfigItem(key, defaultValue = null) {
		const value = this.db.getData('/')[key];
		if (value === undefined) {
			this.setConfigItem(key, defaultValue);
			return defaultValue;
		} else {
			return value;
		}
	}

	setConfigItem(key, value) {
		this.db.push(`/${key}`, value, true);
	}

	removeConfigItem(key) {
		this.db.delete(`/${key}`);
	}
}

module.exports = new ConfigUtil();

'use strict';

const process = require('process');
const JsonDB = require('node-json-db');

let instance = null;
let app = null;

/* To make the util runnable in both main and renderer process */
if (process.type === 'renderer') {
	app = require('electron').remote.app;
} else {
	app = require('electron').app;
}

class ConfigUtil {
	constructor() {
		if (instance) {
			return instance;
		} else {
			instance = this;
		}

		this.db = new JsonDB(app.getPath('userData') + '/settings.json', true, true);
		return instance;
	}

	getConfigItem(key, defaultValue = null) {
		const value = this.db.getData('/')[key];
		if (value === undefined) {
			this.setConfigItem(key, defaultValue);
			return defaultValue;
		} else {
			return value;
		}
	}

	setConfigItem(key, value) {
		this.db.push(`/${key}`, value, true);
	}

	removeConfigItem(key) {
		this.db.delete(`/${key}`);
	}
}

module.exports = new ConfigUtil();

Change config filename to avoid conflict.


var path = require('path');
var fs = require('fs');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = function(options) {
  return {
    entry: [
      'webpack-dev-server/client?http://localhost:' + options.port,
      'webpack/hot/only-dev-server',
      options.entryFile
    ],
    output: {
      path: path.resolve(options.root, 'build'),
      filename: 'app.js',
      pathinfo: true,
      // contentBase: fs.existsSync(path.resolve(options.root, 'index.html')) ? path.resolve(options.root) : __dirname
      contentBase: path.resolve(options.root)
    },
    devtool: '#eval-source-map',
    plugins: [
      new webpack.HotModuleReplacementPlugin(),
      new webpack.DefinePlugin(options.globals),
      new HtmlWebpackPlugin({
        title: options.package.name,
        template: fs.existsSync(path.resolve(options.root, 'index.html')) ? path.resolve(options.root, 'index.html') :'index.html',
        inject: 'body',
        description: options.package.description,
        version: options.package.version
      })
    ],
    // Packup-specific options, not directly used by webpack
    port: options.port,
    loaders: {
      js: {
        loaders: ['react-hot', 'babel']
      }
    }
  };
}

var path = require('path');
var fs = require('fs');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = function(options) {
  return {
    entry: [
      'webpack-dev-server/client?http://localhost:' + options.port,
      'webpack/hot/only-dev-server',
      options.entryFile
    ],
    output: {
      path: path.resolve(options.root, 'build'),
      filename: 'app.js',
      pathinfo: true,
      // contentBase: fs.existsSync(path.resolve(options.root, 'index.html')) ? path.resolve(options.root) : __dirname
      contentBase: path.resolve(options.root)
    },
    devtool: '#eval-source-map',
    plugins: [
      new webpack.HotModuleReplacementPlugin(),
      new webpack.DefinePlugin(options.globals),
      new HtmlWebpackPlugin({
        title: options.package.name,
        template: fs.existsSync(path.resolve(options.root, 'index.html')) ? path.resolve(options.root, 'index.html') : path.resolve(__dirname, 'index.html'),
        inject: 'body',
        description: options.package.description,
        version: options.package.version
      })
    ],
    // Packup-specific options, not directly used by webpack
    port: options.port,
    loaders: {
      js: {
        loaders: ['react-hot', 'babel']
      }
    }
  };
}

Fix resolving of packup index.html template


/**
 * Terminal Module for the Cloud9
 *
 * @copyright 2013, Ajax.org B.V.
 */

define(function(require, exports, module) {
    "use strict";

    var MessageHandler = function(messageMatchers, messageView) {
        this.messageMatchers = messageMatchers;
        this.messageView = messageView;
    };

    var proto = MessageHandler.prototype;

    proto.handleMessage = function(data, tab) {
        this.messageMatchers.forEach(function(trigger) {
            trigger.pattern.test(data) && this.messageView.show(trigger.message, trigger.action, tab);
        }, this);
    };

    proto.reposition = function(tab) {
        this.messageView.repositionMessages(tab);
    };

    proto.hide = function(message) {
        this.messageView.hide(message);
    }

    module.exports = MessageHandler;
});

/**
 * Terminal Module for the Cloud9
 *
 * @copyright 2013, Ajax.org B.V.
 */

define(function(require, exports, module) {
    "use strict";

    var MessageHandler = function(messageMatchers, messageView) {
        this.messageMatchers = messageMatchers;
        this.messageView = messageView;
    };

    var proto = MessageHandler.prototype;

    proto.handleMessage = function(data, tab) {
        this.messageMatchers.forEach(function(trigger) {
            var matches = trigger.pattern.exec(data);

            if (matches !== null) {
                var message = trigger.message;

                matches.map(function(value, key) {
                    message = message.replace("{" + key + "}", value);
                });

                this.messageView.show(message, trigger.action, tab);
            }
        }, this);
    };

    proto.reposition = function(tab) {
        this.messageView.repositionMessages(tab);
    };

    proto.hide = function(message) {
        this.messageView.hide(message);
    }

    module.exports = MessageHandler;
});

Add match references {1}, {2} in messages


import React from 'react';
import styles from './styles';
import DevTools from './containers/DevTools';
import createRemoteStore from './store/createRemoteStore';
import ButtonBar from './components/ButtonBar';

export default ({ socketOptions }) => (
  <div style={styles.container}>
    <DevTools store={createRemoteStore(socketOptions)} />
    <ButtonBar/>
  </div>
);

import React, { Component, PropTypes } from 'react';
import styles from './styles';
import DevTools from './containers/DevTools';
import createRemoteStore from './store/createRemoteStore';
import ButtonBar from './components/ButtonBar';

export default class extends Component {
  static propTypes = {
    socketOptions: PropTypes.shape({
      hostname: PropTypes.string,
      port: PropTypes.number,
      autoReconnect: PropTypes.bool
    })
  };

  componentWillMount() {
    this.store = createRemoteStore(this.props.socketOptions);
  }

  render() {
    return (
      <div style={styles.container}>
        <DevTools store={this.store} />
        <ButtonBar/>
      </div>
    );
  }
}

Use React Component for the main container


const { environment } = require('@rails/webpacker')

// config
const alias = require('./config/alias')
const terser = require("./config/terser");
const splitChunks = require("./config/splitChunks");
const output = require('./config/output')

environment.config.merge(alias)
environment.config.merge(terser)
environment.config.merge(splitChunks)
environment.config.merge(output)

// loaders
const vue = require('./loaders/vue')
const less = require('./loaders/less')

environment.loaders.append('less', less)
environment.loaders.append('vue', vue)
environment.loaders.delete('moduleCss')
environment.loaders.delete('moduleSass')
environment.loaders.delete('nodeModules')

// plugins
const webpack = require('webpack')
const { VueLoaderPlugin } = require('vue-loader')
const MomentLocalesPlugin = require('moment-locales-webpack-plugin')

environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin())
environment.plugins.append(
  "Provide",
  new webpack.ProvidePlugin({
    $: "jquery",
    "window.$": "jquery",
    jQuery: "jquery",
    "window.jQuery": "jquery",
    _: "lodash"
  })
)
// NOTE: Must be updated if add a new locale files - https://yarnpkg.com/es-ES/package/moment-locales-webpack-plugin
environment.plugins.append(
  "MomentLocales",
  new MomentLocalesPlugin({
    localesToKeep: ["es", "ca"]
  })
)

module.exports = environment

const { environment } = require('@rails/webpacker')

// config
const alias = require('./config/alias')
const splitChunks = require("./config/splitChunks");
const output = require('./config/output')

environment.config.merge(alias)
environment.config.merge(splitChunks)
environment.config.merge(output)

// loaders
const vue = require('./loaders/vue')
const less = require('./loaders/less')

environment.loaders.append('less', less)
environment.loaders.append('vue', vue)
environment.loaders.delete('moduleCss')
environment.loaders.delete('moduleSass')
environment.loaders.delete('nodeModules')

// plugins
const webpack = require('webpack')
const { VueLoaderPlugin } = require('vue-loader')
const MomentLocalesPlugin = require('moment-locales-webpack-plugin')

environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin())
environment.plugins.append(
  "Provide",
  new webpack.ProvidePlugin({
    $: "jquery",
    "window.$": "jquery",
    jQuery: "jquery",
    "window.jQuery": "jquery",
    _: "lodash"
  })
)
// NOTE: Must be updated if add a new locale files - https://yarnpkg.com/es-ES/package/moment-locales-webpack-plugin
environment.plugins.append(
  "MomentLocales",
  new MomentLocalesPlugin({
    localesToKeep: ["es", "ca"]
  })
)

module.exports = environment

Remove Terser specifics from the shared configuration


'use strict'

const tabs = require('sdk/tabs')
const parent = require('sdk/remote/parent')
const self = require('sdk/self')
const testpage = self.data.url('linkify-demo.html')
const prefs = require('sdk/simple-prefs').prefs

require('../lib/rewrite-pages.js')
parent.remoteRequire('resource://ipfs-firefox-addon-at-lidel-dot-org/lib/rewrite-pages.js')

exports['test link processing, plain text conversion'] = function (assert, done) {
  prefs.linkify = true
  prefs.fsUris = true

  tabs.open({
    url: testpage,
    onReady: (tab) => {
      let worker = tab.attach({
        contentScript: `
          self.port.emit("test result", {
            numLinks: document.querySelectorAll('#plain-links > a').length,
            relativeScheme: document.querySelector('#relative-ipfs-path').protocol
          })
        `
      })
      worker.port.on('test result', (msg) => {
        assert.equal(msg.numLinks | 0, 4, 'number of linkified plaintext chunks')
        assert.equal(msg.relativeScheme, 'fs:', 'relative ipfs reference rewritten to fs: scheme')

        tab.close(done)
      })
    }
  })
}

require('./prefs-util.js').isolateTestCases(exports)
require('sdk/test').run(exports)

'use strict'

const tabs = require('sdk/tabs')
const self = require('sdk/self')
const testpage = self.data.url('linkify-demo.html')
const prefs = require('sdk/simple-prefs').prefs

exports['test link processing, plain text conversion'] = function (assert, done) {
  prefs.linkify = true
  prefs.fsUris = true

  tabs.open({
    url: testpage,
    onReady: (tab) => {
      // first load in test env doesn't have onload handlers registered (probably due to prefs-util.js harness).
      // this is quick hack to reload the page and work around test framework limitation
      if (tab.url !== testpage + '?foo') {
        tab.url = testpage + '?foo'
        return
      }
      let worker = tab.attach({
        contentScript: `
          self.port.emit('test result', {
            numLinks: document.querySelectorAll('#plain-links > a').length,
            relativeScheme: document.querySelector('#relative-ipfs-path').protocol
          })
        `
      })
      worker.port.on('test result', (msg) => {
        assert.equal(msg.numLinks | 0, 4, 'number of linkified plaintext chunks')
        assert.equal(msg.relativeScheme, 'fs:', 'relative ipfs reference rewritten to fs: scheme')

        tab.close(done)
      })
    }
  })
}

require('./prefs-util.js').isolateTestCases(exports)
require('sdk/test').run(exports)

Fix tests under Nightly 50.0a1


import  { ADD_ACCEPT_NAME, ADD_REJECT_NAME }  from '../actions/name-actions';

const initialState = {
    accepted: [],
    rejected: []
}

export default function (state = initialState, action) {
    switch (action.type) {
        case ADD_ACCEPT_NAME: {
            console.log(...state);
            console.log(...state.accepted);
            console.log(action.payload);

            return {
                ...state,
                accepted: [...state.accepted, action.payload]
            }
        }

        case ADD_REJECT_NAME: {
            return {
                ...state,
                rejected: [...state.rejected, action.payload]
            }
        }

        default:
            return state;
    }
}

import  { ADD_ACCEPT_NAME, ADD_REJECT_NAME, GET_NAMES, INCREMENT, RESTART }  from '../actions/name-actions';
import { Shuffle } from 'lodash';
import names from '../data/names.json';

console.log(names)

const initialState = {
    //names: (typeof localStorage["gender"] != "undefined") ? Shuffle(names[JSON.parse(localStorage.getItem('gender'))]) : [],
    names: names,
    accepted: [],
    rejected: [],
    index: 0
}

export default function (state = initialState, action) {
    switch (action.type) {
        case ADD_ACCEPT_NAME: {
            return {
                ...state,
                accepted: [...state.accepted, action.payload]
            }
        }

        case ADD_REJECT_NAME: {
                return {
                ...state,
                rejected: [...state.rejected, action.payload]
            }
        }

        case GET_NAMES: {
            return {
                names: names
            }
        }

        case INCREMENT: {
            return {
                ...state,
                index: state.index + 1
            }
        }

        case RESTART: {
            return {
                ...state,
                index: 0,
                accepted: [],
                rejected: []
            }
        }

        default:
            return state;
    }
}

Add increment and restart methods


import React, { Component } from 'react';

export default class EmojiSuggestionsPortal extends Component {

  componentWillMount() {
    this.props.store.register(this.props.offsetKey);
    this.updatePortalClientRect(this.props);

    // trigger a re-render so the EmojiSuggestions becomes active
    this.props.setEditorState(this.props.getEditorState());
  }

  componentWillReceiveProps(nextProps) {
    this.updatePortalClientRect(nextProps);
  }

  componentWillUnmount() {
    this.props.store.unregister(this.props.offsetKey);
  }

  updatePortalClientRect(props) {
    this.props.store.updatePortalClientRect(
      props.offsetKey,
      () => (
        this.searchPortal.getBoundingClientRect()
      ),
    );
  }

  render() {
    return (
      <span
        className={this.key}
        ref={(element) => { this.searchPortal = element; }}
      >
        {this.props.children}
      </span>
    );
  }
}

import React, { Component } from 'react';

export default class EmojiSuggestionsPortal extends Component {

  constructor(props) {
  	super(props);
    this.searchPortalRef = (element) => { this.searchPortal = element; };
  }

  componentWillMount() {
    this.props.store.register(this.props.offsetKey);
    this.updatePortalClientRect(this.props);

    // trigger a re-render so the EmojiSuggestions becomes active
    this.props.setEditorState(this.props.getEditorState());
  }

  componentWillReceiveProps(nextProps) {
    this.updatePortalClientRect(nextProps);
  }

  componentWillUnmount() {
    this.props.store.unregister(this.props.offsetKey);
  }

  updatePortalClientRect(props) {
    this.props.store.updatePortalClientRect(
      props.offsetKey,
      () => (
        this.searchPortal.getBoundingClientRect()
      ),
    );
  }

  render() {
    return (
      <span
        className={this.key}
        ref={this.searchPortalRef}
      >
        {this.props.children}
      </span>
    );
  }
}

Move searchPortal ref function to constructor


var Handlebars = require('handlebars');

function Exbars(options) {
  this.defaultLayout = options.defaultLayout ? options.defaultLayout : null;
  this.handlebars = Handlebars;
  this.compilerOptions = options.compilerOptions ? options.compilerOptions : {};
  this.compiledTemplates = {};

  this.registerHelper = function(name, helper) {
    return this.handlebars.registerHelper(name, helper);
  };

  this.registerPartial = function(name, content) {
    return this.handlebars.registerPartial(name, content);
  };

  this.compile = function(template, content) {
    this.compiledTemplates[template] = this.handlebars.compile(content, this.compilerOptions);
  };

  this.render = function(filePath, options, callback) {
    var template = this.compiledTemplates[filePath];
    var layout = options.layout === null ? null : options.layout || this.defaultLayout;
    if(layout) {
      var layoutTemplate = this.compiledTemplates[process.cwd() + '/views/layouts/' + layout + '.hbs'];
      options.body = template(options);
      return callback(null, layoutTemplate(options));
    }
    return callback(null, template(options));
  };

  this.engine = function() {
    return this.render.bind(this);
  };
}

module.exports = Exbars;

var Handlebars = require('handlebars');

function Exbars(options) {
  this.defaultLayout = options.defaultLayout ? options.defaultLayout : null;
  this.compilerOptions = options.compilerOptions ? options.compilerOptions : {};
  this.handlebars = Handlebars;
  this.compiledTemplates = {};

  this.registerHelper = function(name, helper) {
    return this.handlebars.registerHelper(name, helper);
  };

  this.registerPartial = function(name, content) {
    return this.handlebars.registerPartial(name, content);
  };

  this.compile = function(template, content) {
    this.compiledTemplates[template] = this.handlebars.compile(content, this.compilerOptions);
  };

  this.render = function(filePath, options, callback) {
    var template = this.compiledTemplates[filePath];
    var layout = options.layout === false ? null : options.layout || this.defaultLayout;
    if(layout) {
      var layoutTemplate = this.compiledTemplates[process.cwd() + '/views/layouts/' + layout + '.hbs'];
      options.body = template(options);
      return callback(null, layoutTemplate(options));
    }
    return callback(null, template(options));
  };

  this.engine = function() {
    return this.render.bind(this);
  };
}

module.exports = Exbars;

Use false instead of null to avoid using a layout


var fs = require('fs');
var path = require('path');
var semver = require('semver');
var execSync = require('child_process').execSync;
var packageJSONPath = path.join(process.cwd(), 'package.json');
var packageJSON = require(packageJSONPath);

module.exports = function(newVersion, commitMessage){
  var newSemver = packageJSON.version = getNewSemver(newVersion);
  fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON, null, 2));
  commitMessage = (commitMessage || 'Release v%s').replace(/%s/g, newSemver);
  execCmd('git commit -am "' + commitMessage + '"');
  execCmd('git tag v' + newSemver);
  execCmd('git push origin --all');
  execCmd('git push origin --tags');
  if (!packageJSON.private) execCmd('npm publish');
};

function getNewSemver(newVersion) {
  var newSemver = semver.valid(newVersion);
  if (!newSemver) newSemver = semver.inc(packageJSON.version, newVersion);
  if (!newSemver) throw new Error('Invalid new version');
  return newSemver;
}

function execCmd(cmd) {
  console.log(execSync(cmd).toString());
}

var fs = require('fs');
var path = require('path');
var semver = require('semver');
var execSync = require('child_process').execSync;
var packageJSONPath = path.join(process.cwd(), 'package.json');
var packageJSON = require(packageJSONPath);

module.exports = function(newVersion, commitMessage){
  var newSemver = packageJSON.version = getNewSemver(newVersion);
  fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON, null, 2));
  commitMessage = (commitMessage || 'Release v%s').replace(/%s/g, newSemver);
  execCmd('git commit -am "' + commitMessage + '"');
  execCmd('git tag v' + newSemver);
  execCmd('git push origin --all');
  execCmd('git push origin --tags');
  if (!packageJSON.private) execCmd('npm publish');
};

function getNewSemver(newVersion) {
  var newSemver = semver.valid(newVersion);
  if (!newSemver) newSemver = semver.inc(packageJSON.version, newVersion);
  if (!newSemver) throw new Error('Invalid new version');
  return newSemver;
}

function execCmd(cmd) {
  console.log(execSync(cmd).toString().trim());
}

Clean up the command output


let AutomaticComponent = require('./AutomaticComponent');

class Css extends AutomaticComponent {
    /**
     * webpack rules to be appended to the master config.
     */
    webpackRules() {
        return [
            {
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader']
            },

            // We're not doing test: /\.s[ca]ss/ for a reason, related to Vue SFP's.
            // Don't merge.
            {
                test: /\.scss$/,
                exclude: this.excludePathsFor('sass'),
                loaders: ['style-loader', 'css-loader', 'sass-loader']
            },

            {
                test: /\.sass$/,
                exclude: this.excludePathsFor('sass'),
                loaders: ['style-loader', 'css-loader', 'sass-loader']
            },

            {
                test: /\.less$/,
                exclude: this.excludePathsFor('less'),
                loaders: ['style-loader', 'css-loader', 'less-loader']
            }
        ];
    }

    /**
     * Paths to be excluded from the loader.
     *
     * @param {string} preprocessor
     */
    excludePathsFor(preprocessor) {
        let exclusions = Mix.components.get(preprocessor);

        return exclusions
            ? exclusions.details.map(preprocessor => preprocessor.src.path())
            : [];
    }
}

module.exports = Css;

let AutomaticComponent = require('./AutomaticComponent');

class Css extends AutomaticComponent {
    /**
     * webpack rules to be appended to the master config.
     */
    webpackRules() {
        return [
            {
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader']
            },

            {
                test: /\.scss$/,
                exclude: this.excludePathsFor('sass'),
                loaders: ['style-loader', 'css-loader', 'sass-loader']
            },

            {
                test: /\.sass$/,
                exclude: this.excludePathsFor('sass'),
                loaders: [
                    'style-loader',
                    'css-loader',
                    { loader: 'sass-loader', options: { indentedSyntax: true } }
                ]
            },

            {
                test: /\.less$/,
                exclude: this.excludePathsFor('less'),
                loaders: ['style-loader', 'css-loader', 'less-loader']
            }
        ];
    }

    /**
     * Paths to be excluded from the loader.
     *
     * @param {string} preprocessor
     */
    excludePathsFor(preprocessor) {
        let exclusions = Mix.components.get(preprocessor);

        return exclusions
            ? exclusions.details.map(preprocessor => preprocessor.src.path())
            : [];
    }
}

module.exports = Css;

Add indented syntax for .sass files


import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';

import Shortcuts from '../widgets/shortcuts';
import Status from '../widgets/status';

const style = {
  header: {
    fg: '#ffff00',
    bg: '#0000d3',
    bold: true,
  },
  center: {
    bg: '#e7e7e7',
  },
};

class App extends Component {

  static propTypes = {
    children: PropTypes.node,
    status: PropTypes.string,
    shortcuts: PropTypes.array,
  };

  render () {
    const { children, status } = this.props;
    const shortcuts = [
      { key: 'Q', label: 'Quit' },
      { key: 'Escape', label: 'Back' },
      ...this.props.shortcuts,
    ];
    return (
      <box top={0} left={0} bottom={0} right={0} style={style.header}>
        <text tags="true" style={style.header} content=" SQLectron" />
        <box top={1} left={0} right={0} bottom={2} style={style.center}>
          {children}
        </box>
        <Status status={status} />
        <Shortcuts shortcuts={shortcuts} />
      </box>
    );
  }
}

export default connect(
  state => ({
    status: state.status,
    shortcuts: state.shortcuts,
  })
)(App);

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';

import Shortcuts from '../widgets/shortcuts';
import Status from '../widgets/status';

const style = {
  header: {
    fg: '#ffff00',
    bg: '#0000d3',
    bold: true,
  },
  center: {
    bg: '#e7e7e7',
  },
};

class App extends Component {

  static propTypes = {
    children: PropTypes.node,
    status: PropTypes.string,
    shortcuts: PropTypes.array,
  };

  render () {
    const { children, status } = this.props;
    const shortcuts = [
      { key: 'q', label: 'Quit' },
      { key: 'escape', label: 'Back' },
      ...this.props.shortcuts,
    ];
    return (
      <box top={0} left={0} bottom={0} right={0} style={style.header}>
        <text tags="true" style={style.header} content=" SQLectron" />
        <box top={1} left={0} right={0} bottom={2} style={style.center}>
          {children}
        </box>
        <Status status={status} />
        <Shortcuts shortcuts={shortcuts} />
      </box>
    );
  }
}

export default connect(
  state => ({
    status: state.status,
    shortcuts: state.shortcuts,
  })
)(App);

Update list of basic shortcuts to follow standard


// import Ember from 'ember';
import BaseComponent from './-base-toplevel-component';
import RippleSupport from '../mixins/ripple-support';
import layout from '../templates/components/mdl-button';
import computed from 'ember-new-computed';

export default BaseComponent.extend(RippleSupport, {
  primaryClassName: 'button',
  tagName: 'button',
  icon: null,
  isColored: true,
  isRaised: false,
  isFloating: false,
  isMiniFab: false,
  isAccent: false,
  _mdlComponent: null,
  'for': null,
  _isIconMode: computed('icon', 'isFloating', {
    get() {
      return !this.get('isFloating') && this.get('icon');
    }
  }),
  attributeBindings: ['disabled', 'for'],
  classNameBindings: [
    'isMiniFab:mdl-button--mini-fab',
    'isAccent:mdl-button--accent',
    'isRaised:mdl-button--raised',
    '_isIconMode:mdl-button--icon',
    'isColored:mdl-button--colored',
    'isFloating:mdl-button--fab'],
  layout,

  didInsertElement() {
    this._super(...arguments);
    let mdlbtn = new window.MaterialButton(this.get('element'));
    this.set('_mdlComponent', mdlbtn);
  },

  click() {
    this.sendAction();
  }
});

// import Ember from 'ember';
import BaseComponent from './-base-toplevel-component';
import RippleSupport from '../mixins/ripple-support';
import layout from '../templates/components/mdl-button';
import computed from 'ember-new-computed';

export default BaseComponent.extend(RippleSupport, {
  primaryClassName: 'button',
  tagName: 'button',
  icon: null,
  isColored: true,
  isRaised: false,
  isFloating: false,
  isMiniFab: false,
  isAccent: false,
  _mdlComponent: null,
  'for': null,
  _isIconMode: computed('icon', 'isFloating', {
    get() {
      return !this.get('isFloating') && this.get('icon');
    }
  }),
  attributeBindings: ['disabled', 'for'],
  classNameBindings: [
    'isMiniFab:mdl-button--mini-fab',
    'isAccent:mdl-button--accent',
    'isRaised:mdl-button--raised',
    '_isIconMode:mdl-button--icon',
    'isColored:mdl-button--colored',
    'isFloating:mdl-button--fab'],
  layout,

  didInsertElement() {
    this._super(...arguments);
    let mdlbtn = new window.MaterialButton(this.get('element'));
    this.set('_mdlComponent', mdlbtn);
  },

  click() {
    this.sendAction(this);
  }
});

Send button component when clicked


import { evalFloatStr } from '../float'
import { onChange } from '../state'
import { numberCharWidth, somePxls } from './inputCharWidth'

const $float = document.getElementById('float')

const setFloatValue = floatStr => { $float.value = floatStr }

const setFloatOrJs = floatStrOrJs => { set({ fStr: floatStrOrJs }) }

let applyFloat = () => {}

const updateApplyFloat = f64 => {
  applyFloat = (floatStrOrJs) => {
    const floatStr = evalFloatStr(f64)(floatStrOrJs)
    setFloatValue(floatStr)
    set({ fStr: floatStr })
  }
}

$float.addEventListener('input', e => { setFloatOrJs(e.target.value) }, false)
$float.addEventListener('keydown', e => {
  if (e.keyCode === 13) { // On Enter
    applyFloat(e.target.value)
  }
}, false)

const floatCharWidth = 32

const setFloatWidth = () => {
  $float.style.width = `${Math.round(numberCharWidth * floatCharWidth) + somePxls}px`
}

const set = onChange(state => {
  const { fStr, f64 } = state
  updateApplyFloat(f64)
  setFloatValue(fStr)
  setFloatWidth()
})

import { evalFloatStr } from '../float'
import { onChange } from '../state'
import { numberCharWidth, somePxls } from './inputCharWidth'

const $float = document.getElementById('float')

const setFloatValue = floatStr => { $float.value = floatStr }

const setFloatOrJs = floatStrOrJs => { set({ fStr: floatStrOrJs }) }

let applyFloat = () => {}

const updateApplyFloat = f64 => {
  applyFloat = (floatStrOrJs) => {
    const floatStr = evalFloatStr(f64)(floatStrOrJs)
    setFloatValue(floatStr)
    set({ fStr: floatStr })
  }
}

$float.addEventListener('input', e => { setFloatOrJs(e.target.value) }, false)
$float.addEventListener('keydown', e => {
  if (e.keyCode === 13) { // On Enter
    applyFloat(e.target.value)
  }
}, false)

const floatCharWidth = 32

const setFloatWidth = () => {
  $float.style.width = `${Math.round(numberCharWidth * floatCharWidth) + somePxls}px`
}

const set = onChange(state => {
  const { f64 } = state
  let { fStr } = state
  if (!f64 && evalFloatStr(true)(fStr) === fStr) {
    fStr = evalFloatStr(false)(fStr)
  }
  updateApplyFloat(f64)
  setFloatValue(fStr)
  setFloatWidth()
})

Convert to 32 float in float input


//= require d3.v2
//= require lib/models/metric
//= require lib/models/quantity
//= require jquery.quinn.min
//= require establishment_shot/main
//= require establishment_shot/error_handler
//= require establishment_shot/scenario_creator
//= require establishment_shot/scenario_updater
//= require energy_mix/stackedBarChart
//= require establishment_shot/charts/bar_chart
//= require establishment_shot/charts
//= require establishment_shot/text_updater
//= require establishment_shot/chart_renderer
//= require establishment_shot/toggle_year

$(document).ready(function () {
  new EstablishmentShot.Main($("#establishment_shot")).render();
});

//= require d3.v2
//= require lib/models/metric
//= require lib/models/quantity
//= require jquery.quinn
//= require establishment_shot/main
//= require establishment_shot/error_handler
//= require establishment_shot/scenario_creator
//= require establishment_shot/scenario_updater
//= require energy_mix/stackedBarChart
//= require establishment_shot/charts/bar_chart
//= require establishment_shot/charts
//= require establishment_shot/text_updater
//= require establishment_shot/chart_renderer
//= require establishment_shot/toggle_year

$(document).ready(function () {
  new EstablishmentShot.Main($("#establishment_shot")).render();
});

Use non-minified Quinn in establishment shot


'use strict';

export default class Game {
  constructor() {
    console.log('Game - construct');
  }

  start() {
    console.log('Game - start');
  }
}

'use strict';

import bindAll from 'lodash.bindAll';
import raf from 'raf';

export default class Game {
  constructor() {
    bindAll(this, 'update');

    console.log('Game - construct');
  }

  start() {
    console.log('Game - start');

    // TODO: init the game

    this.update();
  }

  update() {
    raf(this.update);

    // TODO: update all the entities

    this.render();
  }

  render() {
    // TODO: render all the things
  }
}

Add update and render methods


'use strict';

angular.module('confRegistrationWebApp')
  .constant('apiUrl', 'http://dev.api.formvent.org/eventhub-api/rest/');

'use strict';

angular.module('confRegistrationWebApp')
  .constant('apiUrl', 'https://api.eventhub.org/eventhub-api/rest/');

Change from dev.api.formvent to api.eventhub.org


var Marionette = require('backbone.marionette'),
    RowLabelCell = require('./cell/RowLabelCell');

var TableRow = Marionette.ItemView.extend({
   tagName: 'tr',

   prependCellType: RowLabelCell,
   appendCellType: RowLabelCell,
   cellType: RowLabelCell,

   render: function() {
      var self = this;

      // Render the prepended cell if the type is set
      // and we have an entry for it in the model
      this._appendCell(this.prependCellType, this.model.get('prepended'));

      // Render the main content for the row
      this.model.get('members').each(function(entry) {
         self._appendCell(self.cellType, {
            'entry': entry.get('amount')
         });
      });

      // Render the appended cell if the type is set
      // and we have an entry for it in the model
      this._appendCell(this.appendedCellType, this.model.get('appended'));
   },

   _appendCell: function(type, model) {
      if (!type || !model) {
         return;
      }

      var cell = new type({
         'model': model
      });
      cell.render();
      this.$el.append(cell.$el);
   }
});

module.exports = TableRow;

var Marionette = require('backbone.marionette'),
    RowLabelCell = require('./cell/RowLabelCell');

var TableRow = Marionette.ItemView.extend({
   tagName: 'tr',

   options: {
      prependCellType: RowLabelCell,
      appendCellType: RowLabelCell,
      cellType: RowLabelCell,
   },

   render: function() {
      var self = this;

      // Render the prepended cell if the type is set
      // and we have an entry for it in the model
      this._appendCell(this.options.prependCellType, this.model.get('prepended'));

      // Render the main content for the row
      this.model.get('members').each(function(entry) {
         self._appendCell(self.options.cellType, {
            'entry': entry.get('amount')
         });
      });

      // Render the appended cell if the type is set
      // and we have an entry for it in the model
      this._appendCell(this.options.appendedCellType, this.model.get('appended'));
   },

   _appendCell: function(type, model) {
      if (!type || !model) {
         return;
      }

      var cell = new type({
         'model': model
      });
      cell.render();
      this.$el.append(cell.$el);
   }
});

module.exports = TableRow;

Move row cell types to 'options' object


'use strict';

// EXPORTS //

module.exports = eval;

'use strict';

/**
* Alias for `eval` global.
*
* @module @stdlib/utils/eval
*
* @example
* var evil = require( '@stdlib/utils/@stdlib/utils/eval' );
*
* var v = evil( '5*4*3*2*1' );
* // returns 120
*/

// MODULES //

var evil = eval;

// EXPORTS //

module.exports = evil;

Add JSDoc annotations with examples


var ChatThreadActionCreators = require('../actions/ChatThreadActionCreators');
var React = require('react');
var cx = require('react/lib/cx');
var TimeAgo = require('./TimeAgo.react');
var Avatar = require('./Avatar.react');
var Status = require('./Status.react');
var ChatMessageUtils = require('../utils/ChatMessageUtils');
var LeftRightAlign = require('../../../js/components/LeftRightAlign.jsx');
var ReactPropTypes = React.PropTypes;
var Router = require('react-router');
var Link = Router.Link;
var Navigation = Router.Navigation;

var ThreadListItem = React.createClass({

  propTypes: {
    thread: ReactPropTypes.object,
      currentThreadID: ReactPropTypes.string,
      threadType: ReactPropTypes.string.required
  },

  render: function() {
    var thread = this.props.thread;
      var lastMessage = thread.lastMessage;
      var contact = ChatMessageUtils.getMessageOther(this.props.thread.id);
    return (
      <Link className={cx({
          'list-group-item': true,
          'active': thread.id === this.props.currentThreadID
      })} to={this.props.threadType} params={{id: thread.id}}>

{this.props.thread.name}

            <LeftRightAlign>

{contact} [<Status user={contact} />]

<TimeAgo when={lastMessage ? lastMessage.date : new Date()} />

            </LeftRightAlign>
            {lastMessage && lastMessage.text}
        </Link>
    );
  },

});

module.exports = ThreadListItem;

var ChatThreadActionCreators = require('../actions/ChatThreadActionCreators');
var React = require('react');
var cx = require('react/lib/cx');
var TimeAgo = require('./TimeAgo.react');
var Avatar = require('./Avatar.react');
var Status = require('./Status.react');
var ChatMessageUtils = require('../utils/ChatMessageUtils');
var LeftRightAlign = require('../../../js/components/LeftRightAlign.jsx');
var ReactPropTypes = React.PropTypes;
var Router = require('react-router');
var Link = Router.Link;
var Navigation = Router.Navigation;

var ThreadListItem = React.createClass({

  propTypes: {
    thread: ReactPropTypes.object,
      currentThreadID: ReactPropTypes.string,
      threadType: ReactPropTypes.string.isRequired
  },

  render: function() {
    var thread = this.props.thread;
      var lastMessage = thread.lastMessage;
      var contact = ChatMessageUtils.getMessageOther(this.props.thread.id);
    return (
      <Link className={cx({
          'list-group-item': true,
          'active': thread.id === this.props.currentThreadID
      })} to={this.props.threadType} params={{id: thread.id}}>

{this.props.thread.name}

            <LeftRightAlign>

{contact} [<Status user={contact} />]

<TimeAgo when={lastMessage ? lastMessage.date : new Date()} />

            </LeftRightAlign>
            {lastMessage && lastMessage.text}
        </Link>
    );
  },

});

module.exports = ThreadListItem;

Fix ThreadListItem prop type checking


module.exports = {
  CONSUMER_KEY        : "YOUR_CONSUMER_KEY",
  CONSUMER_SECRET     : "YOUR_CONSUMER_SECRET",
  ACCESS_TOKEN_KEY    : "YOUR_ACCESS_TOKEN",
  ACCESS_TOKEN_SECRET : "YOUR_TOKEN_SECRET"
}

module.exports = {
  CONSUMER_KEY        : "YOUR_CONSUMER_KEY",
  CONSUMER_SECRET     : "YOUR_CONSUMER_SECRET",
  ACCESS_TOKEN_KEY    : "YOUR_ACCESS_TOKEN",
  ACCESS_TOKEN_SECRET : "YOUR_TOKEN_SECRET",

  USERNAME            : "YOUR_TWITTER_USERNAME"
}

Include username in config files


RocketChat.API.v1.addRoute('spotlight', { authRequired: true }, {
	get() {
		check(this.queryParams, {
			query: String
		});

		const { query } = this.queryParams;

		let result;
		Meteor.runAsUser(this.userId, () => result = Meteor.call('spotlight', query, null));

		return RocketChat.API.v1.success(result);
	}
});

Add new line at the end of the file


Meteor.startup(function () {

  PostsSearchController = PostsListController.extend({
    view: 'search',
    onBeforeAction: function() {
      var query = this.params.query;
      if ('q' in query) {
        Session.set('searchQuery', query.q);
        if (query.q) {
          Meteor.call('logSearch', query.q)
        }
      }
      this.next();
    }
  });

  Router.onBeforeAction(Router._filters.isAdmin, {only: ['logs']});

  // Search

  Router.route('/search/:limit?', {
    name: 'search',
    controller: PostsSearchController
  });

  // Search Logs

  Router.route('/logs/:limit?', {
    name: 'searchLogs',
    waitOn: function () {
      var limit = this.params.limit || 100;
      if(Meteor.isClient) {
        Session.set('logsLimit', limit);
      }
      return Meteor.subscribe('searches', limit);
    },
    data: function () {
      return Searches.find({}, {sort: {timestamp: -1}});
    },
    fastRender: true
  });

});

Meteor.startup(function () {

  PostsSearchController = PostsListController.extend({
    view: 'search',
    getTitle: function() {
      return i18n.t("Search") + ' - ' + getSetting('title', "Telescope");
    },
    getDescription: function() {
      return getSetting('description');
    },
    onBeforeAction: function() {
      var query = this.params.query;
      if ('q' in query) {
        Session.set('searchQuery', query.q);
        if (query.q) {
          Meteor.call('logSearch', query.q)
        }
      }
      this.next();
    }
  });

  Router.onBeforeAction(Router._filters.isAdmin, {only: ['logs']});

  // Search

  Router.route('/search/:limit?', {
    name: 'search',
    controller: PostsSearchController
  });

  // Search Logs

  Router.route('/logs/:limit?', {
    name: 'searchLogs',
    waitOn: function () {
      var limit = this.params.limit || 100;
      if(Meteor.isClient) {
        Session.set('logsLimit', limit);
      }
      return Meteor.subscribe('searches', limit);
    },
    data: function () {
      return Searches.find({}, {sort: {timestamp: -1}});
    },
    fastRender: true
  });

});

Implement getTitle and getDescription for search


'use strict';

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

module.exports = function(grunt) {
  grunt.registerTask('fixdocs', 'Fixes any problems with the generated documenation', function() {
    var docs = fs.readFileSync('README.md', 'utf8')
      .replace(/\r\n|\r|\n/g, os.EOL)
      .replace(/([\s\S]{3000,})\1\1/g, '$1');
    fs.writeFileSync('README.md', docs);
    grunt.log.ok('Fixed docs');
  });
};

'use strict';

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

module.exports = function(grunt) {
  grunt.registerTask('fixdocs', 'Fixes any problems with the generated documentation', function() {
    var docs = fs.readFileSync('README.md', 'utf8').replace(/\r\n|\r|\n/g, os.EOL);
    fs.writeFileSync('README.md', docs);
    grunt.log.ok('Fixed docs');
  });
};

Revert extra code from 0942687 to fix documentation


var expect = require('chai').expect;
var consider = require('./helpers/consider');
var elda = require('../lib/api.js');

describe('API', function() {

  var instance;

  beforeEach(function() {
    instance = elda();
  });

  describe('respondTo', function() {

    it('should be exposed as a function', function(done) {
      expect(typeof instance.respondTo).to.equal('function');
      done();
    });

    it('should return a promise', function() {
      var actual = instance.respondTo();
      expect(typeof actual.then).to.equal('function');
    });

    it('should reject empty or null messages with an exception', function(done) {
      instance.respondTo(null).then(function() {
        done('Unexpected success');
      }, function(ex) {
        consider(function() {
          expect(ex).to.equal('No message provided');
        }, done);
      });
    });

    it('should analyse and respond to a message', function(done) {
      var expected = 'instruction';
      instance.respondTo(expected).then(function(actual) {
        consider(function() {
          expect(actual).to.equal('Received message: ' + expected);
        }, done);
      }, function(ex) {
        done(ex);
      });
    });
  });
});

var expect = require('chai').expect;
var consider = require('./helpers/consider');
var elda = require('../lib/api.js');

describe('API', function() {

  var instance;

  beforeEach(function() {
    instance = elda();
  });

  describe('respondTo', function() {

    it('should be exposed as a function', function() {
      expect(typeof instance.respondTo).to.equal('function');
    });

    it('should return a promise', function() {
      var actual = instance.respondTo();
      expect(typeof actual.then).to.equal('function');
    });

    it('should reject empty or null messages with an exception', function(done) {
      instance.respondTo(null).then(function() {
        done('Unexpected success');
      }, function(ex) {
        consider(function() {
          expect(ex).to.equal('No message provided');
        }, done);
      });
    });

    it('should analyse and respond to a message', function(done) {
      var expected = 'instruction';
      instance.respondTo(expected).then(function(actual) {
        consider(function() {
          expect(actual).to.equal('Received message: ' + expected);
        }, done);
      }, function(ex) {
        done(ex);
      });
    });
  });
});

Add test to consider message analysis


var test = require('tape');
var child = require('child_process');

test('--client chrome', function(t) {
  var exe = child.spawn('node', ['./bin/cmd.js', '--client', 'chrome', 'fixture/console.js']);
  exe.on('close', function() {
    t.end();
  });

  exe.stdout.on('data', function(data) {
    t.equal(data.toString(), 'ok\n');
    exe.kill();
  });
});

var test = require('tape');
var child = require('child_process');

var bin = './bin/cmd.js';
test('amok --client chrome fixture/console.js', function(t) {
  t.plan(1);

  var exe = child.spawn('node', [bin, '--client', 'chrome', 'test/fixture/console.js']);
  exe.stdout.once('data', function(data) {
    t.equal(data.toString(), 'ok\n');
    exe.kill();
  });
});

Clean up chrome console test case


/**
 * External dependencies
 */
import gulp from 'gulp';

gulp.task( 'copy', () => {
	gulp.src(
		[
			'readme.txt',
			'google-site-kit.php',
			'uninstall.php',
			'dist/*.js',
			'dist/assets/**/*',
			'bin/**/*',
			'includes/**/*',
			'third-party/**/*',
			'!third-party/**/**/{tests,Tests,doc?(s),examples}/**/*',
			'!third-party/**/**/{*.md,*.yml,phpunit.*}',
			'!**/*.map',
			'!bin/local-env/**/*',
			'!bin/local-env/',
			'!dist/admin.js',
			'!dist/adminbar.js',
			'!dist/wpdashboard.js',
		],
		{ base: '.' }
	)
		.pipe( gulp.dest( 'release' ) );
} );

/**
 * External dependencies
 */
import gulp from 'gulp';

gulp.task( 'copy', () => {
	gulp.src(
		[
			'readme.txt',
			'google-site-kit.php',
			'uninstall.php',
			'dist/*.js',
			'dist/assets/**/*',
			'bin/**/*',
			'includes/**/*',
			'third-party/**/*',
			'!third-party/**/**/{tests,Tests,doc?(s),examples}/**/*',
			'!third-party/**/**/{*.md,*.yml,phpunit.*}',
			'!**/*.map',
			'!bin/local-env/**/*',
			'!bin/local-env/',
			'!dist/admin.js',
			'!dist/adminbar.js',
			'!dist/wpdashboard.js',
		],
		{ base: '.' }
	)
		.pipe( gulp.dest( 'release/google-site-kit' ) );
} );

Copy files directly into release/google-site-kit.


var Client = require('node-rest-client').Client,
    clientOptions = {
      connection: {
        rejectUnauthorized: false,
        requestCert: true,
      }
    },
    client = new Client(clientOptions),
    tokenArgs = {
      'data': {
        'grant_type':'client_credentials',
        'client_id':'foo',
        'client_secret':'bar',
        'scope':'*'
      },
      headers: {
        'Content-Type':'application/json'
      }
    };

client.post('https://api.fronter.com/oauth/token', tokenArgs, function (data, response) {
    console.log(data);

    var clientArgs = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': data['token_type'] + ' ' + data['access_token']
      }
    };

    client.get('https://api.fronter.com/clients/' + tokenArgs['data']['client_id'], clientArgs, function (data, response) {
      console.log(data);
    }).on('error', function (err) {
      console.log('err: ', err);
    });

}).on('error', function (err) {
  console.log('err: ', err);
});

var Client = require('node-rest-client').Client,
    clientOptions = {
      connection: {
        rejectUnauthorized: true,
        requestCert: true,
      }
    },
    client = new Client(clientOptions),

    token = process.argv[2],
    client_id = process.argv[3],

    params = {
      headers: {
        'Content-Type' : 'application/json',
        'Authorization' : 'bearer ' + token
      }
    };

client.get('https://api.fronter.com/clients/' + client_id, params, function (data, response) {
  console.log(data);
}).on('error', function (err) {
  console.error(' get error: ', err);
});

client.on('error', function (err) {
 console.error(' client error : ', err);
});

Use cli parameters for client_id and token.


import React from 'react';

import BuildingWithPoetic from './BuildingWithPoetic';
import ProjectInfoList from './ProjectInfoList';

const poeticUrl = 'http://www.poeticsystems.com';

class ProjectItem extends React.Component {
  shouldComponentUpdate() {
    return false;
  }

  render() {
    const { project } = this.props;

    return (

{project.name}

{project.description}

          <ProjectInfoList subtitle="Languages" list={project.languages} />
          <ProjectInfoList subtitle="Tools" list={project.tools} />

            {project.url ? 'View' : <BuildingWithPoetic />}

    );
  }
}

ProjectItem.propTypes = {
  project: React.PropTypes.object.isRequired,
};

export default ProjectItem;

Change project image class names


// require source components
var componentsContext = require.context('./src', true, /\.js?$/);
componentsContext.keys().forEach(componentsContext);

// require functional tests
var functionalTestsContext = require.context('./test/functional', true, /\.spec\.js?$/);
functionalTestsContext.keys().forEach(functionalTestsContext);

// require unit tests
var unitTestsContext = require.context('./test/unit/classes', true, /\.spec\.js?$/);
unitTestsContext.keys().forEach(unitTestsContext);

// require source components
var componentsContext = require.context('./src', true, /\.js?$/);
componentsContext.keys().forEach(componentsContext);

// require acceptance tests
var acceptanceTestsContext = require.context('./test/acceptance', true, /\.spec\.js?$/);
acceptanceTestsContext.keys().forEach(acceptanceTestsContext);

// require functional tests
var functionalTestsContext = require.context('./test/functional', true, /\.spec\.js?$/);
functionalTestsContext.keys().forEach(functionalTestsContext);

// require unit tests
var classesUnitTestsContext = require.context('./test/unit/classes', true, /\.spec\.js?$/);
classesUnitTestsContext.keys().forEach(classesUnitTestsContext);
var utilUnitTestsContext = require.context('./test/unit/utils', true, /\.spec\.js?$/);
utilUnitTestsContext.keys().forEach(utilUnitTestsContext);

Add acceptance tests and utils tests to Karma


import { module } from 'qunit';
import startApp from '../helpers/start-app';
import destroyApp from '../helpers/destroy-app';

export default function(name, options = {}) {
  module(name, {
    beforeEach: function() {
      this.application = startApp();
      if (options.beforeEach) {
        options.beforeEach.call(this, arguments);
      }
    },

    afterEach: function() {
      destroyApp(this.application);
      if (options.afterEach) {
        options.afterEach.call(this, arguments);
      }
    }
  });
}

import { module } from 'qunit';
import startApp from '../helpers/start-app';
import destroyApp from '../helpers/destroy-app';

export default function(name, options = {}) {
  module(name, {
    beforeEach() {
      this.application = startApp();

      if (options.beforeEach) {
        options.beforeEach.apply(this, arguments);
      }
    },

    afterEach() {
      destroyApp(this.application);

      if (options.afterEach) {
        options.afterEach.apply(this, arguments);
      }
    }
  });
}

Fix beforeEach/afterEach callbacks with moduleForAcceptance.


'use strict'

const FS = require('fs')
const Path = require('path')
const Base = require('./base')

class GenericPlugin extends Base {
  constructor() {
    super()
    this.registerTag(['Compiler-Include'], function(name, value, options) {
      value = Path.resolve(options.internal.file.directory, value)
      options.internal.imports.push(value)
      return new Promise(function(resolve, reject) {
        FS.readFile(value, function (err, data) {
          if (err) return reject(err)
          data = data.toString('utf8')

          const extension = options.internal.file.extension
          if (extension === '.js' || extension === '.coffee') {
            resolve(';(function(){ ' + data + ' })();')
          } else resolve(data)
        })
      })
    })
    this.registerTag(['Compiler-Output'], function(name, value, options) {
      options.Output = Path.resolve(options.internal.file.directory, value)
    })
    this.registerTag(['Compiler-Compress', 'Compiler-Uglify', 'Compiler-Minify'], function(name, value, options) {
      options.Uglify = value === 'true'
    })
    this.registerTag(['Compiler-Babel', 'Compiler-Transpile'], function(name, value, options) {
      options.Babel = value === 'true'
    })
  }
  compile(contents, options) {
    return this.executeTags(contents, options)
  }
}

module.exports = GenericPlugin

'use strict'

const FS = require('fs')
const Path = require('path')
const Base = require('./base')

class GenericPlugin extends Base {
  constructor() {
    super()
    this.registerTag(['Compiler-Include'], function(name, value, options) {
      value = Path.resolve(options.internal.file.directory, value)
      options.internal.imports.push(value)
      return new Promise(function(resolve, reject) {
        FS.readFile(value, function (err, data) {
          if (err) return reject(err)
          data = data.toString('utf8')

          const extension = options.internal.file.extension
          if (extension === '.js' || extension === '.coffee') {
            resolve('; ' + data + ' ;')
          } else resolve(data)
        })
      })
    })
    this.registerTag(['Compiler-Output'], function(name, value, options) {
      options.Output = Path.resolve(options.internal.file.directory, value)
    })
    this.registerTag(['Compiler-Compress', 'Compiler-Uglify', 'Compiler-Minify'], function(name, value, options) {
      options.Uglify = value === 'true'
    })
    this.registerTag(['Compiler-Babel', 'Compiler-Transpile'], function(name, value, options) {
      options.Babel = value === 'true'
    })
  }
  compile(contents, options) {
    return this.executeTags(contents, options)
  }
}

module.exports = GenericPlugin

Remove function wrapping around js includes