export default function getCloneDimensions(node, options) {
  const { parentNode } = node
  const context = document.createElement('div')
  const clone = node.cloneNode(true)
  const style = getComputedStyle(clone)
  let rect = {}

  // give the node some context to measure off of
  // no height and hidden overflow hide node copy
  context.style.height = 0
  context.style.overflow = 'hidden'

  // clean up any attributes that might cause a conflict with the original node
  // i.e. inputs that should focus or submit data
  clone.setAttribute('id', '')
  clone.setAttribute('name', '')

  // set props to get a true dimension calculation
  clone.style.display = options.display || style.getPropertyValue('display')
  if (style.getPropertyValue('width') !== '') {
    clone.style.width = 'auto'
  }
  if (style.getPropertyValue('height') !== '') {
    clone.style.height = 'auto'
  }

  // append copy to context
  context.appendChild(clone)

  // append context to DOM so we can measure
  parentNode.appendChild(context)

  // get accurate width and height
  rect = clone.getBoundingClientRect()

  // destroy clone
  parentNode.removeChild(context)

  return rect
}

export default function getCloneDimensions(node, options) {
  const { parentNode } = node
  const context = document.createElement('div')
  const clone = node.cloneNode(true)
  const style = getComputedStyle(node)
  let rect = {}

  // give the node some context to measure off of
  // no height and hidden overflow hide node copy
  context.style.height = 0
  context.style.overflow = 'hidden'

  // clean up any attributes that might cause a conflict with the original node
  // i.e. inputs that should focus or submit data
  clone.setAttribute('id', '')
  clone.setAttribute('name', '')

  // set props to get a true dimension calculation
  clone.style.display = options.display || style.getPropertyValue('display')
  if (style.getPropertyValue('width') !== '') {
    clone.style.width = 'auto'
  }
  if (style.getPropertyValue('height') !== '') {
    clone.style.height = 'auto'
  }

  // append copy to context
  context.appendChild(clone)

  // append context to DOM so we can measure
  parentNode.appendChild(context)

  // get accurate width and height
  rect = clone.getBoundingClientRect()

  // destroy clone
  parentNode.removeChild(context)

  return rect
}

Use style from the original node, not the clone


/**
 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
 */
'use strict';

const Base = require('./Validator');

module.exports = class RangeValidator extends Base {

    constructor (config) {
        super({
            range: null,
            not: false,
            allowArray: false,
            ...config
        });
        if (!Array.isArray(this.range)) {
            throw new Error('Range property must be array');
        }
    }

    getMessage () {
        return this.createMessage(this.message, 'Invalid range');
    }

    validateValue (value) {
        if (Array.isArray(value) && !this.allowArray) {
            return this.getMessage();
        }
        let inRange = true;
        const values = Array.isArray(value) ? value : [value];
        for (const item of values) {
            if (!this.range.includes(item)) {
                inRange = false;
                break;
            }
        }
        return this.not !== inRange ? null : this.getMessage();
    }
};

/**
 * @copyright Copyright (c) 2020 Maxim Khorin <maksimovichu@gmail.com>
 */
'use strict';

const Base = require('./Validator');

module.exports = class RangeValidator extends Base {

    constructor (config) {
        super({
            // values: []
            not: false,
            allowArray: false,
            ...config
        });
        if (!Array.isArray(this.values)) {
            throw new Error('Values property must be array');
        }
    }

    getMessage () {
        return this.createMessage(this.message, 'Invalid range');
    }

    validateValue (value) {
        if (Array.isArray(value) && !this.allowArray) {
            return this.getMessage();
        }
        let inRange = true;
        const values = Array.isArray(value) ? value : [value];
        for (const item of values) {
            if (!this.values.includes(item)) {
                inRange = false;
                break;
            }
        }
        return this.not !== inRange ? null : this.getMessage();
    }
};

Replace range prop to values


const electron = require('electron')

electron.ipcRenderer.sendChannel = function () {
  const Grim = require('grim')
  Grim.deprecate('Use `ipcRenderer.send` instead of `ipcRenderer.sendChannel`')
  return this.send.apply(this, arguments)
}

const path = require('path')
const electron = require('electron')

const dirname = path.dirname
path.dirname = function (path) {
  if (typeof path !== 'string') {
    path = '' + path
    const Grim = require('grim')
    Grim.deprecate('Argument to `path.dirname` must be a string')
  }

  return dirname(path)
}

const extname = path.extname
path.extname = function (path) {
  if (typeof path !== 'string') {
    path = '' + path
    const Grim = require('grim')
    Grim.deprecate('Argument to `path.extname` must be a string')
  }

  return extname(path)
}

const basename = path.basename
path.basename = function (path, ext) {
  if (typeof path !== 'string' || (ext !== undefined && typeof ext !== 'string')) {
    path = '' + path
    const Grim = require('grim')
    Grim.deprecate('Arguments to `path.basename` must be strings')
  }

  return basename(path, ext)
}

electron.ipcRenderer.sendChannel = function () {
  const Grim = require('grim')
  Grim.deprecate('Use `ipcRenderer.send` instead of `ipcRenderer.sendChannel`')
  return this.send.apply(this, arguments)
}

Add deprecated shims for invalid args to node path functions


import React, { Component } from 'react';

class SearchBar extends Component {
	constructor(props) {
		super(props);

		this.state = { term: '' };
	}

	render() {
		return (

Youtube video search

				Search: <input
					value={this.state.term}
					onChange={event => this.setState({ term: event.target.value })} />

		);
	}
}

export default SearchBar;

import React, { Component } from 'react';

class SearchBar extends Component {
	constructor(props) {
		super(props);

		this.state = { term: '' };
	}

	render() {
		return (

Youtube video search

				Search: <input
					value={this.state.term}
					onChange={event => this.onInputChange(event.target.value)} />

		);
	}

	onInputChange(term) {
		this.setState({term});
		this.props.onSearchTermChange(term);
	}
}

export default SearchBar;

Change the onChange to call a new method onInputChange which sets the state for this component as the value, also calls the callback property onSearchTermChange passing in the value.


import path from 'path'
import get from 'lodash/get'
import merge from 'lodash/merge'

const applyStaticLoaderFix = (wpConfig, sanityConfig) => {
  // We need to fix the public path, prefixing the server URL for assets such as
  // images to work in development mode (related to blob's generated by style-loader)
  const {httpHost, httpPort, staticPath, basePath} = sanityConfig
  return get(wpConfig, 'module.loaders', []).map(loader => {
    if (typeof loader.loader !== 'string' || !loader.loader.includes('file-loader')) {
      return loader
    }

    const staticDir = path.relative(basePath, staticPath)
    const rootPath = staticDir.replace(/^\.*\/|\/+$/g, '')

    return merge({}, loader, {
      query: {
        publicPath: `http://${httpHost}:${httpPort}/${rootPath}/`
      }
    })
  })
}

export default applyStaticLoaderFix

import path from 'path'
import get from 'lodash/get'
import merge from 'lodash/merge'

const applyStaticLoaderFix = (wpConfig, sanityConfig) => {
  // We need to fix the public path, prefixing the server URL for assets such as
  // images to work in development mode (related to blob's generated by style-loader)
  const {httpHost, httpPort, staticPath, basePath} = sanityConfig

  if (!staticPath || !basePath) {
    throw new Error('`staticPath` and `basePath` must be specified in order for the static loader fix to work')
  }

  return get(wpConfig, 'module.loaders', []).map(loader => {
    if (typeof loader.loader !== 'string' || !loader.loader.includes('file-loader')) {
      return loader
    }

    const staticDir = path.relative(basePath, staticPath)
    const rootPath = staticDir.replace(/^\.*\/|\/+$/g, '')

    return merge({}, loader, {
      query: {
        publicPath: `http://${httpHost}:${httpPort}/${rootPath}/`
      }
    })
  })
}

export default applyStaticLoaderFix

Throw error if basePath or staticPath is missing


define( function() {
	return function( elem ) {

		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
		// IE throws on elements created in popups
		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
		var view = elem.ownerDocument.defaultView;

		if ( !view.opener ) {
			view = window;
		}

		return view.getComputedStyle( elem );
	};
} );

define( function() {
	return function( elem ) {

		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
		// IE throws on elements created in popups
		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
		var view = elem.ownerDocument.defaultView;

		if ( !view || !view.opener ) {
			view = window;
		}

		return view.getComputedStyle( elem );
	};
} );

Make sure elem.ownerDocument.defaultView is not null


var crawler = (function() {
    var that = {};

    that.accept = function(event) {
        update_status(event.target, '/crawling/accept/');
    };

    that.ignore = function(event) {
        update_status(event.target, '/crawling/ignore/');
    };

    function update_status(button, url_prefix) {
        var id = parseInt(button.id.split('-')[2]);
        var url = url_prefix + id + '/';
        $.post(url, {}, function() {
            var row = $('#result-' + id);
            row.remove();
        });
    }

    return that;
})();

var crawler = (function() {
    var that = {};

    that.accept = function(event) {
        update_status(event, '/crawling/accept/');
    };

    that.ignore = function(event) {
        update_status(event, '/crawling/ignore/');
    };

    function update_status(event, url_prefix) {
        function find_button(event) {
            var element;
            for (var i = 0; i < event.path.length; i += 1) {
                element = $(event.path[i]);
                if (element.prop('tagName') === 'BUTTON') {
                    return element;
                }
            }
        }

        var button = find_button(event);
        var id = parseInt(button.prop('id').split('-')[2]);
        var url = url_prefix + id + '/';
        $.post(url, {}, function() {
            var row = $('#result-' + id);
            row.remove();
        });
    }

    return that;
})();

Fix bug when clicking on icon


Application.Services.factory('ProcessList',
                             ["Restangular", "pubsub", processListService]);
function processListService(Restangular, pubsub) {
    var service = {
        processes: {}
    };

    return {
        getProcesses: function(project_id){
            if (service.processes.hasOwnProperty(project_id)){
                return service.processes[project_id];
            } else {
                this.loadProcesses(project_id);
            }
        },

        loadProcesses: function (project_id) {
            Restangular.one('processes').one('project', project_id).getList().then(function(data){
                service.processes[project_id] = data;
            });
        }
    };

}

Application.Services.factory('ProcessList',
                             ["Restangular", "$q", processListService]);
function processListService(Restangular, $q) {
    var service = {
        processes: {}
    };

    return {
        getProcesses: function(project_id){
            var deffered = $q.defer();
            var pid = project_id;
            if (service.processes.hasOwnProperty(project_id)){
                deffered.resolve(service.processes[project_id]);
            } else {
                Restangular.one('processes').one('project', project_id)
                    .getList().then(function(processes){
                        service.processes[pid] = processes;
                        deffered.resolve(service.processes[pid]);
                    });
            }
            return deffered.promise;
        }
    };
}

Return promises. Fix missing return in else statement.


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

module.exports = {
  entry: {
    ui: [
      'webpack-dev-server/client?http://localhost:3001',
      'webpack/hot/only-dev-server',
      './lib/ui/main.js'
    ]
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    publicPath: '/dist/'
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loaders: ['react-hot', 'babel']
    },{
      test: /\.json$/,
      loader: 'json'
    }]
  },
  resolve: {
    alias: {
      bacon: "baconjs"
    }
  },
  resolveLoader: { fallback: path.join(__dirname, "node_modules") },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js'),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ],
  externals: ['mdns']
}

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

module.exports = {
  entry: {
    ui: [
      'webpack-dev-server/client?http://localhost:3001',
      'webpack/hot/only-dev-server',
      './lib/ui/main.js'
    ]
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    publicPath: '/dist/'
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loaders: ['react-hot', 'babel']
    },{
      test: /\.json$/,
      loader: 'json'
    }]
  },
  resolve: {
    alias: {
      bacon: "baconjs"
    }
  },
  resolveLoader: { fallback: path.join(__dirname, "node_modules") },
  plugins: [
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ],
  externals: ['mdns']
}

Remove vendor bundle from here as well


var common = require('./webpack.common.config.js');
var assign = require('object-assign');

module.exports = assign(common, {
    debug: true,
    devtool: 'eval'
});

var common = require('./webpack.common.config.js');
var assign = require('object-assign');

module.exports = assign(common, {
    debug: true,
    devtool: 'source-map'
});

Switch back to source-map for devtool


'use strict';
var alter = require('./alter');
var batoto = require('./batoto');
var kissmanga = require('./kissmanga');
var mangafox = require('./mangafox');

/**
 * Retrieves a series.
 * @param {string} address
 * @return {Series}
 */
module.exports = function (address) {
    var series = batoto(address) || kissmanga(address) || mangafox(address);
    if (series) {
        var populate = series.children;
        series.children = function ($) {
            var children = populate($);
            alter(children);
            return children;
        };
    }
    return series;
};

'use strict';
var alter = require('./alter');
var batoto = require('./batoto');
var kissmanga = require('./kissmanga');
var mangafox = require('./mangafox');
var providers = [batoto, kissmanga, mangafox];

/**
 * Retrieves a series.
 * @param {string} address
 * @return {Series}
 */
module.exports = function (address) {
    var series;
    providers.every(function (provider) {
        series = provider(address);
        return !Boolean(series);
    });
    if (series) {
        var populate = series.children;
        series.children = function ($) {
            var children = populate($);
            alter(children);
            return children;
        };
    }
    return series;
};

/**
 * Adds a provider.
 * @param {!Provider} provider
 */
module.exports.add = function (provider) {
    providers.push(provider);
};

Enable runtime addition of third party providers.


import React from 'react'
import shallowEqual from 'shallowequal'

export const withDomain = ({
  domainClass,
  mapPropsToArg,
  mapPropsToArgsArray = props => mapPropsToArg ? [mapPropsToArg(props)] : [],
  createDomain = props => new domainClass(...mapPropsToArgsArray(props)),  // eslint-disable-line new-cap
  propName = 'domain',
  shouldRecreateDomain = (currentProps, nextProps) =>
    ! shallowEqual(mapPropsToArgsArray(currentProps), mapPropsToArgsArray(nextProps)),
}) =>
  Component =>
    class DomainProvider extends React.Component {

      domain

      componentWillMount() {
        this.domain = createDomain(this.props)
      }

      componentWillUpdate(nextProps) {
        if (shouldRecreateDomain(this.props, nextProps)) {
          this.stop()
          this.domain = createDomain(nextProps)
        }
      }

      componentWillUnmount() {
        this.stop()
      }

      stop() {
        if (this.domain && typeof this.domain.stop === 'function') {
          this.domain.stop()
        }
      }

      render() {
        return React.createElement(Component, { ...this.props, [propName]: this.domain })
      }
    }

import React from 'react'
import shallowEqual from 'shallowequal'

export const withDomain = ({
  domainClass,
  mapPropsToArg,
  mapPropsToArgsArray = props => mapPropsToArg ? [mapPropsToArg(props)] : [],
  createDomain = props => new domainClass(...mapPropsToArgsArray(props)),  // eslint-disable-line new-cap
  propName = 'domain',
  shouldRecreateDomain = (currentProps, nextProps) =>
    ! shallowEqual(mapPropsToArgsArray(currentProps), mapPropsToArgsArray(nextProps)),
}) =>
  Component =>
    class DomainProvider extends React.Component {

      domain

      componentWillMount() {
        this.domain = createDomain(this.props)
      }

      componentWillUpdate(nextProps) {
        if (shouldRecreateDomain(this.props, nextProps)) {
          this.stop()
          this.domain = createDomain(nextProps)
        }
      }

      componentWillUnmount() {
        this.stop()
        this.domain = null
      }

      stop() {
        if (this.domain && typeof this.domain.stop === 'function') {
          this.domain.stop()
        }
      }

      render() {
        return React.createElement(Component, { ...this.props, [propName]: this.domain })
      }
    }

Set domain to null for safety


import React, { Component } from 'react';
import { Container, Content, List } from 'native-base';

import JobTypeCard from './jobTypeCard';
import GlobalStyle from '../../common/globalStyle';

// Temporary constants. These will be moved and implemented in another way in the future!
const EXAMPLE_IMAGE_URL = 'https://facebook.github.io/react/img/logo_og.png';
const JOB_TYPES = ['Snöskottning', 'Lövkrattning', 'Städning', 'Ogräsrensning'];

export default class ChooseJobTypeScreen extends Component {
  static navigationOptions = {
    title: 'Choose Job Type',
  };

  navigateToNextScreen = () => (
    this.props.navigation.navigate('CreateJobScreen')
  );

  renderRow = jobType => (
    <JobTypeCard
      title={jobType} subtitle={`Behöver du hjälp med ${jobType.toLowerCase()}?`}
      cover={EXAMPLE_IMAGE_URL} icon={EXAMPLE_IMAGE_URL}
      toNextScreen={() => this.navigateToNextScreen()}
    />
  );

  render() {
    return (
      <Container>
        <Content contentContainerStyle={GlobalStyle.padder}>
          <List dataArray={JOB_TYPES} renderRow={this.renderRow} />
        </Content>
      </Container>
    );
  }
}

import React, { Component, PropTypes } from 'react';
import { Container, Content, List } from 'native-base';
import { connect } from 'react-redux';
import JobTypeCard from './jobTypeCard';
import GlobalStyle from '../../common/globalStyle';
import { imageProp } from '../../common/propTypes';

const { shape, arrayOf, string } = PropTypes;

class ChooseJobTypeScreen extends Component {
  static navigationOptions = {
    title: 'Choose Job Type',
  };

  static propTypes = {
    jobTypes: shape({
      data: arrayOf(
        shape({
          title: string.isRequired,
          description: string.isRequired,
          icon: imageProp.isRequired,
          image: imageProp.isRequired,
        }).isRequired,
      ).isRequired,
    }).isRequired,
  };

  navigateToNextScreen = () => this.props.navigation.navigate('CreateJobScreen');

  renderRow = jobType => (
    <JobTypeCard
      title={jobType.title} subtitle={jobType.description}
      cover={jobType.image} icon={jobType.icon}
      toNextScreen={() => this.navigateToNextScreen()}
    />
  );

  render() {
    return (
      <Container>
        <Content contentContainerStyle={GlobalStyle.padder}>
          <List dataArray={this.props.jobTypes.data} renderRow={this.renderRow} />
        </Content>
      </Container>
    );
  }
}

const mapStateToProps = state => ({ jobTypes: state.jobTypes });

export default connect(mapStateToProps)(ChooseJobTypeScreen);

Make ChooseJobTypeScreen use data from Redux


"use strict";

angular.module("hikeio").
	directive("headerEntry", function() {
		return {
			scope: {
				align: "@",
				label: "@",
				url: "@"
			},
			compile: function(tplElm, tplAttr) {
				// Include link only if url is included (otherwise, on some browsers it implies /)
				if (!tplAttr.url) {
					var link = tplElm.children()[0];
					tplElm.empty();
					tplElm.append(link.children);
				}
			},

			template: "" +
				"
" +
					"

" +
					"
" +
						"{{label}}" +
					"
" +
					"

" +
				"
" +
			"",
			transclude: true
		};
	});

"use strict";

angular.module("hikeio").
	directive("headerEntry", function() {
		return {
			scope: {
				align: "@",
				label: "@",
				url: "@"
			},
			compile: function(tplElm, tplAttr) {
				// Include link only if url is included (otherwise, on some browsers it implies /)
				if (!tplAttr.url) {
					var link = tplElm.children()[0];
					tplElm.empty();
					tplElm.append(link.children);
				}
			},

			template: "" +
				"
" +
					"

" +
					"
" +
						"" +
					"
" +
					"

" +
				"
" +
			"",
			transclude: true
		};
	});

Use ng-bind instead of {{}} for header entry directive.


define([
  'Class', 'uri', 'bluebird',
  'map/services/DataService'
], function(Class, UriTemplate, Promise, ds) {

  'use strict';

  var GET_REQUEST_ID = 'GeostoreService:get',
      SAVE_REQUEST_ID = 'GeostoreService:save';

  var URL = window.gfw.config.GFW_API_HOST + '/geostore/{id}';

  var GeostoreService = Class.extend({

    get: function(id) {
      return new Promise(function(resolve, reject) {

      var url = new UriTemplate(URL).fillFromObject({id: id});

      ds.define(GET_REQUEST_ID, {
        cache: {type: 'persist', duration: 1, unit: 'days'},
        url: url,
        type: 'GET'
      });

      var requestConfig = {
        resourceId: GET_REQUEST_ID,
        success: function(response) {
          resolve(response.data);
        },
      };

      ds.request(requestConfig);

      });
    },

    save: function(geojson) {
      return new Promise(function(resolve, reject) {

      var url = new UriTemplate(URL).fillFromObject({});

      ds.define(SAVE_REQUEST_ID, {
        url: url,
        type: 'POST',
        contentType: 'application/json'
      });

      var requestConfig = {
        resourceId: SAVE_REQUEST_ID,
        data: JSON.stringify(geojson),
        success: function(response) {
          resolve(response.data.id);
        },
        error: reject
      };

      ds.request(requestConfig);

      });
    }

  });

  return new GeostoreService();

});

define([
  'Class', 'uri', 'bluebird',
  'map/services/DataService'
], function(Class, UriTemplate, Promise, ds) {

  'use strict';

  var GET_REQUEST_ID = 'GeostoreService:get',
      SAVE_REQUEST_ID = 'GeostoreService:save';

  var URL = window.gfw.config.GFW_API_HOST + '/api/geostore/{id}';

  var GeostoreService = Class.extend({

    get: function(id) {
      return new Promise(function(resolve, reject) {

      var url = new UriTemplate(URL).fillFromObject({id: id});

      ds.define(GET_REQUEST_ID, {
        cache: {type: 'persist', duration: 1, unit: 'days'},
        url: url,
        type: 'GET'
      });

      var requestConfig = {
        resourceId: GET_REQUEST_ID,
        success: function(response) {
          resolve(response.data);
        },
      };

      ds.request(requestConfig);

      });
    },

    save: function(geojson) {
      return new Promise(function(resolve, reject) {

      var url = new UriTemplate(URL).fillFromObject({});

      ds.define(SAVE_REQUEST_ID, {
        url: url,
        type: 'POST',
        contentType: 'application/json'
      });

      var requestConfig = {
        resourceId: SAVE_REQUEST_ID,
        data: JSON.stringify(geojson),
        success: function(response) {
          resolve(response.data.id);
        },
        error: reject
      };

      ds.request(requestConfig);

      });
    }

  });

  return new GeostoreService();

});

Use config for API url


import React from 'react'
import { connect } from 'react-redux'
import _ from 'lodash'
import injectSheet from 'react-jss'

import ResourceCard from './resource-card'

const mapStateToProps = state => {
	return {
		pregnancyResourceCenters: state.miniApp.pregnancyResourceCenters,
	}
}

const ResourceListView = ({ classes, pregnancyResourceCenters }) => {
	return (

				Your search results have been arranged by closest distance to your
				location data.

				{_.map(pregnancyResourceCenters, prc => {
					return <ResourceCard key={prc._id} resource={prc} />
				})}

	)
}

const styles = {
	header: {
		padding: '30px 0px 30px 0px',
		'background-color': '#3d65f9',
		'font-size': '14px',
		color: '#99cccc',
		'text-align': 'center',
	},
}

const ResourceList = connect(mapStateToProps)(ResourceListView)

export default injectSheet(styles)(ResourceList)

import React from 'react'
import { connect } from 'react-redux'
import _ from 'lodash'
import injectSheet from 'react-jss'

import ResourceCard from './resource-card'
import LogoAndNavigation from '../logo-and-navigation'

const mapStateToProps = state => {
	return {
		pregnancyResourceCenters: state.miniApp.pregnancyResourceCenters,
	}
}

const ResourceListView = ({ classes, pregnancyResourceCenters }) => {
	return (

			<LogoAndNavigation />

				Your search results have been arranged by closest distance to your
				location data.

				{_.map(pregnancyResourceCenters, prc => {
					return <ResourceCard key={prc._id} resource={prc} />
				})}

	)
}

const styles = {
	header: {
		padding: '30px 0px 30px 0px',
		'background-color': '#3d65f9',
		'font-size': '14px',
		color: '#99cccc',
		'text-align': 'center',
	},
}

const ResourceList = connect(mapStateToProps)(ResourceListView)

export default injectSheet(styles)(ResourceList)

Add logo and navigation to results page


/**
 * This static UI function fills the given HTML <select> element with HTML
 * <option> elements that represent each found device.
 * A device type to filter is optional, the default is the video input type.
 */
VideoStream.UI.deviceSelector = function(selectElement, deviceType = VideoStream.DeviceType.VIDEO_INPUT){
	VideoStream.listDevices(deviceType)
	.then(function(devices){

		var genericText;
		switch(deviceType){
		case VideoStream.DeviceType.VIDEO_INPUT :
			genericText = VideoStream.UI.language['generic-camera'];
			break;
		case VideoStream.DeviceType.AUDIO_INPUT :
			genericText = VideoStream.UI.language['generic-audio-input'];
			break;
		default:
			genericText = VideoStream.UI.language['generic-input'];
		}

		for(var i = 0, genericIndex = 1; i < devices.length; i++){
			var label = devices[i].label === '' ? genericText + ' #' + (genericIndex++) : devices[i].label;

			var option = document.createElement('OPTION');
			option.setAttribute('value', i);
			var text = document.createTextNode(label);
			option.appendChild(text);
			selectElement.appendChild(option);
		}
	});
}

VideoStream.UI.language['generic-input'] = 'Generic Input';
VideoStream.UI.language['generic-camera'] = 'Generic Camera';
VideoStream.UI.language['generic-audio-input'] = 'Generic Audio Input';

/**
 * This static UI function fills the given HTML <select> element with HTML
 * <option> elements that represent each found device.
 * A device type to filter is optional, the default is the video input type.
 */
VideoStream.UI.deviceSelector = function(selectElement, deviceType = VideoStream.DeviceType.VIDEO_INPUT){
	VideoStream.listDevices(deviceType)
	.then(function(devices){

		var genericText;
		switch(deviceType){
		case VideoStream.DeviceType.VIDEO_INPUT :
			genericText = VideoStream.UI.language['generic-camera'];
			break;
		case VideoStream.DeviceType.AUDIO_INPUT :
			genericText = VideoStream.UI.language['generic-audio-input'];
			break;
		default:
			genericText = VideoStream.UI.language['generic-input'];
		}

		for(var i = 0, genericIndex = 1; i < devices.length; i++){
			var label = devices[i].label === '' ? genericText + ' #' + (genericIndex++) : devices[i].label;

			var option = document.createElement('OPTION');
			option.setAttribute('value', devices[i].deviceId);
			var text = document.createTextNode(label);
			option.appendChild(text);
			selectElement.appendChild(option);
		}
	});
}

VideoStream.UI.language['generic-input'] = 'Generic Input';
VideoStream.UI.language['generic-camera'] = 'Generic Camera';
VideoStream.UI.language['generic-audio-input'] = 'Generic Audio Input';

Write correct device id into value


import Ember from 'ember';
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

const { Object, RSVP } = Ember;
const { resolve } = RSVP;

moduleForComponent('school-vocabulary-manager', 'Integration | Component | school vocabulary manager', {
  integration: true
});

test('it renders', function(assert) {
  let vocabulary = Object.create({
    title: 'fake vocab',
    topLevelTerms: resolve([])
  });

  this.set('vocabulary', vocabulary);
  this.on('nothing', parseInt);
  this.render(hbs`{{school-vocabulary-manager
    vocabulary=vocabulary
    manageTerm=(action 'nothing')
    manageVocabulary=(action 'nothing')
  }}`);

  const all = '.breadcrumbs span:eq(0)';
  const vocab = '.breadcrumbs span:eq(1)';

  assert.equal(this.$(all).text().trim(), 'All Vocabularies');
  assert.equal(this.$(vocab).text().trim(), vocabulary.title);
});

import Ember from 'ember';
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

const { Object, RSVP } = Ember;
const { resolve } = RSVP;

moduleForComponent('school-vocabulary-manager', 'Integration | Component | school vocabulary manager', {
  integration: true
});

test('it renders', function(assert) {
  let vocabulary = Object.create({
    title: 'fake vocab',
    terms: resolve([])
  });

  this.set('vocabulary', vocabulary);
  this.on('nothing', parseInt);
  this.render(hbs`{{school-vocabulary-manager
    vocabulary=vocabulary
    manageTerm=(action 'nothing')
    manageVocabulary=(action 'nothing')
  }}`);

  const all = '.breadcrumbs span:eq(0)';
  const vocab = '.breadcrumbs span:eq(1)';

  assert.equal(this.$(all).text().trim(), 'All Vocabularies');
  assert.equal(this.$(vocab).text().trim(), vocabulary.title);
});

Fix school vocal term manager test


import commitExcessActions from './commitExcessActions';

export function recompute(previousLiftedState, storeState, action, nextActionId = 1, isExcess) {
  const actionId = nextActionId - 1;
  const liftedState = { ...previousLiftedState };
  liftedState.stagedActionIds = [...liftedState.stagedActionIds, actionId];
  liftedState.actionsById = { ...liftedState.actionsById };
  if (action.type === 'PERFORM_ACTION') {
    liftedState.actionsById[actionId] = action;
  } else {
    liftedState.actionsById[actionId] = {
      action: action.action || action,
      timestamp: action.timestamp || Date.now(),
      type: 'PERFORM_ACTION'
    };
  }
  liftedState.nextActionId = nextActionId;
  liftedState.computedStates = [...liftedState.computedStates, { state: storeState }];
  liftedState.currentStateIndex++;

  if (isExcess) commitExcessActions(liftedState);

  return liftedState;
}

import commitExcessActions from './commitExcessActions';

export function recompute(previousLiftedState, storeState, action, nextActionId = 1, isExcess) {
  const actionId = nextActionId - 1;
  const liftedState = { ...previousLiftedState };

  if (liftedState.currentStateIndex === liftedState.stagedActionIds.length - 1) {
    liftedState.currentStateIndex++;
  }
  liftedState.stagedActionIds = [...liftedState.stagedActionIds, actionId];
  liftedState.actionsById = { ...liftedState.actionsById };
  if (action.type === 'PERFORM_ACTION') {
    liftedState.actionsById[actionId] = action;
  } else {
    liftedState.actionsById[actionId] = {
      action: action.action || action,
      timestamp: action.timestamp || Date.now(),
      type: 'PERFORM_ACTION'
    };
  }
  liftedState.nextActionId = nextActionId;
  liftedState.computedStates = [...liftedState.computedStates, { state: storeState }];

  if (isExcess) commitExcessActions(liftedState);

  return liftedState;
}

Fix `currentStateIndex` while time travelling


function PlayState(playerPos) {
    "use strict";

    var self = this;
    var charSprite = new Sprite("img/char_S0.png", function() {
        var charColl = new CollisionBody(charSprite.size);
        self.char = new Entity(playerPos, charColl, charSprite);
    });
}

// Subclass the GameState class.
PlayState.prototype = GameState.prototype;

PlayState.prototype.update = function (deltaTime) {
    "use strict";
}

PlayState.prototype.render = function (screen) {
    "use strict";

    this.char.render(screen);

    screen.renderText("Hello World!", new Vector2(5, 20));
    screen.renderText("This is OpenJGL Speaking.", new Vector2(5, 40), "#55F", "oblique small-caps bold 16px IndieFlower Lobster Serif");
}

PlayState.prototype.willAppear = function () {
    "use strict";

    Log.info("A Play State will soon appear.", this);
}

PlayState.prototype.willDisappear = function () {
    "use strict";

    Log.info("A Play State will soon disappear.", this);
}

PlayState.prototype.toString = function () {
    "use strict";
    return "PlayState";
}

function PlayState(playerPos) {
    "use strict";

    var self = this;
    var charSprite = new Sprite("img/char_S0.png", function() {
        var charColl = new CollisionBody(charSprite.size);
        self.char = new Entity(playerPos, charColl, charSprite);
    });
}

// Subclass the GameState class.
PlayState.prototype = GameState.prototype;

PlayState.prototype.update = function (deltaTime) {
    "use strict";
}

PlayState.prototype.render = function (screen) {
    "use strict";

    this.char.render(screen);

    screen.renderText("Hello World!", new Vector2(5, 20));
    screen.renderText("This is OpenJGL Speaking.", new Vector2(5, 40), 16, "#55F", "oblique small-caps bold IndieFlower Lobster Serif");
}

PlayState.prototype.willAppear = function () {
    "use strict";

    Log.info("A Play State will soon appear.", this);
}

PlayState.prototype.willDisappear = function () {
    "use strict";

    Log.info("A Play State will soon disappear.", this);
}

PlayState.prototype.toString = function () {
    "use strict";
    return "PlayState";
}

Update rendering for new renderText method


import Validator from 'validatorjs';

export default {
    props: {
        valid: {
            type: Boolean,
            default: true,
            twoWay: true
        },
        dirty: {
            type: Boolean,
            default: false,
            twoWay: true
        },
        hideValidationErrors: {
            type: Boolean,
            default: false
        },
        validationRules: String,
        validationMessages: Object
    },

    data() {
        return {
            validationError: ''
        };
    },

    events: {
        'ui-input::set-validity': function(valid, error, id) {
            // Abort if event isn't meant for this component
            if (!this.eventTargetsComponent(id)) {
                return;
            }

            this.setValidity(valid, error);
        }
    },

    methods: {
        validate() {
            if (!this.validationRules || !this.dirty) {
                return;
            }

            let data = {
                value: this.value
            };

            let rules = {
                value: this.validationRules
            };

            let validation = new Validator(data, rules, this.validationMessages);

            validation.setAttributeNames({ value: this.name.replace(/_/g, ' ') });

            this.setValidity(validation.passes(), validation.errors.first('value'));
        },

        setValidity(valid, error) {
            this.valid = valid;

            if (!valid && error && error.length) {
                this.validationError = error;
            }
        }
    }
};

import Validator from 'validatorjs';

export default {
    props: {
        valid: {
            type: Boolean,
            default: true,
            twoWay: true
        },
        dirty: {
            type: Boolean,
            default: false,
            twoWay: true
        },
        hideValidationErrors: {
            type: Boolean,
            default: false
        },
        validationRules: [String, Array],
        validationMessages: Object
    },

    data() {
        return {
            validationError: ''
        };
    },

    events: {
        'ui-input::set-validity': function(valid, error, id) {
            // Abort if event isn't meant for this component
            if (!this.eventTargetsComponent(id)) {
                return;
            }

            this.setValidity(valid, error);
        }
    },

    methods: {
        validate() {
            if (!this.validationRules || !this.dirty) {
                return;
            }

            let data = {
                value: this.value
            };

            let rules = {
                value: this.validationRules
            };

            let validation = new Validator(data, rules, this.validationMessages);

            validation.setAttributeNames({ value: this.name.replace(/_/g, ' ') });

            this.setValidity(validation.passes(), validation.errors.first('value'));
        },

        setValidity(valid, error) {
            this.valid = valid;

            if (!valid && error && error.length) {
                this.validationError = error;
            }
        }
    }
};

Update validation-rules prop to accept Array in addition to String


//from: https://github.com/auth0/jwt-decode/blob/master/lib/index.js
import { base64UrlDecode } from './-base64-url-decode';

export function jwt_decode(token) {
  if (typeof token !== 'string') {
    throw new Error('Invalid token specified');
  }

  return JSON.parse(base64UrlDecode(token.split('.')[1]));
}

//from: https://github.com/auth0/jwt-decode/blob/master/lib/index.js
import { base64UrlDecode } from './-base64-url-decode';

export function jwt_decode(token) {
  if (typeof token !== 'string') {
    throw new Error('Invalid token specified');
  }

  var tokenParts = token.split('.');
  if (tokenParts.length !== 3) {
    throw new Error('Invalid token specified');
  }

  return JSON.parse(base64UrlDecode(tokenParts[1]));
}

Validate token parts before decoding.


angular.module("app").controller("DiagnosticsDialogController",
				 function($scope, $mdDialog, roslib) {

  var OK = 0;
  var WARN = 1;
  var ERROR = 2;
  var STALE = 3;

  var diagnostics_callback = function(diagnostics) {
      $scope.diagnostics = diagnostics;
      console.log(diagnostics);
  };
  var diagnostics_sub = roslib.subscribe("/diagnostics_agg", "diagnostic_msgs/DiagnosticArray", diagnostics_callback);
  $scope.hide = function() {
    $mdDialog.hide();
  };
  $scope.cancel = function() {
    $mdDialog.cancel();
  };
  $scope.answer = function(answer) {
    $mdDialog.hide(answer);
  };
  $scope.statusLevelToColor = function(level) {
      if(level === OK) {
	  return "green";
      }
      else if(level === WARN) {
	  return "yellow";
      }
      else if(level === STALE) {
	  return "blue";
      }
      else {
	  return "red";
      }
  };
  $scope.statusLevelToSymbol = function(level) {
      if(level === OK) {
	  return "\u2714";
      }
      else if(level === WARN) {
	  return "\u2757";
      }
      else if(level === STALE) {
	  return "\u2753";
      }
      else {
	  return "\u2716";
      }
  };
});

angular.module("app").controller("DiagnosticsDialogController",
				 function($scope, $mdDialog, roslib) {

  var OK = 0;
  var WARN = 1;
  var ERROR = 2;
  var STALE = 3;

  var diagnostics_callback = function(diagnostics) {
      $scope.diagnostics = diagnostics;
      console.log(diagnostics);
  };
  var diagnostics_sub = roslib.subscribe("/diagnostics_agg", "diagnostic_msgs/DiagnosticArray", diagnostics_callback);
  $scope.hide = function() {
    $mdDialog.hide();
  };
  $scope.cancel = function() {
    $mdDialog.cancel();
  };
  $scope.answer = function(answer) {
    $mdDialog.hide(answer);
  };
  $scope.statusLevelToColor = function(level) {
      if(level === OK) {
	  return "green";
      }
      else if(level === WARN) {
	  return "orange";
      }
      else if(level === STALE) {
	  return "blue";
      }
      else {
	  return "red";
      }
  };
  $scope.statusLevelToSymbol = function(level) {
      if(level === OK) {
	  return "\u2714";
      }
      else if(level === WARN) {
	  return "\u2757";
      }
      else if(level === STALE) {
	  return "\u2753";
      }
      else {
	  return "\u2716";
      }
  };
});

Make diagnostics warning color more visible


var capitalize = require('../capitalize');

var chai = require('chai');
var expect = chai.expect;

describe('capitalize', function() {
	it('capitalizes single words', function() {
		expect(capitalize('express')).to.equal('Express');
		expect(capitalize('cats')).to.equal('Cats');
	});

	it('makes the rest of the string lowercase', function() {
		expect(capitalize('javaScript')).to.equal('Javascript');
	});

	it('leaves empty strings alone', function() {
		expect(capitalize('')).to.equal('');
	});

	it('leaves strings with no words alone', function() {
		expect(capitalize(' ')).to.equal(' ');
		expect(capitalize('123')).to.equal('123');
	});

	it('capitalizes multiple-word strings', function() {
		expect(capitalize('what is Express')).to.equal('What is express');
		expect(capitalize('i love lamp')).to.equal('I love lamp');
	});

	it('leaves already-capitalized words alone', function() {
		expect(capitalize('Express')).to.equal('Express');
		expect(capitalize('Evan')).to.equal('Evan');
		expect(capitalize('Catman')).to.equal('Catman');
	});
});

var capitalize = require('../capitalize');

var chai = require('chai');
var expect = chai.expect;

describe('capitalize', function() {
	it('capitalizes single words', function() {
		expect(capitalize('express')).to.equal('Express');
		expect(capitalize('cats')).to.equal('Cats');
	});

	it('makes the rest of the string lowercase', function() {
		expect(capitalize('javaScript')).to.equal('Javascript');
	});

	it('leaves empty strings alone', function() {
		expect(capitalize('')).to.equal('');
	});

	it('leaves strings with no words alone', function() {
		expect(capitalize(' ')).to.equal(' ');
		expect(capitalize('123')).to.equal('123');
	});

	it('capitalizes multiple-word strings', function() {
		expect(capitalize('what is Express')).to.equal('What is express');
		expect(capitalize('i love lamp')).to.equal('I love lamp');
	});

	it('leaves already-capitalized words alone', function() {
		expect(capitalize('Express')).to.equal('Express');
		expect(capitalize('Evan')).to.equal('Evan');
		expect(capitalize('Catman')).to.equal('Catman');
	});

	it('capitalizes String objects without changing their values', function() {
		var str = new String('who is JavaScript?');
		expect(capitalize(str)).to.equal('Who is javascript?');
		expect(str.valueOf()).to.equal('who is JavaScript?');
	});
});

Test for String Object and value mutation of the same


Add minimized version of updated script.


import React from 'react';
import styles from '../../css/app.css';
export default class Application extends React.Component {
	constructor( props, context ) {
		super( props, context );
	}
	render() {
		return (

Past ebin header placeholder

					{this.props.children}

 Footer placeholder

		);
	}
}

import React from 'react';
import styles from '../../css/app.css';
import {
	Link
}
from 'react-router';
export default class Application extends React.Component {
	constructor( props, context ) {
		super( props, context );
	}
	render() {
		return (

					<Link to="/">Past ebin</Link>

					{this.props.children}

 Footer placeholder

		);
	}
}

Add link back to home page to pastes, change h1 to just 'Past ebin'


import _ from 'lodash'
import axios from 'axios'
import moment from 'moment'
import Vue from 'vue'
import {assert, expect} from 'chai'
import moxios from 'moxios'

// Emulate browser globals
global._ = _;
global.axios = axios;
global.moment = moment;
global.Vue = Vue;

// Fail if there's an unhandled promise rejection warning.
process.on('unhandledRejection', (error, promise) => {
    console.error('Unhandled promise rejection', {error, promise})
    process.exit(1);
});

//
require('./Structures/Model.spec.js');
require('./Structures/Collection.spec.js')

//
require('./Validation/rule.spec.js')
require('./Validation/rules.spec.js')
require('./Validation/messages.spec.js')

//
require('./HTTP/ProxyResponse.spec.js')

//
require('./Errors/RequestError.spec.js')
require('./Errors/ResponseError.spec.js')
require('./Errors/ValidationError.spec.js')

import _ from 'lodash'
import axios from 'axios'
import moment from 'moment'
import Vue from 'vue'
import {assert, expect} from 'chai'
import moxios from 'moxios'

// Emulate browser globals
global._ = _;
global.axios = axios;
global.moment = moment;
global.Vue = Vue;

// Fail if there's an unhandled promise rejection warning.
process.on('unhandledRejection', (error, promise) => {
    console.error('Unhandled promise rejection', {error, promise})
    process.exit(1);
});

// Structures
require('./Structures/Model.spec.js');
require('./Structures/Collection.spec.js')

// Validation
require('./Validation/Rule.spec.js')
require('./Validation/Rules.spec.js')
require('./Validation/Messages.spec.js')

// HTTP
require('./HTTP/ProxyResponse.spec.js')

// Errors
require('./Errors/RequestError.spec.js')
require('./Errors/ResponseError.spec.js')
require('./Errors/ValidationError.spec.js')

Fix another path case inconsistency


var text = "hello,this is a bad sentence.";

var punctuation = ",.!;";

for (var i = 0; i < text.length; i++) {
  if (punctuation.indexOf(text[i]) > -1) {
    if ((text[i+1] != " ") && (i != text.length-1)) {
      console.log("Pedant: punctuation error at index " + (i+1) + ": " + text);
    }
  }
}

var text = "'The quick brown,fox jumped over the lazy dog, he said, as he noticed that he forgot to close the quote.";
var MAX_QUOTE_LENGTH = 20;

var punctuation = ",.!;";
var quotes = "\"\'";
for (var i = 0; i < text.length; i++) {

    // check for punctuation
    if (punctuation.indexOf(text[i]) > -1) {
        if ((text[i + 1] != " ") && (i != text.length - 1)) {
            console.log("punctuation error at index " + i + ":");
            var error = showPrettyError(text, i);
            console.log(error[0]);
            console.log(error[1]);
            console.log("====================");
        }
    }

    // check for missing quotes
    if (quotes.indexOf(text[i]) > -1) {
        var k = 0;
        for (j = 1; j < text.length; j++) {
            if (quotes.indexOf(text[j]) == -1) {
                k++;
            }
        }

        if (k > MAX_QUOTE_LENGTH) {
            console.log("max quote length of " + MAX_QUOTE_LENGTH + " exceeded at index " + j + " (quote started at index " + i + ") :");
            var error = showPrettyError(text, j);
            console.log(error[0]);
            console.log(error[1]);
            console.log("====================");
        }

    }
}

function showPrettyError(text, index) {
    var contextAmount = 8;
    var showContextSegment = "...";
    return [
        showContextSegment + text.substr(index - contextAmount, index + contextAmount) + showContextSegment,
        pad(Math.max(index + 1 - contextAmount, index + 1), "^", " ").substr(index - contextAmount - showContextSegment.length)
    ];

    //http://stackoverflow.com/a/15660515
    function pad(width, string, padding) {
        return (width <= string.length) ? string : pad(width, padding + string, padding);
    }

}

Check for missing closing quotes; print errors


var isFunction = require('lodash/lang/isFunction');
var dispatcher = require('focus').dispatcher;
module.exports = {
    /**
     * Register the cartridge.
     */
    _registerCartridge: function registerCartridge(){
      this.cartridgeConfiguration = this.cartridgeConfiguration || this.props.cartridgeConfiguration;
      if(!isFunction(this.cartridgeConfiguration)){
        this.cartridgeConfiguration = function cartridgeConfiguration(){
          return {};
        };
        console.warn(`
          Your detail page does not have any cartrige configuration, this is not mandarory but recommended.
          It should be a component attribute return by a function.
          function cartridgeConfiguration(){
            var cartridgeConfiguration = {
              summary: {component: "A React Component", props: {id: this.props.id}},
              cartridge: {component: "A React Component"},
              actions: {components: "react actions"}
            };
            return cartridgeConfiguration;
          }
        `);
      }
      var cartridgeConf = this.cartridgeConfiguration();
      dispatcher.handleViewAction({
        data: {
          cartridgeComponent: cartridgeConf.cartridge,
          summaryComponent: cartridgeConf.summary,
          actions: cartridgeConf.actions
        },
        type: 'update'
      });
    },
    componentWillMount: function pageMixinWillMount(){
      this._registerCartridge();
    }
};

var isFunction = require('lodash/lang/isFunction');
var dispatcher = require('focus').dispatcher;
var Empty = require('../../common/empty').component;
module.exports = {
    /**
     * Register the cartridge.
     */
    _registerCartridge: function registerCartridge(){
      this.cartridgeConfiguration = this.cartridgeConfiguration || this.props.cartridgeConfiguration;
      if(!isFunction(this.cartridgeConfiguration)){
        this.cartridgeConfiguration = function cartridgeConfiguration(){
          return {};
        };
        console.warn(`
          Your detail page does not have any cartrige configuration, this is not mandarory but recommended.
          It should be a component attribute return by a function.
          function cartridgeConfiguration(){
            var cartridgeConfiguration = {
              summary: {component: "A React Component", props: {id: this.props.id}},
              cartridge: {component: "A React Component"},
              actions: {components: "react actions"}
            };
            return cartridgeConfiguration;
          }
        `);
      }
      var cartridgeConf = this.cartridgeConfiguration();
      dispatcher.handleViewAction({
        data: {
          cartridgeComponent: cartridgeConf.cartridge || {component: Empty},
          summaryComponent: cartridgeConf.summary|| {component: Empty},
          actions: cartridgeConf.actions|| {primary: [], secondary: Empty},
          barContentLeftComponent: cartridgeConf.barLeft || {component: Empty}
        },
        type: 'update'
      });
    },
    componentWillMount: function pageMixinWillMount(){
      this._registerCartridge();
    }
};

Add the cartrige left compoennt in the mixin.


import assert from "assert";
import { introspectStarwars } from './introspectStarwars';
import { initTemplateStringTransformer } from '../src/index';
import fs from 'fs';
import path from 'path';

// Uncomment the below to generate a new schema JSON
// describe("graphql", () => {
//   it("can introspect star wars", async () => {
//     const result = await introspectStarwars();
//
//     fs.writeFileSync(path.join(__dirname, "starwars.json"),
//       JSON.stringify(result, null, 2));
//
//     assert.ok(result.data);
//     assert.ok(result.data.__schema);
//   });
// });

describe("runtime query transformer", () => {
  it("can be initialized with an introspected query", async () => {
    const result = await introspectStarwars();
    const transformer = initTemplateStringTransformer(result.data);
  });

  it("can compile a Relay.QL query", () => {
    Relay.QL`
      query HeroNameQuery {
        hero {
          name
        }
      }
    `;
  });

  it("can transform a simple query", async () => {
    const result = await introspectStarwars();
    const transformer = initTemplateStringTransformer(result.data);
    const transformed = transformer(`
      query HeroNameQuery {
        hero {
          name
        }
      }
    `);

    const expected = Relay.QL`
      query HeroNameQuery {
        hero {
          name
        }
      }
    `;

    assert.deepEqual(transformed, expected);
  });
});

import assert from "assert";
import { introspectStarwars } from './introspectStarwars';
import { initTemplateStringTransformer } from '../src/index';
import fs from 'fs';
import path from 'path';

// Uncomment the below to generate a new schema JSON
// describe("graphql", () => {
//   it("can introspect star wars", async () => {
//     const result = await introspectStarwars();
//
//     fs.writeFileSync(path.join(__dirname, "starwars.json"),
//       JSON.stringify(result, null, 2));
//
//     assert.ok(result.data);
//     assert.ok(result.data.__schema);
//   });
// });

describe("runtime query transformer", () => {
  it("can be initialized with an introspected query", async () => {
    const result = await introspectStarwars();
    const transformer = initTemplateStringTransformer(result.data);
  });

  it("can compile a Relay.QL query", () => {
    Relay.QL`
      query HeroNameQuery {
        hero {
          name
        }
      }
    `;
  });

  it("can transform a simple query", async () => {
    const result = await introspectStarwars();
    const transformer = initTemplateStringTransformer(result.data);
    const transformed = transformer(`
      query HeroNameAndFriendsQuery {
        hero {
          id
          name
          friends {
            name
          }
        }
      }
    `);

    const expected = Relay.QL`
      query HeroNameAndFriendsQuery {
        hero {
          id
          name
          friends {
            name
          }
        }
      }
    `;

    assert.deepEqual(transformed, expected);
  });
});

Make query slightly more complex


/* ************************************************************************

   coretest

   Copyright:
     2010 Deutsche Telekom AG, Germany, http://telekom.com

 ************************************************************************ */

/* ************************************************************************

#asset(coretest/*)

************************************************************************ */

core.Env.define("application", "coretest.Application");

/**
 * Unify application class
 */
core.Class("coretest.Application",
{
  include : [unify.Application],

  members :
  {
    // overridden
    main : function()
    {
      // Call super class
      unify.Application.prototype.main.call(this);

      // Configure application
      document.title = "coretest";

      // Create view managers
      var MasterViewManager = new unify.view.ViewManager("master");

      // Register your view classes...
      MasterViewManager.register(coretest.view.Start, true);
      MasterViewManager.register(coretest.view.Test);
      MasterViewManager.register(coretest.view.OtherTest);

      // Add TabViews or SplitViews...
      var TabView = new unify.view.TabViewManager(MasterViewManager);
      TabView.register(coretest.view.Start);
      TabView.register(coretest.view.Test);

      // Add view manager (or SplitView or TabView) to the root
      this.add(TabView);
      //this.add(MasterViewManager);

      // Add at least one view manager to the navigation managment
      var Navigation = unify.view.Navigation.getInstance();
      Navigation.register(MasterViewManager);
      Navigation.init();
    },

    _getTheme : function() {
      return new unify.theme.Dark();
    }
  }
});

/* ************************************************************************

   coretest

   Copyright:
     2010 Deutsche Telekom AG, Germany, http://telekom.com

 ************************************************************************ */

/* ************************************************************************

#asset(coretest/*)

************************************************************************ */

/**
 * Unify application class
 */
core.Class("coretest.Application",
{
  include : [unify.Application],

  members :
  {
    // overridden
    main : function()
    {
      // Call super class
      unify.Application.prototype.main.call(this);

      // Configure application
      document.title = "coretest";

      // Create view managers
      var MasterViewManager = new unify.view.ViewManager("master");

      // Register your view classes...
      MasterViewManager.register(coretest.view.Start, true);
      MasterViewManager.register(coretest.view.Test);
      MasterViewManager.register(coretest.view.OtherTest);

      // Add TabViews or SplitViews...
      var TabView = new unify.view.TabViewManager(MasterViewManager);
      TabView.register(coretest.view.Start);
      TabView.register(coretest.view.Test);

      // Add view manager (or SplitView or TabView) to the root
      this.add(TabView);
      //this.add(MasterViewManager);

      // Add at least one view manager to the navigation managment
      var Navigation = unify.view.Navigation.getInstance();
      Navigation.register(MasterViewManager);
      Navigation.init();
    },

    _getTheme : function() {
      return new unify.theme.Dark();
    }
  }
});

Remove manual setting of application environment


import { get, set } from '@ember/object';
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed, observer } from '@ember/object';
import { htmlSafe } from '@ember/string';
import C from 'ui/utils/constants';
import { on } from '@ember/object/evented';

export default Component.extend({
  intl:                service(),

  comparisonObserver: on('init', observer('model.metricRule.comparison', function() {
    if (get(this, 'model.metricRule.comparison') === get(this, 'hasValue')) {
      set(this, 'model.metricRule.thresholdValue', null)
    } else {
      set(this, 'model.metricRule.thresholdValue', 0)
    }
  })),

  verbStyles: computed('model._targetType', function() {
    const targetType = get(this, 'model._targetType');
    const arr = ['pod', 'workload', 'workloadSelector', 'node', 'nodeSelector']

    let out = '';

    if (arr.includes(targetType)) {
      out = `padding-top: 6px;`;
    }

    return htmlSafe(out);
  }),

  operatorContent: computed(function() {
    return Object.values(C.ALERTING_COMPARISON).map((value) => {
      return {
        label: get(this, 'intl').t(`alertPage.comparison.${ value }`),
        value,
      }
    })
  }),

  hasValue:            C.ALERTING_COMPARISON.HAS_VALUE,
  durationContent:     C.ALERT_DURATION,

});

import { get, set } from '@ember/object';
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed, observer } from '@ember/object';
import { htmlSafe } from '@ember/string';
import C from 'ui/utils/constants';
import { on } from '@ember/object/evented';

export default Component.extend({
  intl:                service(),

  comparisonObserver: on('init', observer('model.metricRule.comparison', function() {
    if (get(this, 'model.metricRule.comparison') === get(this, 'hasValue')) {
      set(this, 'model.metricRule.thresholdValue', null)
    }
  })),

  verbStyles: computed('model._targetType', function() {
    const targetType = get(this, 'model._targetType');
    const arr = ['pod', 'workload', 'workloadSelector', 'node', 'nodeSelector']

    let out = '';

    if (arr.includes(targetType)) {
      out = `padding-top: 6px;`;
    }

    return htmlSafe(out);
  }),

  operatorContent: computed(function() {
    return Object.values(C.ALERTING_COMPARISON).map((value) => {
      return {
        label: get(this, 'intl').t(`alertPage.comparison.${ value }`),
        value,
      }
    })
  }),

  hasValue:            C.ALERTING_COMPARISON.HAS_VALUE,
  durationContent:     C.ALERT_DURATION,

});

Fix threshold is reset when edit alert rule


'use strict';

var expect = require('chai').expect,
    fs     = require('fs'),
    uncss  = require('../lib/uncss');

describe('Using globbing patterns', function () {

    it('should find both index pages in the directory and return the used CSS for both of them', function (done) {
        this.timeout(25000);

        uncss(['tests/glob/**/*.html'], function (err, output) {
            expect(err).to.be.null;
            expect(output).to.exist;
            expect(output).to.contain('h1');
            expect(output).to.contain('h2');
            expect(output).not.to.contain('h3');
            expect(output).not.to.contain('h4');
            expect(output).not.to.contain('h5');
            expect(output).not.to.contain('h6');
            done();
        });
    });
});

'use strict';

var expect = require('chai').expect,
    uncss  = require('../lib/uncss');

describe('Using globbing patterns', function () {

    it('should find both index pages in the directory and return the used CSS for both of them', function (done) {
        this.timeout(25000);

        uncss(['tests/glob/**/*.html'], function (err, output) {
            expect(err).to.be.null;
            expect(output).to.exist;
            expect(output).to.contain('h1');
            expect(output).to.contain('h2');
            expect(output).not.to.contain('h3');
            expect(output).not.to.contain('h4');
            expect(output).not.to.contain('h5');
            expect(output).not.to.contain('h6');
            done();
        });
    });
});

Remove fs from test dependencies.


var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
//var models = require("./models");

var PORT = process.env.PORT || 3000;

//models.sequelize.sync().then(function () {

  io.on('connection', function(client) {
    console.log('Someone connected!');

    client.on('join', function(data) {
      if(data === 'This is your teacher speaking') {
        client.emit('greeting', 'Hiya, Teach!');
      } else{
        client.emit('greeting', 'Hello, student. Please wait for your instructor to open a new poll.');
      }
    });

    client.on('newPoll', function(data) {
      io.sockets.emit('openPoll', data);
    });

    client.on('disconnect', function(client) {
      console.log('Bye!\n');
    });
  });

  require('./config/routes.js')(app, express, io);

  server.listen(PORT, function (){
    console.log('listening on port', PORT);
  });

// };

var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
//var models = require("./models");

var PORT = process.env.PORT || 3000;

//models.sequelize.sync().then(function () {
  require('./config/routes.js')(app, express, io);

  server.listen(PORT, function (){
    console.log('listening on port', PORT);
  });

// };

Remove socket test code, push io object to routes


'use strict'

var path = require('path')
var createTransform = require('./transform')

module.exports = function degreePlugin (browserify, options) {
  browserify.transform(createTransform(options.files.map(resolve)))

  function resolve (file) {
    return path.resolve(browserify.basedir || process.cwd(), file)
  }
}

'use strict'

var createTransform = require('./transform')

module.exports = function degreePlugin (browserify, options) {
  browserify.transform(createTransform(options.files.map(resolve)))

  function resolve (file) {
    return require.resolve(browserify.basedir || process.cwd(), file)
  }
}

Use require.resolve to turn partial filenames or '.' into full names


import { default as React } from 'react';
import en from './en';
import es from './es';

const locales = {en, es};

export default function translate(key) {
    return Component => {
        class TranslationComponent extends React.Component {

            componentWillMount() {
                let strings = locales[this.context.locale]['Framework7'];
                nekunoApp.params.modalTitle = strings.modalTitle;
                nekunoApp.params.modalButtonOk = strings.modalButtonOk;
                nekunoApp.params.modalButtonCancel = strings.modalButtonCancel;
            }

            render() {
                var strings = locales[this.context.locale][key];
                const merged = {
                    ...this.props.strings,
                    ...strings
                };
                if (strings) {
                    return <Component {...this.props} strings={merged} locale={this.context.locale}/>;
                } else {
                    return <Component {...this.props} locale={this.context.locale}/>;
                }

            }
        }

        TranslationComponent.contextTypes = {
            locale: React.PropTypes.string
        };

        return TranslationComponent;
    };
}

import { default as React } from 'react';
import en from './en';
import es from './es';

const locales = {en, es};

export default function translate(key) {
    return Component => {
        class TranslationComponent extends React.Component {

            componentWillMount() {
                let strings = locales[this.context.locale]['Framework7'];
                nekunoApp.params.modalTitle = strings.modalTitle;
                nekunoApp.params.modalButtonOk = strings.modalButtonOk;
                nekunoApp.params.modalButtonCancel = strings.modalButtonCancel;
            }

            // TranslationComponent receives ref from parent, so this is a wrapper to use children methods.
            getSelectedFilter() {
                let filter = null;
                Object.keys(this.refs).forEach(function(value){
                    if (typeof this.refs[value].getSelectedFilter === 'function'){
                        filter = this.refs[value].getSelectedFilter();
                    }
                }, this);

                return filter;
            }

            selectedFilterContains(a) {
                let contains = null;
                Object.keys(this.refs).forEach(function(value){
                    if (typeof this.refs[value].selectedFilterContains === 'function'){
                        contains = this.refs[value].selectedFilterContains(a);
                    }
                }, this);

                return contains;
            }

            render() {
                var strings = locales[this.context.locale][key];
                const merged = {
                    ...this.props.strings,
                    ...strings
                };
                if (strings) {
                    return <Component {...this.props} ref={Date.now()} strings={merged} locale={this.context.locale}/>;
                } else {
                    return <Component {...this.props} ref={Date.now()} locale={this.context.locale}/>;
                }

            }
        }

        TranslationComponent.contextTypes = {
            locale: React.PropTypes.string
        };

        return TranslationComponent;
    };
}

Access translated components by ref


var PATH = require('path'),

    pjoin = PATH.join,
    presolve = PATH.resolve.bind(null, __dirname),

    PRJ_ROOT = presolve('../../'),

    PRJ_TECHS = presolve('../techs/');

exports.getTechs = function() {

    return {
        'bemjson.js'    : '',
        'bemdecl.js'    : 'bemdecl.js',
        'deps.js'       : 'deps.js',
        'js'            : 'js-i',
        'css'           : 'css',
        'ie.css'        : 'ie.css',
        'ie6.css'       : 'ie6.css',
        'ie7.css'       : 'ie7.css',
        'ie8.css'       : 'ie8.css',
        'ie9.css'       : 'ie9.css',

        'bemhtml'       : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/bemhtml.js'),
        'html'          : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/html.js')
    };

};

// Do not create any techs files during bundle creation by default
exports.defaultTechs = [];

var PATH = require('path'),

    pjoin = PATH.join,
    presolve = PATH.resolve.bind(null, __dirname),

    PRJ_ROOT = presolve('../../'),

    PRJ_TECHS = presolve('../techs/');

exports.getTechs = function() {

    return {
        'bemjson.js'    : '',
        'bemdecl.js'    : 'bemdecl.js',
        'deps.js'       : 'deps.js',
        'js'            : 'js-i',
        'css'           : 'css',
        'ie.css'        : 'ie.css',
        'ie6.css'       : 'ie6.css',
        'ie7.css'       : 'ie7.css',
        'ie8.css'       : 'ie8.css',
        'ie9.css'       : 'ie9.css',

        'bemhtml'       : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/bemhtml.js'),
        'html'          : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/bemjson2html.js')
    };

};

// Do not create any techs files during bundle creation by default
exports.defaultTechs = [];

Support rename html tech to bemjson2html


angular
    .module('app')
    .controller('apiController', [
        '$rootScope',
        '$scope',
        '$location',
        '$routeParams',
        'authService',
        'MARLINAPI_CONFIG',
        function($rootScope, $scope, $location, $routeParams, Auth, MARLINAPI_CONFIG) {

            $scope.documentationPage = function() {

                $scope.api_base = MARLINAPI_CONFIG.base_url;

            };

        }
    ]);

angular
    .module('app')
    .controller('apiController', [
        '$rootScope',
        '$scope',
        '$location',
        '$routeParams',
        'authService',
        'MARLINAPI_CONFIG',
        function($rootScope, $scope, $location, $routeParams, Auth, MARLINAPI_CONFIG) {

            $scope.documentationPage = function() {

                $scope.api_base = MARLINAPI_CONFIG.base_url.replace('api', 'public_api');

            };

        }

    ]);

Fix link to api and public api.


import { directive } from 'lit-html/lit-html.js'

/*
 * Convert an RGB-Array into a Hex color
 */
export const rgbToHex = (value, defaultValue = '#000000') => directive(part => {
    // Is an RGB array
    if (Array.isArray(value) && value.length === 3) {
        const hex = `#${value.map(x => x.toString(16).padStart(2, '0')).join('')}`
        part.setValue(hex)
    // Is not an RGB array, so use the defaultValue
    } else {
        part.setValue(defaultValue)
    }
})

import { directive } from 'lit-html/lit-html.js'

/*
 * Convert an RGB-Array into a Hex color
 */
export const rgbToHex = directive((value, defaultValue = '#000000') => part => {
  // Is an RGB array
  if (Array.isArray(value) && value.length === 3) {
      const hex = `#${value.map(x => x.toString(16).padStart(2, '0')).join('')}`
      part.setValue(hex)
  // Is not an RGB array, so use the defaultValue
  } else {
      part.setValue(defaultValue)
  }
})

Convert to new lit-html standard


const {Record} = require('immutable');

const MonitorRecord = Record({
    id: null, // Block Id
    /** Present only if the monitor is sprite-specific, such as x position */
    spriteName: null,
    /** Present only if the monitor is sprite-specific, such as x position */
    targetId: null,
    opcode: null,
    value: null,
    params: null,
    mode: 'default',
    sliderMin: 0,
    sliderMax: 100,
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    visible: true
});

module.exports = MonitorRecord;

const {Record} = require('immutable');

const MonitorRecord = Record({
    id: null, // Block Id
    /** Present only if the monitor is sprite-specific, such as x position */
    spriteName: null,
    /** Present only if the monitor is sprite-specific, such as x position */
    targetId: null,
    opcode: null,
    value: null,
    params: null,
    mode: 'default',
    sliderMin: 0,
    sliderMax: 100,
    x: null, // (x: null, y: null) Indicates that the monitor should be auto-positioned
    y: null,
    width: 0,
    height: 0,
    visible: true
});

module.exports = MonitorRecord;

Update for auto-positioning monitors so that having just one of x or y be 0 (e.g. a monitor placed in the top right corner of the stage) does not result in the monitor being treated as a new monitor and get auto-positioned.


'use strict';

angular.module('kanbanBoardApp')
  .controller('BoardCtrl', ['$scope', 'Task', 'Project', 'Workspace', 'Tag', 'WORKSPACE_ID', 'PROJECT_ID', function ($scope, Task, Project, Workspace, Tag, WORKSPACE_ID, PROJECT_ID) {
    $scope.tags = [];
    var tagsLoaded = false;

    $scope.tagsLoaded = function () {
      return tagsLoaded;
    };

    $scope.loadTags = function () {
      Workspace.get({path: 'tags'}, function (response) {
        $scope.tags = response.data;
        tagsLoaded = true;
      });
    };

    $scope.getPointTags = function (tags) {
      return tags.filter( function (tag) {
        if (tag.name.match(/points/)) {
          return tag;
        }
      });
    };

    $scope.tagPointValue = function (tag) {
      return tag.name.replace(/[^\d+]/g, '');
    }
  }]);

'use strict';

angular.module('kanbanBoardApp')
  .controller('BoardCtrl', ['$scope', 'Task', 'Project', 'Workspace', 'Tag', 'WORKSPACE_ID', 'PROJECT_ID', function ($scope, Task, Project, Workspace, Tag, WORKSPACE_ID, PROJECT_ID) {
    $scope.tags = [];
    var tagsLoaded = false;

    $scope.tagsLoaded = function () {
      return tagsLoaded;
    };

    $scope.loadTags = function () {
      Workspace.get({path: 'tags'}, function (response) {
        $scope.tags = response.data;
        tagsLoaded = true;
      });
    };

    $scope.getPointTags = function (tags) {
      return tags.filter( function (tag) {
        if (tag.name.match(/points/)) {
          return tag;
        }
      });
    };

    $scope.tagPointValue = function (tag) {
      return parseInt(tag.name.replace(/[^\d+]/g, ''));
    }
  }]);

Return the point as a number.


import builder from 'xmlbuilder';
import kebabCase from 'lodash/kebabCase';

// custom stringify options for xml builder
// just kebab-cases all attributes and tag names
const customStringifyOptions = {
    eleName(val = '') {
        return this.assertLegalChar(kebabCase(val));
    },

    attName(val = '') {
        return kebabCase(val);
    },
};

/**
 * Recursively turns jsx children into xml nodes
 * @param {Array} children
 * @param {XMLNode} node
 */
function renderNode(node, children = []) {
    Array.from(children).forEach(child => {
        if (child && child.tag) {
            node.ele(child.tag, child.props);
            renderNode(child.children, node);
            node.end();
        } else {
            node.text(child);
        }
    });
}

/**
 * Nested JSON to pretty string
 * @param {Object} data
 * @return {String}
 */
export default function renderToString({ tag, children }, options = {}) {
    if (tag !== 'speak') {
        throw new Error(`SSML must start with a 'speak' tag, currently '${tag}'`);
    }

    const xml = builder.create(tag, {
        stringify: customStringifyOptions,
        headless: true,
    });

    renderNode(xml, children);

    return xml.end(options);
}

import builder from 'xmlbuilder';
import kebabCase from 'lodash/kebabCase';

// custom stringify options for xml builder
// just kebab-cases all attributes and tag names
const customStringifyOptions = {
    eleName(val = '') {
        return this.assertLegalChar(kebabCase(val));
    },

    attName(val = '') {
        return kebabCase(val);
    },
};

/**
 * Recursively turns jsx children into xml nodes
 * @param {Array} children
 * @param {XMLNode} node
 */
function renderNode(node, children = []) {
    [...children].forEach(child => {
        if (child && child.tag) {
            node.ele(child.tag, child.props);
            renderNode(child.children, node);
            node.end();
        } else {
            node.text(child);
        }
    });
}

/**
 * Nested JSON to pretty string
 * @param {Object} data
 * @return {String}
 */
export default function renderToString({ tag, children }, options = {}) {
    if (tag !== 'speak') {
        throw new Error(`SSML must start with a 'speak' tag, currently '${tag}'`);
    }

    const xml = builder.create(tag, {
        stringify: customStringifyOptions,
        headless: true,
    });

    renderNode(xml, children);

    return xml.end(options);
}

Use a spread instead of Array.from


'use strict';

const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
<% if(strategies.indexOf('local') !== -1) { %>const local = require('feathers-authentication-local');<% } %>
<% if(oauthProviders.length){ %>const oauth2 = require('feathers-authentication-oauth2');<% } %>
<% oauthProviders.forEach(provider => { %>
const <%= provider.strategyName %> = require('<%= provider.module %>');
<% }); %>

module.exports = function() {
  const app = this;
  const config = app.get('authentication');

  // Set up authentication with the secret
  app.configure(authentication(config));
  app.configure(jwt());
  <% if(strategies.indexOf('local') !== -1) { %>
  app.configure(local());
  <% } %>
  <% oauthProviders.forEach(provider => { %>
  app.configure(oauth2(Object.assign({
    name: '<%= provider.name %>',
    Strategy: <%= provider.strategyName %>
  }, config.<%= provider.name %>)));
  <% }); %>

  // The `authentication` service is used to create a JWT.
  // The before `create` hook registers strategies that can be used
  // to create a new valid JWT (e.g. local or oauth2)
  app.service('authentication').hooks({
    before: {
      create: [
        authentication.hooks.authenticate(config.strategies)
      ],
      remove: [
        authentication.hooks.authenticate('jwt')
      ]
    }
  });
};

'use strict';

const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
<% if(strategies.indexOf('local') !== -1) { %>const local = require('feathers-authentication-local');<% } %>
<% if(oauthProviders.length){ %>const oauth2 = require('feathers-authentication-oauth2');<% } %>
<% oauthProviders.forEach(provider => { %>
const <%= provider.strategyName %> = require('<%= provider.module %>');
<% }); %>

module.exports = function() {
  const app = this;
  const config = app.get('authentication');

  // Set up authentication with the secret
  app.configure(authentication(config));
  app.configure(jwt());
  <% if(strategies.indexOf('local') !== -1) { %>
  app.configure(local());
  <% } %>
  <% oauthProviders.forEach(provider => { %>
  app.configure(oauth2(Object.assign({
    name: '<%= provider.name %>',
    Strategy: <%= provider.strategyName %>,
    successRedirect: '/'
  }, config.<%= provider.name %>)));
  <% }); %>

  // The `authentication` service is used to create a JWT.
  // The before `create` hook registers strategies that can be used
  // to create a new valid JWT (e.g. local or oauth2)
  app.service('authentication').hooks({
    before: {
      create: [
        authentication.hooks.authenticate(config.strategies)
      ],
      remove: [
        authentication.hooks.authenticate('jwt')
      ]
    }
  });
};

Add a successRedirect by default


module.exports = {
  server: function(primus, options) {
    primus.on('connection', function(spark) {
      spark.hostname = spark.request.headers.host.split(':')[0];
    });
  }
};

module.exports = {
  server: function(primus, options) {
    var url = require('url');
    primus.on('connection', function(spark) {
      spark.hostname = url.parse(
        spark.request.headers.origin ||
        spark.request.headers.host
      ).hostname;
    });
  }
};

Fix domain detection in ws request


var express = require('express');
var app = express();

app.get('/', function (req, res) {
	res.send('Destroy all humans!');
});

var server = app.listen(3000, function () {
	var port = server.address().port;
	console.log('Fired up at http://localhost:%s, baby', port);
});

var express = require('express');
var app = express();

app.get('/', function (req, res) {
	res.send('Destroy all humans!');
});

app.get('/game', function (req, res) {
	var game = {
		game: 'Destroy all humans!'
	};
	res.send(game);
});

var server = app.listen(3000, function () {
	var port = server.address().port;
	console.log('Fired up at http://localhost:%s, baby', port);
	console.log('Try http://localhost:%s/', port);
	console.log('Try http://localhost:%s/game', port);
});

Add route that responds with json


var CELOS_USER = "celos";

var CELOS_DEFAULT_OOZIE = "http://admin1.ny7.collective-media.net:11000/oozie";

var CELOS_DEFAULT_HDFS = "hdfs://nameservice1";

var NAME_NODE = CELOS_DEFAULT_HDFS;

var JOB_TRACKER = "admin1.ny7.collective-media.net:8032";

var HIVE_METASTORE = "thrift://admin1.ny7.collective-media.net:9083";

var CELOS_DEFAULT_OOZIE_PROPERTIES = {
    "user.name": CELOS_USER,
    "jobTracker" : JOB_TRACKER,
    "nameNode" : CELOS_DEFAULT_HDFS,
    "hiveMetastore": HIVE_METASTORE,
    "oozie.use.system.libpath": "true"
};

var CELOS_USER = "celos";

var CELOS_DEFAULT_OOZIE = "http://oozie002.ny7.collective-media.net:11000/oozie";

var CELOS_DEFAULT_HDFS = "hdfs://nameservice1";

var NAME_NODE = CELOS_DEFAULT_HDFS;

var JOB_TRACKER = "admin1.ny7.collective-media.net:8032";

var HIVE_METASTORE = "thrift://hive-meta.ny7.collective-media.net:9803";

var CELOS_DEFAULT_OOZIE_PROPERTIES = {
    "user.name": CELOS_USER,
    "jobTracker" : JOB_TRACKER,
    "nameNode" : CELOS_DEFAULT_HDFS,
    "hiveMetastore": HIVE_METASTORE,
    "oozie.use.system.libpath": "true"
};

Update Oozie and Hive URLs.


import toolbox from 'sw-toolbox';

/* global process */
toolbox.options.debug = (process.env.NODE_ENV !== 'production');

toolbox.precache([
  '/service-worker.js',
  '/index.html',
  '/app.js',
  '/web-worker.js',
  '/manifest.json',
]);

/* global Request */
toolbox.router.get('/(.*)', (request, values, options) => {
  return toolbox.networkFirst(request, values, options).catch(() => {
    return toolbox.cacheOnly(new Request('/index.html'), values, options);
  });
}, {
  origin: /localhost:8080$/,
});

toolbox.router.any('/(.*)', toolbox.networkOnly, {
  origin: /localhost:3000$/,
});

toolbox.router.get('/(.*)', toolbox.cacheFirst, {
  origin: /\.(googleapis|gstatic)\.com$/,
  cache: {
    name: 'googleapis',
  },
});

(sw => {
  sw.addEventListener('activate', event => {
    event.waitUntil(self.clients.claim());
  });
})(self); /* global self */

import toolbox from 'sw-toolbox';

const { Request, Response } = self; /* global self */

const statics = [
  '/service-worker.js',
  '/index.html',
  '/app.js',
  '/web-worker.js',
  '/manifest.json',
];
const exts = statics.map(name => name.slice(name.lastIndexOf('.')));
const extRegex = new RegExp(`(${exts.join('|')})$`, 'i');

// Cache static assets.
toolbox.precache(statics);

// Enable debug mode and suppress sockjs-node request errors.
if (process.env.NODE_ENV !== 'production') { /* global process */
  toolbox.options.debug = true;

  toolbox.router.get('/sockjs-node/*', (request, values, options) => {
    return toolbox.networkOnly(request, values, options)
                  .catch(() => new Response());
  });
}

// Redirect SPA subroute requests to index.
toolbox.router.get('/*', (request, values, options) => {
  // Do not redirect static asset requests.
  if (request.url.match(extRegex)) {
    // TODO: Maybe use `fastest` when in production for faster app startup?
    return toolbox.networkFirst(request, values, options)
                  .catch(() => new Response());
  }

  // TODO: Maybe use `fastest` here? Why rely on the server for route redirects?
  return toolbox.networkFirst(request, values, options).catch(() => {
    return toolbox.cacheOnly(new Request('/index.html'), values, options)
                  .catch(() => new Response());
  });
}, {
  origin: /localhost:8080$/,
  cache: {
    name: 'statics',
  },
});

// Cache Google fonts and icons.
// TODO: Maybe use `cacheFirst` with additional `cache.maxAgeSeconds` here in
// order to not fire off network requests to Google on every startup?
toolbox.router.get('/*', toolbox.fastest, {
  origin: /\.(googleapis|gstatic)\.com$/,
  cache: {
    name: 'googleapis',
  },
});

Change some service worker caching behavior. * Ignore socket requests when in development. * Use fastest for google assets. * Add some todos to think about.


export default {
    getReadWidget:   () => '<ma-choices-column values="::entry.listValues[field.name()]"></ma-choices-column>',
    getLinkWidget:   () => '<ma-reference-many-link-column ids="::value" values="::entry.listValues[field.name()]" field="::field"></ma-reference-many-link-column>',
    getFilterWidget: () => '<ma-reference-many-field field="::field" value="value" datastore="::datastore"></reference-many-field-field>',
    getWriteWidget:  () => '<ma-reference-many-field field="::field" value="value" datastore="::datastore"></ma-reference-many-field>'
};

export default {
    getReadWidget:   () => '<ma-choices-column values="::entry.listValues[field.name()]"></ma-choices-column>',
    getLinkWidget:   () => '<ma-reference-many-link-column ids="::value" values="::entry.listValues[field.name()]" field="::field"></ma-reference-many-link-column>',
    getFilterWidget: () => '<ma-reference-many-field field="::field" value="value" datastore="::datastore"></ma-reference-many-field>',
    getWriteWidget:  () => '<ma-reference-many-field field="::field" value="value" datastore="::datastore"></ma-reference-many-field>'
};

Fix wrong closing tag in reference_many filter


'use strict';

var evil = require( './../lib' );

function compile( ctor ) {
	var name;
	var str;

	name = ctor.match( /^(\w*)Array$/ )[ 1 ];
	name = name + 'DataArray';

	str = '';
	str += '(function create(){';
	str += '"use strict";';
	str += 'class '+name+' extends '+ctor+'{';
	str += 'constructor(x){';
	str += 'super(x);';
	str += '}';
	str += '}';
	str += 'return '+name+';';
	str += '})();';
	return str;
}

var ctors;
var fcn;
var i;

ctors = [
	'Int8Array',
	'Uint8Array',
	'Uint8ClampedArray',
	'Int16Array',
	'Uint16Array',
	'Int32Array',
	'Uint32Array',
	'Float32Array',
	'Float64Array',
	'Array'
];

for ( i = 0; i < ctors.length; i++ ) {
	fcn = evil( compile( ctors[i] ) );
	console.log( fcn.toString() );
}

'use strict';

var hasClass = require( '@stdlib/utils/detect-class-support' )();
var evil = require( './../lib' );

function compile( ctor ) {
	var name;
	var str;

	name = ctor.match( /^(\w*)Array$/ )[ 1 ];
	name = name + 'DataArray';

	str = '';
	str += '(function create(){';
	str += '"use strict";';

	if ( hasClass ) {
		str += 'class '+name+' extends '+ctor+'{';
		str += 'constructor(x){';
		str += 'super(x);';
		str += '}';
		str += '}';
	} else {
		str += 'function '+name+'(){';
		str += 'if (!(this instanceof '+name+')){';
		str += 'return new '+name+'();';
		str += '}';
		str += 'ctor.call(this);';
		str += 'return this;';
		str += '}';
		str += name+'.prototype = Object.create('+ctor+'.prototype);';
		str += name+'.prototype.constructor = '+name+';';
	}
	str += 'return '+name+';';
	str += '})();';
	return str;
}

var ctors;
var fcn;
var i;

ctors = [
	'Int8Array',
	'Uint8Array',
	'Uint8ClampedArray',
	'Int16Array',
	'Uint16Array',
	'Int32Array',
	'Uint32Array',
	'Float32Array',
	'Float64Array',
	'Array'
];

for ( i = 0; i < ctors.length; i++ ) {
	fcn = evil( compile( ctors[i] ) );
	console.log( fcn.toString() );
}

Fix example to work on Node v1 and earlier


import DockerContainer from './DockerContainer.js'
import { checkDockerDaemon } from '../../../utils/index.js'

export default class DockerRunner {
  #codeDir = null
  #container = null

  constructor(funOptions, env, dockerOptions) {
    const {
      codeDir,
      functionKey,
      handler,
      runtime,
      layers,
      provider,
    } = funOptions

    this.#codeDir = codeDir
    if (
      dockerOptions.hostServicePath &&
      this.#codeDir === funOptions.servicePath
    ) {
      this.#codeDir = dockerOptions.hostServicePath
    }
    this.#container = new DockerContainer(
      env,
      functionKey,
      handler,
      runtime,
      layers,
      provider,
      dockerOptions,
    )
  }

  cleanup() {
    if (this.#container) {
      return this.#container.stop()
    }

    return undefined
  }

  // context will be generated in container
  async run(event) {
    // FIXME TODO this should run only once -> static private
    await checkDockerDaemon()

    if (!this.#container.isRunning) {
      await this.#container.start(this.#codeDir)
    }

    return this.#container.request(event)
  }
}

import DockerContainer from './DockerContainer.js'
import { checkDockerDaemon } from '../../../utils/index.js'

export default class DockerRunner {
  #codeDir = null
  #container = null

  constructor(funOptions, env, dockerOptions) {
    const {
      codeDir,
      functionKey,
      handler,
      runtime,
      layers,
      provider,
      servicePath,
    } = funOptions

    this.#codeDir = codeDir
    if (
      dockerOptions.hostServicePath &&
      this.#codeDir.startsWith(servicePath)
    ) {
      this.#codeDir = this.#codeDir.replace(
        servicePath,
        dockerOptions.hostServicePath,
      )
    }
    this.#container = new DockerContainer(
      env,
      functionKey,
      handler,
      runtime,
      layers,
      provider,
      dockerOptions,
    )
  }

  cleanup() {
    if (this.#container) {
      return this.#container.stop()
    }

    return undefined
  }

  // context will be generated in container
  async run(event) {
    // FIXME TODO this should run only once -> static private
    await checkDockerDaemon()

    if (!this.#container.isRunning) {
      await this.#container.start(this.#codeDir)
    }

    return this.#container.request(event)
  }
}

Fix code dir for docker container


import React from 'react';
import PropTypes from 'prop-types';
import { createPortal } from 'react-dom';
import { canUseDOM } from './utils';

class Portal extends React.Component {
  componentWillUnmount() {
    if (this.defaultNode) {
      document.body.removeChild(this.defaultNode);
    }
    this.defaultNode = null;
  }

  render() {
    if (!canUseDOM) {
      return null;
    }
    if (!this.props.node && !this.defaultNode) {
      this.defaultNode = document.createElement('div');
      document.body.appendChild(this.defaultNode);
    }
    return createPortal(
      this.props.children,
      this.props.node || this.defaultNode
    );
  }
}

Portal.propTypes = {
  children: PropTypes.node.isRequired,
  node: PropTypes.any
};

export default Portal;

import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { canUseDOM } from './utils';

class Portal extends React.Component {
  componentWillUnmount() {
    if (this.defaultNode) {
      document.body.removeChild(this.defaultNode);
    }
    this.defaultNode = null;
  }

  render() {
    if (!canUseDOM) {
      return null;
    }
    if (!this.props.node && !this.defaultNode) {
      this.defaultNode = document.createElement('div');
      document.body.appendChild(this.defaultNode);
    }
    return ReactDOM.createPortal(
      this.props.children,
      this.props.node || this.defaultNode
    );
  }
}

Portal.propTypes = {
  children: PropTypes.node.isRequired,
  node: PropTypes.any
};

export default Portal;

Fix portal import from react-dom


// function to create the singleton options object that can be shared
// throughout an application
function createurlQueryConfig() {
  // default options
  return {
    // add in generated URL change handlers based on a urlPropsQueryConfig if provided
    addUrlChangeHandlers: true,

    // add in `props.params` from react-router to the url object
    addRouterParams: true,

    // use this history if no history is specified
    history: {
      push() {
        // eslint-disable-next-line
        console.error('No history provided to react-url-query. Please provide one via configureUrlQuery.');
      },
      replace() {
        // eslint-disable-next-line
        console.error('No history provided to react-url-query. Please provide one via configureUrlQuery.');
      },
    },

    // reads in location from react-router-redux if available and passes it
    // to the reducer in the urlQueryMiddleware
    readLocationFromStore(state) {
      if (state && state.routing) {
        return state.routing.locationBeforeTransitions;
      }

      return undefined;
    },
  };
}

export default createurlQueryConfig();

// function to create the singleton options object that can be shared
// throughout an application
function createurlQueryConfig() {
  // default options
  return {
    // add in generated URL change handlers based on a urlPropsQueryConfig if provided
    addUrlChangeHandlers: true,

    // add in `props.params` from react-router to the url object
    addRouterParams: true,

    // function to specify change handler name (onChange<PropName>)
    changeHandlerName: propName => `onChange${propName[0].toUpperCase()}${propName.substring(1)}`,

    // use this history if no history is specified
    history: {
      push() {
        // eslint-disable-next-line
        console.error('No history provided to react-url-query. Please provide one via configureUrlQuery.');
      },
      replace() {
        // eslint-disable-next-line
        console.error('No history provided to react-url-query. Please provide one via configureUrlQuery.');
      },
    },

    // reads in location from react-router-redux if available and passes it
    // to the reducer in the urlQueryMiddleware
    readLocationFromStore(state) {
      if (state && state.routing) {
        return state.routing.locationBeforeTransitions;
      }

      return undefined;
    },
  };
}

export default createurlQueryConfig();

Add default value for changeHandlerName to config


const { resolve, join } = require("path");
const { IgnorePlugin } = require("webpack");
const path = require("path");

const moduleRoot = resolve(__dirname, "..");
const outputPath = join(moduleRoot, "dist");

module.exports = {
  mode: "production",
  entry: join(moduleRoot, "src", "index.js"),
  target: "node",
  devtool: "source-map",
  output: {
    path: outputPath,
    filename: "index.js",
    library: "truffle-hdwallet-provider",
    libraryTarget: "umd",
    umdNamedDefine: true
  },
  externals: ["fs", "bindings", "any-promise"],
  resolve: {
    alias: {
      // eth-block-tracker is es6 but automatically builds an es5 version for us on install. thanks eth-block-tracker!
      "eth-block-tracker": "eth-block-tracker/dist/es5/index.js",

      // replace native `scrypt` module with pure js `js-scrypt`
      "scrypt": "js-scrypt",

      // replace native `secp256k1` with pure js `elliptic.js`
      "secp256k1": "secp256k1/elliptic.js",

      // fix websocket require path
      "websocket": path.resolve(__dirname, "../")
    }
  },
  plugins: [
    // ignore these plugins completely
    new IgnorePlugin(/^(?:electron|ws)$/)
  ]
};

const { resolve, join } = require("path");
const { IgnorePlugin } = require("webpack");
const path = require("path");

const moduleRoot = resolve(__dirname, "..");
const outputPath = join(moduleRoot, "dist");

module.exports = {
  mode: "production",
  entry: join(moduleRoot, "src", "index.js"),
  target: "node",
  devtool: "source-map",
  output: {
    path: outputPath,
    filename: "index.js",
    library: "truffle-hdwallet-provider",
    libraryTarget: "umd",
    umdNamedDefine: true
  },
  externals: ["fs", "bindings", "any-promise", "websocket"],
  resolve: {
    alias: {
      // eth-block-tracker is es6 but automatically builds an es5 version for us on install. thanks eth-block-tracker!
      "eth-block-tracker": "eth-block-tracker/dist/es5/index.js",

      // replace native `scrypt` module with pure js `js-scrypt`
      "scrypt": "js-scrypt",

      // replace native `secp256k1` with pure js `elliptic.js`
      "secp256k1": "secp256k1/elliptic.js",
    }
  },
  plugins: [
    // ignore these plugins completely
    new IgnorePlugin(/^(?:electron|ws)$/)
  ]
};

Mark websocket as external for webpack