<commit_before>import _ from 'lodash';
import chalk from 'chalk';
import * as util from '../core/util.js';
import { clone, checkAndSwitch, checkRemoteResetRequired } from '../core/dependencies.js';
import { getTargetFromRepoUrl } from '../core/resolve.js';
import globalConfig from '../core/globalConfig.js';
import * as getSnapshot from '../core/getSnapshot.js';
import checkForConflicts from '../core/checkForConflicts.js';
import GitRepositorySnapshot from '../core/GitRepositorySnapshot.js';
import snapshotPool from '../core/snapshotPool.js';
import getStatus from '../core/getStatus.js';
import logger from '../core/logger.js';

async function stashAndPull( snapshot, pkgdir, options, propagateErrors = false ) {
	const changed = !await snapshot.isUpToDate();
	if ( !changed ) {
		return false;
	}
	// repo is the same - do an update
	const stashName = await snapshot.stash();
	try {
		await snapshot.pull();
	} catch ( err ) {
		if ( propagateErrors ) {
			throw err;
		}
	}
	await snapshot.stashPop( stashName );
	return changed;
}

async function updateMainProject( options, snapshot ) {
	if ( await snapshot.getStatus() !== 'installed' ) {
		// root project is not a git repository, just continue
		return;
	}
	if ( !options.json ) {
		logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Updating...` );
	}
	const stashName = await snapshot.stash();
	try {
		await snapshot.pull();
	} catch ( err ) {
		logger.error( `${util.formatConsoleDependencyName( snapshot.name, true )} Main project pull failed, does your branch exist on the remote?` );
	}
	await snapshot.stashPop( stashName );
	// if ( !options.json ) {
		// let targetName;
		// try {
			// targetName = target.tag || target.commit || target.branch;
		// } catch ( err ) {
		// }
		// logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Complete`, targetName ? `[${chalk.magenta(targetName)}]` : ``, changed ? `[${chalk.yellow( 'changes detected' )}]` : `` );
	// }
}

async function switchIncorrectBranchRefs( options, snapshot, ref ) {
	if ( !options.json ) {
		logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Updating...` );
	}

	// clone new repository if it's missing
	if ( await snapshot.getStatus() === 'missing' ) {
		if ( !options.json ) {
			logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Repository missing, performing fresh clone...` );
		}
		const repoUrl = util.parseRepositoryUrl( ref );
		await clone( snapshot.dir, options, repoUrl, options.link, snapshot );
	}

	let targetObj = null;
	try {
		targetObj = await getTargetFromRepoUrl( snapshot, ref, snapshot.dir );
	} catch ( err ) {
	}
	if ( !targetObj ) {
		// desired branch / tag does not exist - fall back to master
		targetObj = { branch: 'master' };
	}

	// check to see if the local branch still exists on the remote, reset if not
	if ( options['remote-reset'] !== false ) {
		const repoUrl = util.parseRepositoryUrl( ref );
		await checkRemoteResetRequired( snapshot, targetObj, snapshot.name, snapshot.dir, options, repoUrl );
	}
	if ( options.switch ) {
		await checkAndSwitch( snapshot, options, snapshot.dir, ref );
	}
	try {
		await stashAndPull( snapshot, snapshot.dir, options, true );
	} catch ( err ) {
		// On a repo that looks like everything should work fine but doesn't, the repo has probably been recreated.
		// if the repo is clean, hard reset and pull.
		const errout = await snapshot.pullCaptureError();
		if ( errout === 'fatal: refusing to merge unrelated histories' ) {
			if ( await snapshot.isWorkingCopyClean() ) {
				logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Unrelated histories detected, performing hard reset...` );
				await snapshot.fixUnrelatedHistory( targetObj );
			} else {
				logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Unrelated histories detected, but cannot reset due to local changes!` );
			}
		} else {
			throw err;
		}
	}
}

async function iterateDeps( options, snapshot ) {
	const deps = await snapshot.getDependencies();
	for ( const name of Object.keys( deps ) ) {
		const ref = deps[name];
		const childSnapshot = await snapshotPool.fromName( name, ref );
		await switchIncorrectBranchRefs( options, childSnapshot, ref );
		await iterateDeps( options, childSnapshot );
	}
}

/**
 * Executes update on given directory
 *
 * @param {Object} options - Command line options
 * @param {string} options.cwd - Working directory
 * @param {boolean} [options.force-latest=false] - Force latest version on conflict
 */
async function update( options ) {
	if ( !_.isString( options.cwd ) ) {
		throw new Error( `Invalid cwd argument ${options.cwd}` );
	}
	await globalConfig.init( options.cwd );
	util.defaultOptions( options );

	const initialSnapshot = await getSnapshot.getSnapshot( options.cwd );

	// make sure there are no conflicts in any dependencies before doing update
	const conflicts = await checkForConflicts( initialSnapshot, initialSnapshot.main );
	if ( conflicts.length > 0 ) {
		for ( const ss of conflicts ) {
			logger.log( 'error', `${util.formatConsoleDependencyName( ss.name )} Git conflict detected` );
		}
		const conflictString = `${conflicts.length} conflict${conflicts.length === 1 ? '' : 's'} detected`;
		logger.log( 'error', `${chalk.red( conflictString )} aborting update` );
		return;
	}
	if ( !options.fromCloneCommand ) {
		await updateMainProject( options, initialSnapshot.main );
	}

	if (options['ignore-dependencies']) {
		return;
	}

	// re-read config file in case the .flaviorc has changed
	await globalConfig.init( options.cwd );

	// Iterate over all dependencies
	await iterateDeps( options, await GitRepositorySnapshot.fromDir( options.cwd ) );

	if ( !options.json ) {
		//snapshotPool.clearAll();
		const statusSnapshot = await getSnapshot.getSnapshot( options.cwd );
		const status = await getStatus( { ...options, nofetch: true }, statusSnapshot, {
			changed: true
		} );
		console.log( status );
	}
}

export default update;
<commit_msg>Don't show "changed" on fresh clone<commit_after>import _ from 'lodash';
import chalk from 'chalk';
import * as util from '../core/util.js';
import { clone, checkAndSwitch, checkRemoteResetRequired } from '../core/dependencies.js';
import { getTargetFromRepoUrl } from '../core/resolve.js';
import globalConfig from '../core/globalConfig.js';
import * as getSnapshot from '../core/getSnapshot.js';
import checkForConflicts from '../core/checkForConflicts.js';
import GitRepositorySnapshot from '../core/GitRepositorySnapshot.js';
import snapshotPool from '../core/snapshotPool.js';
import getStatus from '../core/getStatus.js';
import logger from '../core/logger.js';

async function stashAndPull( snapshot, pkgdir, options, propagateErrors = false ) {
	const changed = !await snapshot.isUpToDate();
	if ( !changed ) {
		return false;
	}
	// repo is the same - do an update
	const stashName = await snapshot.stash();
	try {
		await snapshot.pull();
	} catch ( err ) {
		if ( propagateErrors ) {
			throw err;
		}
	}
	await snapshot.stashPop( stashName );
	return changed;
}

async function updateMainProject( options, snapshot ) {
	if ( await snapshot.getStatus() !== 'installed' ) {
		// root project is not a git repository, just continue
		return;
	}
	if ( !options.json ) {
		logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Updating...` );
	}
	const stashName = await snapshot.stash();
	try {
		await snapshot.pull();
	} catch ( err ) {
		logger.error( `${util.formatConsoleDependencyName( snapshot.name, true )} Main project pull failed, does your branch exist on the remote?` );
	}
	await snapshot.stashPop( stashName );
	// if ( !options.json ) {
		// let targetName;
		// try {
			// targetName = target.tag || target.commit || target.branch;
		// } catch ( err ) {
		// }
		// logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Complete`, targetName ? `[${chalk.magenta(targetName)}]` : ``, changed ? `[${chalk.yellow( 'changes detected' )}]` : `` );
	// }
}

async function switchIncorrectBranchRefs( options, snapshot, ref ) {
	if ( !options.json ) {
		logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Updating...` );
	}

	// clone new repository if it's missing
	if ( await snapshot.getStatus() === 'missing' ) {
		if ( !options.json ) {
			logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Repository missing, performing fresh clone...` );
		}
		const repoUrl = util.parseRepositoryUrl( ref );
		await clone( snapshot.dir, options, repoUrl, options.link, snapshot );
	}

	let targetObj = null;
	try {
		targetObj = await getTargetFromRepoUrl( snapshot, ref, snapshot.dir );
	} catch ( err ) {
	}
	if ( !targetObj ) {
		// desired branch / tag does not exist - fall back to master
		targetObj = { branch: 'master' };
	}

	// check to see if the local branch still exists on the remote, reset if not
	if ( options['remote-reset'] !== false ) {
		const repoUrl = util.parseRepositoryUrl( ref );
		await checkRemoteResetRequired( snapshot, targetObj, snapshot.name, snapshot.dir, options, repoUrl );
	}
	if ( options.switch ) {
		await checkAndSwitch( snapshot, options, snapshot.dir, ref );
	}
	try {
		await stashAndPull( snapshot, snapshot.dir, options, true );
	} catch ( err ) {
		// On a repo that looks like everything should work fine but doesn't, the repo has probably been recreated.
		// if the repo is clean, hard reset and pull.
		const errout = await snapshot.pullCaptureError();
		if ( errout === 'fatal: refusing to merge unrelated histories' ) {
			if ( await snapshot.isWorkingCopyClean() ) {
				logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Unrelated histories detected, performing hard reset...` );
				await snapshot.fixUnrelatedHistory( targetObj );
			} else {
				logger.log( 'info', util.formatConsoleDependencyName( snapshot.name ), `Unrelated histories detected, but cannot reset due to local changes!` );
			}
		} else {
			throw err;
		}
	}
}

async function iterateDeps( options, snapshot ) {
	const deps = await snapshot.getDependencies();
	for ( const name of Object.keys( deps ) ) {
		const ref = deps[name];
		const childSnapshot = await snapshotPool.fromName( name, ref );
		await switchIncorrectBranchRefs( options, childSnapshot, ref );
		await iterateDeps( options, childSnapshot );
	}
}

/**
 * Executes update on given directory
 *
 * @param {Object} options - Command line options
 * @param {string} options.cwd - Working directory
 * @param {boolean} [options.force-latest=false] - Force latest version on conflict
 */
async function update( options ) {
	if ( !_.isString( options.cwd ) ) {
		throw new Error( `Invalid cwd argument ${options.cwd}` );
	}
	await globalConfig.init( options.cwd );
	util.defaultOptions( options );

	const initialSnapshot = await getSnapshot.getSnapshot( options.cwd );

	// make sure there are no conflicts in any dependencies before doing update
	const conflicts = await checkForConflicts( initialSnapshot, initialSnapshot.main );
	if ( conflicts.length > 0 ) {
		for ( const ss of conflicts ) {
			logger.log( 'error', `${util.formatConsoleDependencyName( ss.name )} Git conflict detected` );
		}
		const conflictString = `${conflicts.length} conflict${conflicts.length === 1 ? '' : 's'} detected`;
		logger.log( 'error', `${chalk.red( conflictString )} aborting update` );
		return;
	}
	if ( !options.fromCloneCommand ) {
		await updateMainProject( options, initialSnapshot.main );
	}

	if (options['ignore-dependencies']) {
		return;
	}

	// re-read config file in case the .flaviorc has changed
	await globalConfig.init( options.cwd );

	// Iterate over all dependencies
	await iterateDeps( options, await GitRepositorySnapshot.fromDir( options.cwd ) );

	if ( !options.json ) {
		//snapshotPool.clearAll();
		const statusSnapshot = await getSnapshot.getSnapshot( options.cwd );
		const status = await getStatus( { ...options, nofetch: true }, statusSnapshot, {
			changed: !options.fromCloneCommand
		} );
		console.log( status );
	}
}

export default update;
<|endoftext|>


<commit_before>/*global $, OpenLayers, gnt, projects_IC, projects_QU, projects_PP, map, city_polygon */

/*
 Dashboard UI namespace

 gnt.dashboard
*/
gnt.dashboard = {};
gnt.map_loaded = false;
// Create a select feature control and add it to the map.
//gnt.dashboard.select;
gnt.dashboard.geojsonFormat = new OpenLayers.Format.GeoJSON();

gnt.after_map_loaded = function(){
    var style_map = new OpenLayers.StyleMap({
        "default": {
            strokeWidth: 1,
            strokeColor: $('body').css('background-color'),
            cursor: 'pointer',
            fillColor: $('body').css('background-color'),
            fillOpacity: 0.4
        },
        "select": {
            strokeWidth: 1,
            strokeColor: $('body').css('background-color'),
            cursor: 'pointer',
            fillColor: $('body').css('background-color'),
            fillOpacity: 0.7
        }
    }),
        PP_layer = new OpenLayers.Layer.Vector("Plan proposals layer", {
            styleMap: style_map,
            visibility: true
            }),
        IC_layer = new OpenLayers.Layer.Vector("Idea competitions layer", {
            styleMap: style_map,
            visibility: true
            }),
        QU_layer = new OpenLayers.Layer.Vector("Questionnaires layer", {
            styleMap: style_map,
            visibility: true
        }),
        questionnaires = gnt.dashboard.geojsonFormat.read(projects_QU),
        idea_competitions = gnt.dashboard.geojsonFormat.read(projects_IC),
        plan_projects = gnt.dashboard.geojsonFormat.read(projects_PP),
        bounds,
        i,
        j,
        k;
        map.addLayers([IC_layer, QU_layer, PP_layer]);
        var select = new OpenLayers.Control.SelectFeature(
            [QU_layer, IC_layer, PP_layer],
            {
                id: 'selectcontrol',
                hover: true,
                onSelect: function (event) {
                    //connect the select feature with the list
                    var id = event.fid;
                    $('#' + id).addClass('hover');
                },
                onUnselect: function (event) {
                    //connect the select feature with the list
                    var id = event.fid;
                    $('#' + id).removeClass('hover');
                }
            }
        );
        map.addControl(select);
        select.activate();

        //Project geometries to map projection
        // We assume that all projects are in the same coordinate system
        var source_proj_code = 'EPSG:4326',
            source_proj,
            target_proj,
            city_ol_feature;
        if(projects_IC.crs !== undefined) {
            source_proj_code = projects_IC.crs.properties.code;
        }
        else if(projects_QU.crs !== undefined) {
            source_proj_code = projects_QU.crs.properties.code;
        }
        else if(projects_PP.crs !== undefined) {
            source_proj_code = projects_PP.crs.properties.code;
        }
        else if (city_polygon.crs !== undefined){ // fallback to Organization area
            source_proj_code = city_polygon.crs.properties.code;
        }
        source_proj = new OpenLayers.Projection(source_proj_code);
        target_proj = new OpenLayers.Projection(map.getProjection());

        for (i = 0; i < idea_competitions.length; i++) {
            idea_competitions[i].geometry.transform(source_proj, target_proj);
        }
        for (j = 0; j < questionnaires.length; j++) {
            questionnaires[j].geometry.transform(source_proj, target_proj);
        }
        for (k = 0; k < plan_projects.length; k++) {
            plan_projects[k].geometry.transform(source_proj, target_proj);
        }

        {% if request.META.HTTP_HOST != "oregonstateparks.maptionnaire.com" %}
        QU_layer.addFeatures(questionnaires);
        IC_layer.addFeatures(idea_competitions);
        IC_layer.addFeatures(plan_projects);
        {% endif %}
        //count the bounds for the map
        for (i = 0; i < idea_competitions.length; i++) {
            if (bounds === undefined) {
                bounds = idea_competitions[i].geometry.getBounds();
            } else {
                bounds.extend(idea_competitions[i].geometry.getBounds());
            }
        }
        for (j = 0; j < questionnaires.length; j++) {
            if (bounds === undefined) {
                bounds = questionnaires[j].geometry.getBounds();
            } else {
                bounds.extend(questionnaires[j].geometry.getBounds());
            }
        }
        for (k = 0; k < plan_projects.length; k++) {
            if (bounds === undefined) {
                bounds = plan_projects[k].geometry.getBounds();
            } else {
                bounds.extend(plan_projects[k].geometry.getBounds());
            }
        }
        if (bounds === undefined) {
            city_ol_feature = gnt.dashboard.geojsonFormat.read(city_polygon);
            city_ol_feature[0].geometry.transform(source_proj, target_proj);
            bounds = city_ol_feature[0].geometry.getBounds();
        }

        {% if request.META.HTTP_HOST == "oregonstateparks.maptionnaire.com" %}
        $('li.project').css('background','white');
        map.setCenter(new OpenLayers.LonLat(-13575293.937978, 5709272.0092249),10);
        {% else %}
        map.zoomToExtent(bounds);
        {% endif %}
        //connect the list hover with the feature
        $('.project').hover(function (event) {
            var layer,feature;
            for (layer in map.layers) {
                if (map.layers[layer].getFeatureByFid) {
                    feature = map.layers[layer].getFeatureByFid(this.id);
                    if (feature) {
                        map.getControl('selectcontrol').select(feature);
                    }
                }
            }
        },
            function (event) {
            var layer,
                feature;
                for (layer in map.layers) {
                    if (map.layers[layer].getFeatureByFid) {
                        feature = map.layers[layer].getFeatureByFid(this.id);
                        if (feature) {
                            map.getControl('selectcontrol').unselect(feature);
                        }
                    }
                }
            });
        //this is for setting links on features
        $('.olMapViewport').click(function (event) {
            if ($('.project.hover a').length > 0) {
                window.location = $('.project.hover a').last()[0].href;
            }
        });
        $('ul.nav li a').click(
            function(e) {
                e.preventDefault();
                e.stopPropagation();
                $('body').removeClass('main map settings');
                $('body').addClass(this.parentNode.classList[0]);
        });

    };

gnt.dashboard.init = function () {

    gnt.map_loaded = gnt.maps.create_map('map');
    if (gnt.map_loaded){
        gnt.after_map_loaded();
    }

};

<commit_msg>the hover effects on dashboard are only needed when there are several questionnaires<commit_after>/*global $, OpenLayers, gnt, projects_IC, projects_QU, projects_PP, map, city_polygon */

/*
 Dashboard UI namespace

 gnt.dashboard
*/
gnt.dashboard = {};
gnt.map_loaded = false;
// Create a select feature control and add it to the map.
//gnt.dashboard.select;
gnt.dashboard.geojsonFormat = new OpenLayers.Format.GeoJSON();

gnt.after_map_loaded = function(){
    var style_map = new OpenLayers.StyleMap({
        "default": {
            strokeWidth: 1,
            strokeColor: $('body').css('background-color'),
            cursor: 'pointer',
            fillColor: $('body').css('background-color'),
            fillOpacity: 0.4
        },
        "select": {
            strokeWidth: 1,
            strokeColor: $('body').css('background-color'),
            cursor: 'pointer',
            fillColor: $('body').css('background-color'),
            fillOpacity: 0.7
        }
    }),
        PP_layer = new OpenLayers.Layer.Vector("Plan proposals layer", {
            styleMap: style_map,
            visibility: true
            }),
        IC_layer = new OpenLayers.Layer.Vector("Idea competitions layer", {
            styleMap: style_map,
            visibility: true
            }),
        QU_layer = new OpenLayers.Layer.Vector("Questionnaires layer", {
            styleMap: style_map,
            visibility: true
        }),
        questionnaires = gnt.dashboard.geojsonFormat.read(projects_QU),
        idea_competitions = gnt.dashboard.geojsonFormat.read(projects_IC),
        plan_projects = gnt.dashboard.geojsonFormat.read(projects_PP),
        bounds,
        i,
        j,
        k;
        map.addLayers([IC_layer, QU_layer, PP_layer]);
        var select = new OpenLayers.Control.SelectFeature(
            [QU_layer, IC_layer, PP_layer],
            {
                id: 'selectcontrol',
                hover: true,
                onSelect: function (event) {
                    //connect the select feature with the list
                    var id = event.fid;
                    $('#' + id).addClass('hover');
                },
                onUnselect: function (event) {
                    //connect the select feature with the list
                    var id = event.fid;
                    $('#' + id).removeClass('hover');
                }
            }
        );
        map.addControl(select);
        select.activate();

        //Project geometries to map projection
        // We assume that all projects are in the same coordinate system
        var source_proj_code = 'EPSG:4326',
            source_proj,
            target_proj,
            city_ol_feature;
        if(projects_IC.crs !== undefined) {
            source_proj_code = projects_IC.crs.properties.code;
        }
        else if(projects_QU.crs !== undefined) {
            source_proj_code = projects_QU.crs.properties.code;
        }
        else if(projects_PP.crs !== undefined) {
            source_proj_code = projects_PP.crs.properties.code;
        }
        else if (city_polygon.crs !== undefined){ // fallback to Organization area
            source_proj_code = city_polygon.crs.properties.code;
        }
        source_proj = new OpenLayers.Projection(source_proj_code);
        target_proj = new OpenLayers.Projection(map.getProjection());

        for (i = 0; i < idea_competitions.length; i++) {
            idea_competitions[i].geometry.transform(source_proj, target_proj);
        }
        for (j = 0; j < questionnaires.length; j++) {
            questionnaires[j].geometry.transform(source_proj, target_proj);
        }
        for (k = 0; k < plan_projects.length; k++) {
            plan_projects[k].geometry.transform(source_proj, target_proj);
        }

        {% if request.META.HTTP_HOST != "oregonstateparks.maptionnaire.com" %}
        QU_layer.addFeatures(questionnaires);
        IC_layer.addFeatures(idea_competitions);
        IC_layer.addFeatures(plan_projects);
        {% endif %}
        //count the bounds for the map
        for (i = 0; i < idea_competitions.length; i++) {
            if (bounds === undefined) {
                bounds = idea_competitions[i].geometry.getBounds();
            } else {
                bounds.extend(idea_competitions[i].geometry.getBounds());
            }
        }
        for (j = 0; j < questionnaires.length; j++) {
            if (bounds === undefined) {
                bounds = questionnaires[j].geometry.getBounds();
            } else {
                bounds.extend(questionnaires[j].geometry.getBounds());
            }
        }
        for (k = 0; k < plan_projects.length; k++) {
            if (bounds === undefined) {
                bounds = plan_projects[k].geometry.getBounds();
            } else {
                bounds.extend(plan_projects[k].geometry.getBounds());
            }
        }
        if (bounds === undefined) {
            city_ol_feature = gnt.dashboard.geojsonFormat.read(city_polygon);
            city_ol_feature[0].geometry.transform(source_proj, target_proj);
            bounds = city_ol_feature[0].geometry.getBounds();
        }

        {% if request.META.HTTP_HOST == "oregonstateparks.maptionnaire.com" %}
        map.setCenter(new OpenLayers.LonLat(-13575293.937978, 5709272.0092249),10);
        {% else %}
        map.zoomToExtent(bounds);
        {% endif %}
        //connect the list hover with the feature
        if (questionnaires.length < 2){
            $('li.project').css('background','white');
        } else {
            $('.project').hover(function (event) {
                var layer,feature;
                for (layer in map.layers) {
                    if (map.layers[layer].getFeatureByFid) {
                        feature = map.layers[layer].getFeatureByFid(this.id);
                        if (feature) {
                            map.getControl('selectcontrol').select(feature);
                        }
                    }
                }
            },
                function (event) {
                var layer,
                    feature;
                    for (layer in map.layers) {
                        if (map.layers[layer].getFeatureByFid) {
                            feature = map.layers[layer].getFeatureByFid(this.id);
                            if (feature) {
                                map.getControl('selectcontrol').unselect(feature);
                            }
                        }
                    }
                });
        }
        //this is for setting links on features
        $('.olMapViewport').click(function (event) {
            if ($('.project.hover a').length > 0) {
                window.location = $('.project.hover a').last()[0].href;
            }
        });
        $('ul.nav li a').click(
            function(e) {
                e.preventDefault();
                e.stopPropagation();
                $('body').removeClass('main map settings');
                $('body').addClass(this.parentNode.classList[0]);
        });

    };

gnt.dashboard.init = function () {

    gnt.map_loaded = gnt.maps.create_map('map');
    if (gnt.map_loaded){
        gnt.after_map_loaded();
    }

};

<|endoftext|>


<commit_before>// Copyright 2015 Teem2 LLC, MIT License (see LICENSE)
// Teem server

define.class(function(require, exports, self){

	var http = require('http')
	var os = require('os')
	var path = require('path')
	var fs = require('fs')
	var url = require('url')

	var FileWatcher = require('$server/filewatcher')
	var ExternalApps = require('$server/externalapps')
	var BusServer = require('$rpc/busserver')
	var CompositionServer = require('$dreem/compositionserver')
	var NodeWebSocket = require('$server/nodewebsocket')
	var mimeFromFile = require('$server/mimefromfile')

	// Doccumentation
	self.atConstructor = function(args){
		this.compositions = {}

		this.args = args
		var port = this.args['-port'] || 8080
		var iface = this.args['-iface'] || '0.0.0.0'

		this.server = http.createServer(this.request.bind(this))
		this.server.listen(port, iface)
		this.server.on('upgrade', this.upgrade.bind(this))

		if(iface == '0.0.0.0'){
			var ifaces = os.networkInterfaces()
			var txt = ''
			Object.keys(ifaces).forEach(function(ifname){
				var alias = 0;
				ifaces[ifname].forEach(function(iface){
					if ('IPv4' !== iface.family) return
					var addr = 'http://' + iface.address + ':' + port + '/'
					if(!this.address) this.address = addr
					txt += ' ~~on ~c~'+addr
				}.bind(this))
			}.bind(this))
			console.color('Server running' + txt + '~~ Ready to go!\n')
		}
		else {
			this.address = 'http://' + iface + ':' + port + '/'
			console.color('Server running on ~c~' + this.address + "~~\n")
		}
		// use the browser spawner
		var browser = this.args['-browser']
		if(browser && (!this.args['-delay'] || this.args['-count'] ==0 )){
			ExternalApps.browser(this.address + (browser===true?'':browser), this.args['-devtools'])
		}

		this.watcher = new FileWatcher()
		this.watcher.atChange = function(file){
			if(!args['-nodreem'] && file.indexOf('dreem.js') !== -1){
				return this.broadcast({type:'delay'})
			}
			file = file.slice(define.expandVariables(define.$root).length)
			// ok lets rip off our
			this.broadcast({
				type:'filechange',
				file: file
			})
		}.bind(this)

		this.busserver = new BusServer()

		process.on('SIGHUP', function(){
			if(this.args['-close']) this.broadcast({type:'close'})
			if(this.args['-delay']) this.broadcast({type:'delay'})
		}.bind(this))

		if(this.args['-web']) this.getComposition(this.args['-web'])
	}

	self.COMP_DIR = 'compositions'

	self.broadcast = function(msg){
		this.busserver.broadcast(msg)
		for(var k in this.compositions){
			this.compositions[k].busserver.broadcast(msg)
		}
	}

	self.default_composition = null

	self.getComposition = function(url){
		if(url.indexOf('.')!== -1) return
		var path = url.split('/')
		var name = path[1] || path[0] || this.default_composition
		if(!name) return

		// lets find the composition either in define.COMPOSITIONS
		if(!this.compositions[name]) this.compositions[name] = new CompositionServer(this.args, name, this)
		return this.compositions[name]
	}

	self.upgrade = function(req, sock, head){
		// lets connect the sockets to the app
		var sock = new NodeWebSocket(req, sock, head)
		sock.url = req.url
		var composition = this.getComposition(req.url)
		if(!composition) this.busserver.addWebSocket(sock)
		else composition.busserver.addWebSocket(sock)
	}

	self.request = function(req, res){
		// lets delegate to
		var host = req.headers.host
		var requrl = req.url
		var composition = this.getComposition(requrl)

		// if we are a composition request, send it to composition
		if(composition) return composition.request(req, res)

		// otherwise handle as static file
		if(requrl.indexOf('/proxy?') == 0){
			// lets connect a http request and forward it back!
			var tgt_url = url.parse(decodeURIComponent(requrl.slice(7)))
			var proxy_req = http.request({
				hostname: tgt_url.hostname,
				path: tgt_url.path + tgt_url.search,
				headers: {
					accept: req.headers.accept,
					'user-agent': req.headers['user-agent'],
					'accept-encoding': req.headers['accept-encoding'],
					'accept-language': req.headers['accept-language']
				}
			}, function(proxy_res){
				res.writeHead(proxy_res.statusCode, proxy_res.headers)
				proxy_res.pipe(res)
			})

			proxy_req.end()
			return
		}

		if(requrl.indexOf('_extlib_') != -1){
			var file = requrl.replace(/\_extlib\_/, define.expandVariables(define.$extlib))
		}
		else{
			var idx = requrl.indexOf('?')
			if(idx !== -1) requrl = requrl.slice(0, idx)
			var file = path.join(define.expandVariables(define.$root), requrl)
		}

		fs.stat(file, function(err, stat){
			if(err || !stat.isFile()){
				if(url =='/favicon.ico'){
					res.writeHead(200)
					res.end()
					return
				}
				res.writeHead(404)
				res.end()
				console.color('~br~Error~y~ ' + file + '~~ File not found, returning 403\n')
				return
			}

			var header = {
				"Cache-control":"max-age=0",
				"Content-Type": mimeFromFile(file),
				"ETag": stat.mtime.getTime() + '_' + stat.ctime.getTime() + '_' + stat.size
			}

			this.watcher.watch(file)

			if( req.headers['if-none-match'] == header.ETag){
				res.writeHead(304,header)
				res.end()
				return
			}

			var stream = fs.createReadStream(file)
			res.writeHead(200, header)
			stream.pipe(res)
			// ok so we get a filechange right?

		}.bind(this))
	}
})<commit_msg>windows path fix for partial reloader<commit_after>// Copyright 2015 Teem2 LLC, MIT License (see LICENSE)
// Teem server

define.class(function(require, exports, self){

	var http = require('http')
	var os = require('os')
	var path = require('path')
	var fs = require('fs')
	var url = require('url')

	var FileWatcher = require('$server/filewatcher')
	var ExternalApps = require('$server/externalapps')
	var BusServer = require('$rpc/busserver')
	var CompositionServer = require('$dreem/compositionserver')
	var NodeWebSocket = require('$server/nodewebsocket')
	var mimeFromFile = require('$server/mimefromfile')

	// Doccumentation
	self.atConstructor = function(args){
		this.compositions = {}

		this.args = args
		var port = this.args['-port'] || 8080
		var iface = this.args['-iface'] || '0.0.0.0'

		this.server = http.createServer(this.request.bind(this))
		this.server.listen(port, iface)
		this.server.on('upgrade', this.upgrade.bind(this))

		if(iface == '0.0.0.0'){
			var ifaces = os.networkInterfaces()
			var txt = ''
			Object.keys(ifaces).forEach(function(ifname){
				var alias = 0;
				ifaces[ifname].forEach(function(iface){
					if ('IPv4' !== iface.family) return
					var addr = 'http://' + iface.address + ':' + port + '/'
					if(!this.address) this.address = addr
					txt += ' ~~on ~c~'+addr
				}.bind(this))
			}.bind(this))
			console.color('Server running' + txt + '~~ Ready to go!\n')
		}
		else {
			this.address = 'http://' + iface + ':' + port + '/'
			console.color('Server running on ~c~' + this.address + "~~\n")
		}
		// use the browser spawner
		var browser = this.args['-browser']
		if(browser && (!this.args['-delay'] || this.args['-count'] ==0 )){
			ExternalApps.browser(this.address + (browser===true?'':browser), this.args['-devtools'])
		}

		this.watcher = new FileWatcher()
		this.watcher.atChange = function(file){
			if(!args['-nodreem'] && file.indexOf('dreem.js') !== -1){
				return this.broadcast({type:'delay'})
			}
			file = file.slice(define.expandVariables(define.$root).length).replace(/\\/g, "/")
			// ok lets rip off our
			this.broadcast({
				type:'filechange',
				file: file
			})
		}.bind(this)

		this.busserver = new BusServer()

		process.on('SIGHUP', function(){
			if(this.args['-close']) this.broadcast({type:'close'})
			if(this.args['-delay']) this.broadcast({type:'delay'})
		}.bind(this))

		if(this.args['-web']) this.getComposition(this.args['-web'])
	}

	self.COMP_DIR = 'compositions'

	self.broadcast = function(msg){
		this.busserver.broadcast(msg)
		for(var k in this.compositions){
			this.compositions[k].busserver.broadcast(msg)
		}
	}

	self.default_composition = null

	self.getComposition = function(url){
		if(url.indexOf('.')!== -1) return
		var path = url.split('/')
		var name = path[1] || path[0] || this.default_composition
		if(!name) return

		// lets find the composition either in define.COMPOSITIONS
		if(!this.compositions[name]) this.compositions[name] = new CompositionServer(this.args, name, this)
		return this.compositions[name]
	}

	self.upgrade = function(req, sock, head){
		// lets connect the sockets to the app
		var sock = new NodeWebSocket(req, sock, head)
		sock.url = req.url
		var composition = this.getComposition(req.url)
		if(!composition) this.busserver.addWebSocket(sock)
		else composition.busserver.addWebSocket(sock)
	}

	self.request = function(req, res){
		// lets delegate to
		var host = req.headers.host
		var requrl = req.url
		var composition = this.getComposition(requrl)

		// if we are a composition request, send it to composition
		if(composition) return composition.request(req, res)

		// otherwise handle as static file
		if(requrl.indexOf('/proxy?') == 0){
			// lets connect a http request and forward it back!
			var tgt_url = url.parse(decodeURIComponent(requrl.slice(7)))
			var proxy_req = http.request({
				hostname: tgt_url.hostname,
				path: tgt_url.path + tgt_url.search,
				headers: {
					accept: req.headers.accept,
					'user-agent': req.headers['user-agent'],
					'accept-encoding': req.headers['accept-encoding'],
					'accept-language': req.headers['accept-language']
				}
			}, function(proxy_res){
				res.writeHead(proxy_res.statusCode, proxy_res.headers)
				proxy_res.pipe(res)
			})

			proxy_req.end()
			return
		}

		if(requrl.indexOf('_extlib_') != -1){
			var file = requrl.replace(/\_extlib\_/, define.expandVariables(define.$extlib))
		}
		else{
			var idx = requrl.indexOf('?')
			if(idx !== -1) requrl = requrl.slice(0, idx)
			var file = path.join(define.expandVariables(define.$root), requrl)
		}

		fs.stat(file, function(err, stat){
			if(err || !stat.isFile()){
				if(url =='/favicon.ico'){
					res.writeHead(200)
					res.end()
					return
				}
				res.writeHead(404)
				res.end()
				console.color('~br~Error~y~ ' + file + '~~ File not found, returning 403\n')
				return
			}

			var header = {
				"Cache-control":"max-age=0",
				"Content-Type": mimeFromFile(file),
				"ETag": stat.mtime.getTime() + '_' + stat.ctime.getTime() + '_' + stat.size
			}

			this.watcher.watch(file)

			if( req.headers['if-none-match'] == header.ETag){
				res.writeHead(304,header)
				res.end()
				return
			}

			var stream = fs.createReadStream(file)
			res.writeHead(200, header)
			stream.pipe(res)
			// ok so we get a filechange right?

		}.bind(this))
	}
})<|endoftext|>


<commit_before>/*! art-template@runtime | https://github.com/aui/art-template */

// const detectNode = require('detect-node');
// const runtime = Object.create(detectNode ? global : window);
var globalThis = typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};

var runtime = Object.create(globalThis);
var ESCAPE_REG = /["&'<>]/;

/**
 * 编码模板输出的内容
 * @param  {any}        content
 * @return {string}
 */
runtime.$escape = content => xmlEscape(toString(content));

/**
 * 迭代器，支持数组与对象
 * @param {array|Object} data
 * @param {function}     callback
 */
runtime.$each = (data, callback) => {
    if (Array.isArray(data)) {
        for (let i = 0, len = data.length; i < len; i++) {
            callback(data[i], i);
        }
    } else {
        for (let i in data) {
            callback(data[i], i);
        }
    }
};

// 将目标转成字符
function toString(value) {
    if (typeof value !== 'string') {
        if (value === undefined || value === null) {
            value = '';
        } else if (typeof value === 'function') {
            value = toString(value.call(value));
        } else {
            value = JSON.stringify(value);
        }
    }

    return value;
}

// 编码 HTML 内容
function xmlEscape(content) {
    const html = '' + content;
    const regexResult = ESCAPE_REG.exec(html);
    if (!regexResult) {
        return content;
    }

    let result = '';
    let i, lastIndex, char;
    for (i = regexResult.index, lastIndex = 0; i < html.length; i++) {
        switch (html.charCodeAt(i)) {
            case 34:
                char = '"';
                break;
            case 38:
                char = '&';
                break;
            case 39:
                char = ''';
                break;
            case 60:
                char = '<';
                break;
            case 62:
                char = '>';
                break;
            default:
                continue;
        }

        if (lastIndex !== i) {
            result += html.substring(lastIndex, i);
        }

        lastIndex = i + 1;
        result += char;
    }

    if (lastIndex !== i) {
        return result + html.substring(lastIndex, i);
    } else {
        return result;
    }
}

module.exports = runtime;
<commit_msg>chore: styling<commit_after>/*! art-template@runtime | https://github.com/aui/art-template */

var globalThis = typeof self !== 'undefined' ? self
    : typeof window !== 'undefined' ? window
    : typeof global !== 'undefined' ? global : {};

var runtime = Object.create(globalThis);
var ESCAPE_REG = /["&'<>]/;

/**
 * 编码模板输出的内容
 * @param  {any}        content
 * @return {string}
 */
runtime.$escape = content => xmlEscape(toString(content));

/**
 * 迭代器，支持数组与对象
 * @param {array|Object} data
 * @param {function}     callback
 */
runtime.$each = (data, callback) => {
    if (Array.isArray(data)) {
        for (let i = 0, len = data.length; i < len; i++) {
            callback(data[i], i);
        }
    } else {
        for (let i in data) {
            callback(data[i], i);
        }
    }
};

// 将目标转成字符
function toString(value) {
    if (typeof value !== 'string') {
        if (value === undefined || value === null) {
            value = '';
        } else if (typeof value === 'function') {
            value = toString(value.call(value));
        } else {
            value = JSON.stringify(value);
        }
    }

    return value;
}

// 编码 HTML 内容
function xmlEscape(content) {
    const html = '' + content;
    const regexResult = ESCAPE_REG.exec(html);
    if (!regexResult) {
        return content;
    }

    let result = '';
    let i, lastIndex, char;
    for (i = regexResult.index, lastIndex = 0; i < html.length; i++) {
        switch (html.charCodeAt(i)) {
            case 34:
                char = '"';
                break;
            case 38:
                char = '&';
                break;
            case 39:
                char = ''';
                break;
            case 60:
                char = '<';
                break;
            case 62:
                char = '>';
                break;
            default:
                continue;
        }

        if (lastIndex !== i) {
            result += html.substring(lastIndex, i);
        }

        lastIndex = i + 1;
        result += char;
    }

    if (lastIndex !== i) {
        return result + html.substring(lastIndex, i);
    } else {
        return result;
    }
}

module.exports = runtime;
<|endoftext|>


<commit_before>import { openModal, closeModal } from '../modal';
import { MODAL } from '../../consts/types';
import createMockStore from './utils/create-mock-store' ;

describe('[Action] modal', () => {
  describe('openModal', () => {
    it('should dispatch the proper action', () => {
      const mockStore = createMockStore();
      const store = mockStore({});

      const expected = {
        type: MODAL.OPEN,
        item: {
          type: 'rant',
          id: 1,
          data: {
            test: 'test',
          },
        },
      };

      store.dispatch(openModal('rant', 1, { test: 'test' }));
      expect(store.getActions()).toEqual([expected]);
    });
  });
});
<commit_msg>test(actions): finish modal action test<commit_after>import { openModal, closeModal } from '../modal';
import { MODAL } from '../../consts/types';
import createMockStore from './utils/create-mock-store' ;

describe('[Action] modal', () => {
  describe('openModal', () => {
    it('should dispatch the proper action', () => {
      const mockStore = createMockStore();
      const store = mockStore({});

      const expected = {
        type: MODAL.OPEN,
        item: {
          type: 'rant',
          id: 1,
          data: {
            test: 'test',
          },
        },
      };

      store.dispatch(openModal('rant', 1, { test: 'test' }));
      expect(store.getActions()).toEqual([expected]);
    });
  });
  describe('closeModal', () => {
    it('should dispatch the proper action', () => {
      const mockStore = createMockStore();
      const store = mockStore({});

      const expected = {
        type: MODAL.CLOSE,
        item: null,
      };

      store.dispatch(closeModal());
      expect(store.getActions()).toEqual([expected]);
    });
  });
});
<|endoftext|>


<commit_before>import React from 'react';

import {shallow, mount, render} from 'enzyme';
import {expect} from 'chai';
import sinon from 'sinon';

import Simple, {Block} from './simple';
import {Emitter, Receiver} from '../index';

describe('Simple', () => {
  it('should have 6 blocks', () => {
    const wrapper = mount(<Simple />);
    expect(wrapper.find(Block)).to.have.length(6);
  });
});

describe('Emitter and Receiver', () => {
  it('should update children', () => {
    const Block = () =>

    const receiver = mount(<Receiver />)
    function expectToFindBlocks(receiver, count) {
      expect(receiver.find(Block)).to.have.length(count)
    }
    expectToFindBlocks(receiver, 0)
    const emitter = mount(<Emitter />)
    expectToFindBlocks(receiver, 0)
    emitter.setProps({children: [<Block key={1}/>]})
    expectToFindBlocks(receiver, 1)
    const receiver2 = mount(<Receiver />)
    expectToFindBlocks(receiver2, 1)
    const emitter2 = mount(<Emitter><Block /></Emitter>)
    expectToFindBlocks(receiver, 2)
    expectToFindBlocks(receiver2, 2)
    emitter2.unmount()
    expectToFindBlocks(receiver, 1)
  })
})
<commit_msg>test text children<commit_after>import React from 'react';

import {shallow, mount, render} from 'enzyme';
import {expect} from 'chai';
import sinon from 'sinon';

import Simple, {Block} from './simple';
import {Emitter, Receiver} from '../index';

describe('Simple', () => {
  it('should have 6 blocks', () => {
    const wrapper = mount(<Simple />);
    expect(wrapper.find(Block)).to.have.length(6);
  });
});

describe('Emitter and Receiver', () => {
  it('should update children', () => {
    const Block = () =>

    const receiver = mount(<Receiver />)
    function expectToFindBlocks(receiver, count) {
      expect(receiver.find(Block)).to.have.length(count)
    }
    expectToFindBlocks(receiver, 0)
    const emitter = mount(<Emitter />)
    expectToFindBlocks(receiver, 0)
    emitter.setProps({children: [<Block key={1}/>]})
    expectToFindBlocks(receiver, 1)
    const receiver2 = mount(<Receiver />)
    expectToFindBlocks(receiver2, 1)
    const emitter2 = mount(<Emitter><Block /></Emitter>)
    expectToFindBlocks(receiver, 2)
    expectToFindBlocks(receiver2, 2)
    emitter2.unmount()
    expectToFindBlocks(receiver, 1)
  })

  it('should render text children', () => {
    const receiver = mount(<Receiver />)
    const emitter = mount(<Emitter>Hello World!</Emitter>)
    expect(receiver.text()).to.equal('Hello World!')
  })
})
<|endoftext|>


<commit_before>import { CALL_API } from 'redux-api-middleware'

import config from '../app/config.js'

//
//  actions types
//

export const GET_BUS_STOPS_AROUND_ME_REQUEST  = 'GET_BUS_STOPS_AROUND_ME_REQUEST'
export const GET_BUS_STOPS_AROUND_ME_SUCCESS  = 'GET_BUS_STOPS_AROUND_ME_SUCCESS'
export const GET_BUS_STOPS_AROUND_ME_ERROR    = 'GET_BUS_STOPS_AROUND_ME_ERROR'
export const SET_METERS_AROUND_ME             = 'SET_METERS_AROUND_ME'
export const SET_COORDS_AROUND_ME             = 'SET_COORDS_AROUND_ME'

//
//  actions creators
//

export function setMetersAroundMe( meters ) {
  return {
    type: SET_METERS_AROUND_ME,
    meters: meters
  };
}

export function setCoordsAroundMe( coords ) {
  return {
    type: SET_COORDS_AROUND_ME,
    coords: coords
  };
}

/*export function getBusStopsAroundMe( coords, meters ) {
  return {
    type: GET_BUS_STOPS_AROUND_ME,
    meters: meters,
    coords: coords
  };
}*/

export function getBusStopsAroundMe( coords, meters ) {
  console.log('get bus stops around me middleware dispatch');
  console.log('enpoint: ' + config.api.protocol + config.api.domain + '/' + config.api.endpoints.busStops +
                '?lt=' + coords.latitude + '&ln=' + coords.longitude + '&r=' + meters );
  return {
    [CALL_API]: {
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      method: 'GET',
      types: ['GET_BUS_STOPS_AROUND_ME_REQUEST', 'GET_BUS_STOPS_AROUND_ME_SUCCESS', 'GET_BUS_STOPS_AROUND_ME_FAILURE'],
      endpoint: config.api.protocol + config.api.domain + '/' + config.api.endpoints.busStops +
                '?lt=' + coords.latitude + '&ln=' + coords.longitude + '&r=' + meters
    }
  }
}

<commit_msg>create new actions to redux and actions to redux-thunk<commit_after>//
//  actions types
//

export const GET_BUS_STOPS_AROUND_ME_ERROR      = 'GET_BUS_STOPS_AROUND_ME_ERROR'
export const GET_BUS_STOPS_AROUND_ME_SUCCESS    = 'GET_BUS_STOPS_AROUND_ME_SUCCESS'
export const SET_METERS_AROUND_ME               = 'SET_METERS_AROUND_ME'
export const SET_COORDS_AROUND_ME               = 'SET_COORDS_AROUND_ME'
export const SET_LOADING_STATE                  = 'SET_LOADING_STATE'

//
//  actions creators
//

export const setloading = ( state ) => {
  return {
    type: SET_LOADING_STATE,
    state: state
  };
}

export const setMetersAroundMe = ( meters ) => {
  return {
    type: SET_METERS_AROUND_ME,
    meters: meters
  };
}

export const setCoordsAroundMe = ( coords ) => {
  return {
    type: SET_COORDS_AROUND_ME,
    coords: coords
  };
}

//
//  actions api
//

export const getBusStopsSucces = ( response ) => {
  return {
    type: GET_BUS_STOPS_AROUND_ME_SUCCESS,
    busStopsAroundMe: response
  };
}

export const getBusStopsError = ( error ) => {
  return {
    type: GET_BUS_STOPS_AROUND_ME_ERROR,
    error: error
  };
}
<|endoftext|>


<commit_before>const ADD_TABLE_ROW = "ADD_TABLE_ROW"
const TOGGLE_EDIT_TABLE_ROW = "TOGGLE_EDIT_TABLE_ROW"
const SAVE_TABLE_ROW = "SAVE_TABLE_ROW"
const START_TIMER = "START_TIMER"
const STOP_TIMER = "STOP_TIMER"
const RESET_TIMER = "RESET_TIMER"
const CREATE_TIMER = "CREATE_TIMER"
const UPDATE_TIMER = "UPDATE_TIMER"

export const addTableRow = (tableRow) => {
  return {
    type: ADD_TABLE_ROW,
    tableRow
  }
}

export const toggleTableRowEditing = (id) => {
  return {
    type: TOGGLE_EDIT_TABLE_ROW,
    id
  }
}

export const saveTableRow = (cells) => {
  return {
    type: SAVE_TABLE_ROW,
    cells
  }
}

export const createTimer = (minutes) => {
  return {
    type: CREATE_TIMER,
    minutes
  }
}

export const startTimer = (time) => {
  return {
    type: START_TIMER,
    time
  }
}

export const stopTimer = () => {
  return{
    type: STOP_TIMER
  }
}

export const resetTimer = () => {
  return {
    type: RESET_TIMER
  }
}

export const updateTimer = (time) => {
  return {
    type: UPDATE_TIMER,
    time
  }
}

/*
  Timer object:
  {
    minutes: integer,
    seconds: integer,
    active: bool,
    initialMinutes: integer,
    initialSeconds: integer
  }
*/<commit_msg>add sync actions for remote timer<commit_after>const ADD_TABLE_ROW = "ADD_TABLE_ROW"
const TOGGLE_EDIT_TABLE_ROW = "TOGGLE_EDIT_TABLE_ROW"
const SAVE_TABLE_ROW = "SAVE_TABLE_ROW"
const START_TIMER = "START_TIMER"
const STOP_TIMER = "STOP_TIMER"
const RESET_TIMER = "RESET_TIMER"
const CREATE_TIMER = "CREATE_TIMER"
const UPDATE_TIMER = "UPDATE_TIMER"
const CREATE_REMOTE_TIMER = "CREATE_REMOTE_TIMER"
const UPDATE_REMOTE_TIMER = "UPDATE_REMOTE_TIMER"

export const addTableRow = tableRow => {
  return {
    type: ADD_TABLE_ROW,
    tableRow
  }
}

export const toggleTableRowEditing = id => {
  return {
    type: TOGGLE_EDIT_TABLE_ROW,
    id
  }
}

export const saveTableRow = cells => {
  return {
    type: SAVE_TABLE_ROW,
    cells
  }
}

export const createTimer = minutes => {
  return {
    type: CREATE_TIMER,
    minutes
  }
}

export const startTimer = time => {
  return {
    type: START_TIMER,
    time
  }
}

export const stopTimer = () => {
  return{
    type: STOP_TIMER
  }
}

export const resetTimer = () => {
  return {
    type: RESET_TIMER
  }
}

export const updateTimer = time => {
  return {
    type: UPDATE_TIMER,
    time
  }
}

export const createRemoteTimer = timer => {
  return {
    type: CREATE_REMOTE_TIMER,
    timer
  }
}

export const updateRemoteTimer = timer => {
  return {
    type: UPDATE_REMOTE_TIMER,
    timer
  }
}

/*
  Timer object:
  {
    minutes: integer,
    seconds: integer,
    active: bool,
    initialMinutes: integer,
    initialSeconds: integer
  }
*/<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import { UUID } from '../constants/config';

export const RECIEVE_LEAGUES = 'RECIEVE_LEAGUES';
export const RECIEVE_LEAGUE_TABLE = 'RECIEVE_LEAGUE_TABLE';
const leagues_endpoint = 'http://api.football-data.org/v1/soccerseasons/';

export function receiveLeagues(leagues = {}) {
  return {
    type: RECIEVE_LEAGUES,
    leagues: leagues
  };
}

export function receiveLeagueTable(leagues = {}) {
  return {
    type: RECIEVE_LEAGUE_TABLE,
    leagues: leagues
  };
}

export function fetchLeagues() {
  return dispatch => {
    return fetch(leagues_endpoint, { headers: { 'X-Auth-Token': UUID } })
      .then(response => response.json())
      .then(json => dispatch(receiveLeagues(json)));
  };
}

export function fetchLeagueTable(id) {
  return dispatch => {
    let endpoint = leagues_endpoint + id + '/leagueTable';
    return fetch(endpoint, { headers: { 'X-Auth-Token': UUID } })
      .then(response => response.json())
      .then(json => dispatch(receiveLeagueTable(json)));
  };
}
<commit_msg>Refactoring leagues action to be more dynamic<commit_after>import fetch from 'isomorphic-fetch';
import { UUID } from '../constants/config';

export const RECIEVE_LEAGUES = 'RECIEVE_LEAGUES';
export const RECIEVE_LEAGUE_TABLE = 'RECIEVE_LEAGUE_TABLE';
const leagues_endpoint = 'http://api.football-data.org/v1/soccerseasons/';

export function receiveLeagues(leagues = {}) {
  return {
    type: RECIEVE_LEAGUES,
    leagues: leagues
  };
}

export function receiveLeagueTable(leagues = {}) {
  return {
    type: RECIEVE_LEAGUE_TABLE,
    leagues: leagues
  };
}

export function fetchLeagues(id = '') {
  return dispatch => {
    return fetch(leagues_endpoint + id, { headers: { 'X-Auth-Token': UUID } })
      .then(response => response.json())
      .then(json => dispatch(receiveLeagues(json)));
  };
}

export function fetchLeagueTable(id) {
  return dispatch => {
    let endpoint = leagues_endpoint + id + '/leagueTable';
    return fetch(endpoint, { headers: { 'X-Auth-Token': UUID } })
      .then(response => response.json())
      .then(json => dispatch(receiveLeagueTable(json)));
  };
}
<|endoftext|>


<commit_before>import { _, t, os, Q, async, log, lazy_require } from 'azk';
import { config, set_config } from 'azk';
import { UIProxy } from 'azk/cli/ui';
import { OSNotSupported, DependencyError } from 'azk/utils/errors';
import { net } from 'azk/utils';
import Azk from 'azk';

var which      = require('which');   // Search for command in path
var qfs        = require('q-io/fs');
var request    = require('request');
var semver     = require('semver');
var { isIPv4 } = require('net');

lazy_require(this, {
  docker  : ['azk/docker', 'default'],
  exec    : ['child_process'],
  isOnline: 'is-online',
});

var ports_tabs = {
  linux : ":",
  darwin: ".",
};

export class Configure extends UIProxy {
  constructor(user_interface) {
    super(user_interface);
    this.dns_tab   = ports_tabs[os.platform()];
    this.docker_ip = null;
  }

  // Run configures and checks by operational system
  run() {
    var method = this[os.platform()];
    if (method) {
      return method.apply(this);
    } else {
      throw new OSNotSupported(os.platform());
    }
  }

  // Mac OS X configure and checks
  // TODO: Check dependencies versions
  darwin() {
    return this._checksForRequiresVm();
  }

  // Linux configure and checks
  linux() {
    if (config('agent:requires_vm')) {
      return this._checksForRequiresVm();
    } else {
      var socket = config('docker:socket');
      return async(this, function* () {
        return _.merge(
          {},
          yield this._checkAzkVersion(),
          yield this._checkDockerSocket(socket),
          yield this._checkAndConfigureNetwork(false),
          yield this._loadDnsServers(),
          yield this._cleanContainers(),
          yield this._checkPorts('agent:balancer:port', 'balancer', 'AZK_BALANCER_PORT'),
          yield this._checkPorts('agent:dns:port', 'dns', 'AZK_DNS_PORT')
        );
      })
      .fail((err) => {
        if (!err instanceof DependencyError)
          err = new DependencyError('docker_access', { socket });

        throw err;
      });
    }
  }

  _checksForRequiresVm() {
    return async(this, function* () {
      return _.merge(
        {},
        yield this._checkAzkVersion(),
        yield this._which('VBoxManage'),
        yield this._which('unfsd', 'paths:unfsd'),
        yield this._checkAndConfigureNetwork(),
        yield this._checkAndGenerateSSHKeys(),
        yield this._loadDnsServers()
      );
    });
  }

  _checkAzkVersion() {
    return async(this, function* (notify) {
      try {
        // check connectivity
        var currentOnline = yield Q.ninvoke(isOnline);

        if ( !currentOnline ) {
          log.debug('isOnline == false');
          return {}; //can't check version
        }

        // get AZK version from Github API
        var options = {
          headers: { 'User-Agent': 'request' },
          json: true,
        }

        notify({ type: "status", keys: "configure.check_version"});
        var [response, body] = yield Q.ninvoke(request, 'get', config('urls:github:api:tags_url'), options);

        var tagName = body[0].name;
        var parsedVersion = semver.clean(tagName);
        var newAzkVersionExists = semver.lt(parsedVersion, Azk.version);
        if ( newAzkVersionExists ) {
          // just warn user that new AZK version is available
          this.warning('errors.dependencies.*.upgrade', {
            current_version: Azk.version,
            new_version: parsedVersion
          });
        } else {
          log.debug('AZK version `v'+ parsedVersion +'` is up to date.');
        }
      } catch (err) {
        notify({
          type: "status",
          status: "error",
          data: new Error(t("configure.check_version_error", {
            error_message: err.message
          })),
        });
      }

      return {};
    });
  }

  _cleanContainers() {
    return docker
      .azkListContainers()
      .then((containers) => {
        this.warning('configure.clean_containers', { count: containers.length });
        var removes = _.map(containers, (container) => {
          return docker
            .getContainer(container.Id)
            .remove({ force: true });
        });
        return Q
          .all(removes)
          .then(() => { return {} });
      });
  }

  _checkDockerSocket(socket) {
    var host   = `unix://${socket}`;
    set_config('docker:host', host);

    return docker.info()
      .then((info) => {
        return { 'docker:host': host };
      });
  }

  _checkPorts(confKey, service, env) {
    var port = config(confKey);
    return net
      .checkPort(port, this.docker_ip)
      .then((avaibly) => {
        if (!avaibly)
          throw new DependencyError('port_error', { port, service, env });
      });
  }

  _which(command, save_key = null) {
    return Q.nfcall(which, command)
      .then((path) => {
        if (save_key) return { [save_key]: path };
      })
      .fail(() => {
        throw new DependencyError(command);
      });
  }

  // Check for ssh keys, used for connection vm
  _checkAndGenerateSSHKeys() {
    var file = config('agent:vm:ssh_key');
    return qfs.exists(file).then((exist) => {
      if (!exist) {
        this.info('configure.generating_key');
        var script = `
          set -x;
          ssh-keygen -t rsa -f ${file} -N ''; result=$?;
          set +x;
          echo "";
          exit $result;
        `;
        return this.execSh(script).then((code) => {
          if (code != 0) {
            throw new DependencyError('ssh_keygen');
          } else {
            return code;
          }
        });
      }
    });
  }

  // Check vm ip is configurat
  _checkAndConfigureNetwork(use_vm = true) {
    return async(this, function* () {
      var file   = config('agent:balancer:file_dns');
      var exist  = yield qfs.exists(file);
      var ip     = null;
      var result = {};

      // File exist? Get content
      if (exist) {
        var content = yield qfs.read(file);
        ip = this._parseNameserver(content)[0];
      }

      // Not exist or invalid content
      if (_.isEmpty(ip)) {
        if (use_vm) {
          this.warning('configure.vm_ip_msg');
          ip = yield this._getNetworkIp();
        } else {
          ip = yield this._getDockerIp();
        }
        yield this._generateResolverFile(ip, file);
      }

      if (use_vm) {
        result['docker:host'] = `http://${ip}:2375`;
      }

      // Save to use in configure
      this.docker_ip = ip;

      // Save configuration
      return _.merge({
        ['agent:vm:ip']      : ip,
        ['agent:dns:ip']     : ip,
        ['agent:balancer:ip']: ip,
      }, result);
    });
  }

  // Generate file /etc/resolver/*
  _generateResolverFile(ip, file) {
    var port = config('agent:dns:port');

    // Creating resolver file and adding ip (with sudo)
    this.info('configure.adding_ip', { ip, file });
    ip = `${ip}${this.dns_tab}${port}`;
    var script = `
      echo "";
      set -x;
      sudo mkdir -p /etc/resolver 2>/dev/null;
      echo "# azk agent configure" | sudo tee ${file};
      echo "nameserver ${ip}" | sudo tee -a ${file};
      sudo chown \$(id -u):\$(id -g) ${file};
      set +x;
      echo "";
    `;

    // Call interactive shell (to support sudo)
    return this.execSh(script).then((code) => {
      if (code != 0) {
        throw new DependencyError('network');
      } else {
        return code;
      }
    });
  }

  _parseNameserver(content) {
    var lines   = content.split('\n');
    var regex   = /^\s*nameserver\s{1,}((?:[0-9]{1,3}\.){3}[0-9]{1,3})/;
    var capture = null;
    return _.reduce(lines, (nameservers, line) => {
      if (capture = line.match(regex)) {
        var ip = capture[1];
        if (isIPv4(ip)) nameservers.push(ip);
      }
      return nameservers;
    }, []);
  }

  // TODO: improve to get a free network ip ranges
  // TODO: filter others /etc/resolver/* azk files
  _getNetworkIp() {
    var question = {
      name    : 'ip',
      message : 'configure.ip_question',
      default : config('agent:vm:ip'),
      validate: (value) => {
        var data       = { ip: value };
        var of_range   = this.t('configure.ip_of_range', data);
        var ip_invalid = this.t('configure.ip_invalid', data);
        var ranges     = [ '127.0.0.1', '0.0.0.0' ];

        // Check is valid ip
        if (!isIPv4(value)) { return ip_invalid; }
        if (_.contains(ranges, value)) { return of_range; }

        return true;
      }
    };

    return this.prompt(question)
      .then((answers) => {
        return answers.ip;
      });
  }

  _getDockerIp() {
    var cmd   = "/sbin/ifconfig docker0";
    var regex = /inet\s(?:addr:){0,1}(.*?)\s.*(?:Mask|netmask)/m;

    return Q.nfcall(exec, cmd)
      .spread((stdout) => {
        var match = stdout.match(regex);
        if (match) { return match[1]; }
        throw new Error('Get ip from docker0 interface');
      });
  }

  _loadDnsServers() {
    return async(this, function* () {
      var cf_key = 'agent:dns:nameservers';
      var nameservers = this._filderDnsServers(config(cf_key));

      if (_.isEmpty(nameservers)) {
        nameservers = this._filderDnsServers(yield this._readResolverFile());
      }

      if (_.isEmpty(nameservers)) {
        nameservers = config('agent:dns:defaultserver');
      }

      return { [cf_key]: nameservers };
    });
  }

  _filderDnsServers(nameservers) {
    return _.filter(nameservers, (server) => { return !server.match(/^127\./) });
  }

  _readResolverFile() {
    var file = "/etc/resolv.conf";
    return qfs.read(file).then(this._parseNameserver);
  }
}
<commit_msg>Fixing azk version check on agent start<commit_after>import { _, t, os, Q, async, log, lazy_require } from 'azk';
import { config, set_config } from 'azk';
import { UIProxy } from 'azk/cli/ui';
import { OSNotSupported, DependencyError } from 'azk/utils/errors';
import { net } from 'azk/utils';
import Azk from 'azk';

var which      = require('which');   // Search for command in path
var qfs        = require('q-io/fs');
var request    = require('request');
var semver     = require('semver');
var { isIPv4 } = require('net');

lazy_require(this, {
  docker  : ['azk/docker', 'default'],
  exec    : ['child_process'],
  isOnline: 'is-online',
});

var ports_tabs = {
  linux : ":",
  darwin: ".",
};

export class Configure extends UIProxy {
  constructor(user_interface) {
    super(user_interface);
    this.dns_tab   = ports_tabs[os.platform()];
    this.docker_ip = null;
  }

  // Run configures and checks by operational system
  run() {
    var method = this[os.platform()];
    if (method) {
      return method.apply(this);
    } else {
      throw new OSNotSupported(os.platform());
    }
  }

  // Mac OS X configure and checks
  // TODO: Check dependencies versions
  darwin() {
    return this._checksForRequiresVm();
  }

  // Linux configure and checks
  linux() {
    if (config('agent:requires_vm')) {
      return this._checksForRequiresVm();
    } else {
      var socket = config('docker:socket');
      return async(this, function* () {
        return _.merge(
          {},
          yield this._checkAzkVersion(),
          yield this._checkDockerSocket(socket),
          yield this._checkAndConfigureNetwork(false),
          yield this._loadDnsServers(),
          yield this._cleanContainers(),
          yield this._checkPorts('agent:balancer:port', 'balancer', 'AZK_BALANCER_PORT'),
          yield this._checkPorts('agent:dns:port', 'dns', 'AZK_DNS_PORT')
        );
      })
      .fail((err) => {
        if (!err instanceof DependencyError)
          err = new DependencyError('docker_access', { socket });

        throw err;
      });
    }
  }

  _checksForRequiresVm() {
    return async(this, function* () {
      return _.merge(
        {},
        yield this._checkAzkVersion(),
        yield this._which('VBoxManage'),
        yield this._which('unfsd', 'paths:unfsd'),
        yield this._checkAndConfigureNetwork(),
        yield this._checkAndGenerateSSHKeys(),
        yield this._loadDnsServers()
      );
    });
  }

  _checkAzkVersion() {
    return async(this, function* (notify) {
      try {
        // check connectivity
        var currentOnline = yield Q.ninvoke(isOnline);

        if ( !currentOnline ) {
          log.debug('isOnline == false');
          return {}; //can't check version
        }

        // get AZK version from Github API
        var options = {
          headers: { 'User-Agent': 'request' },
          json: true,
        }

        notify({ type: "status", keys: "configure.check_version"});
        var [response, body] = yield Q.ninvoke(request, 'get', config('urls:github:api:tags_url'), options);

        var tagNameGithub = body[0].name;
        var tagNameGithubParsed = semver.clean(tagNameGithub);
        var newAzkVersionExists = semver.lt(Azk.version, tagNameGithubParsed);
        if ( newAzkVersionExists ) {
          // just warn user that new AZK version is available
          this.warning('errors.dependencies.*.upgrade', {
            current_version: Azk.version,
            new_version: tagNameGithubParsed
          });
        } else {
          log.debug('AZK version `v'+ tagNameGithubParsed +'` is up to date.');
        }
      } catch (err) {
        notify({
          type: "status",
          status: "error",
          data: new Error(t("configure.check_version_error", {
            error_message: err.message
          })),
        });
      }

      return {};
    });
  }

  _cleanContainers() {
    return docker
      .azkListContainers()
      .then((containers) => {
        this.warning('configure.clean_containers', { count: containers.length });
        var removes = _.map(containers, (container) => {
          return docker
            .getContainer(container.Id)
            .remove({ force: true });
        });
        return Q
          .all(removes)
          .then(() => { return {} });
      });
  }

  _checkDockerSocket(socket) {
    var host   = `unix://${socket}`;
    set_config('docker:host', host);

    return docker.info()
      .then((info) => {
        return { 'docker:host': host };
      });
  }

  _checkPorts(confKey, service, env) {
    var port = config(confKey);
    return net
      .checkPort(port, this.docker_ip)
      .then((avaibly) => {
        if (!avaibly)
          throw new DependencyError('port_error', { port, service, env });
      });
  }

  _which(command, save_key = null) {
    return Q.nfcall(which, command)
      .then((path) => {
        if (save_key) return { [save_key]: path };
      })
      .fail(() => {
        throw new DependencyError(command);
      });
  }

  // Check for ssh keys, used for connection vm
  _checkAndGenerateSSHKeys() {
    var file = config('agent:vm:ssh_key');
    return qfs.exists(file).then((exist) => {
      if (!exist) {
        this.info('configure.generating_key');
        var script = `
          set -x;
          ssh-keygen -t rsa -f ${file} -N ''; result=$?;
          set +x;
          echo "";
          exit $result;
        `;
        return this.execSh(script).then((code) => {
          if (code != 0) {
            throw new DependencyError('ssh_keygen');
          } else {
            return code;
          }
        });
      }
    });
  }

  // Check vm ip is configurat
  _checkAndConfigureNetwork(use_vm = true) {
    return async(this, function* () {
      var file   = config('agent:balancer:file_dns');
      var exist  = yield qfs.exists(file);
      var ip     = null;
      var result = {};

      // File exist? Get content
      if (exist) {
        var content = yield qfs.read(file);
        ip = this._parseNameserver(content)[0];
      }

      // Not exist or invalid content
      if (_.isEmpty(ip)) {
        if (use_vm) {
          this.warning('configure.vm_ip_msg');
          ip = yield this._getNetworkIp();
        } else {
          ip = yield this._getDockerIp();
        }
        yield this._generateResolverFile(ip, file);
      }

      if (use_vm) {
        result['docker:host'] = `http://${ip}:2375`;
      }

      // Save to use in configure
      this.docker_ip = ip;

      // Save configuration
      return _.merge({
        ['agent:vm:ip']      : ip,
        ['agent:dns:ip']     : ip,
        ['agent:balancer:ip']: ip,
      }, result);
    });
  }

  // Generate file /etc/resolver/*
  _generateResolverFile(ip, file) {
    var port = config('agent:dns:port');

    // Creating resolver file and adding ip (with sudo)
    this.info('configure.adding_ip', { ip, file });
    ip = `${ip}${this.dns_tab}${port}`;
    var script = `
      echo "";
      set -x;
      sudo mkdir -p /etc/resolver 2>/dev/null;
      echo "# azk agent configure" | sudo tee ${file};
      echo "nameserver ${ip}" | sudo tee -a ${file};
      sudo chown \$(id -u):\$(id -g) ${file};
      set +x;
      echo "";
    `;

    // Call interactive shell (to support sudo)
    return this.execSh(script).then((code) => {
      if (code != 0) {
        throw new DependencyError('network');
      } else {
        return code;
      }
    });
  }

  _parseNameserver(content) {
    var lines   = content.split('\n');
    var regex   = /^\s*nameserver\s{1,}((?:[0-9]{1,3}\.){3}[0-9]{1,3})/;
    var capture = null;
    return _.reduce(lines, (nameservers, line) => {
      if (capture = line.match(regex)) {
        var ip = capture[1];
        if (isIPv4(ip)) nameservers.push(ip);
      }
      return nameservers;
    }, []);
  }

  // TODO: improve to get a free network ip ranges
  // TODO: filter others /etc/resolver/* azk files
  _getNetworkIp() {
    var question = {
      name    : 'ip',
      message : 'configure.ip_question',
      default : config('agent:vm:ip'),
      validate: (value) => {
        var data       = { ip: value };
        var of_range   = this.t('configure.ip_of_range', data);
        var ip_invalid = this.t('configure.ip_invalid', data);
        var ranges     = [ '127.0.0.1', '0.0.0.0' ];

        // Check is valid ip
        if (!isIPv4(value)) { return ip_invalid; }
        if (_.contains(ranges, value)) { return of_range; }

        return true;
      }
    };

    return this.prompt(question)
      .then((answers) => {
        return answers.ip;
      });
  }

  _getDockerIp() {
    var cmd   = "/sbin/ifconfig docker0";
    var regex = /inet\s(?:addr:){0,1}(.*?)\s.*(?:Mask|netmask)/m;

    return Q.nfcall(exec, cmd)
      .spread((stdout) => {
        var match = stdout.match(regex);
        if (match) { return match[1]; }
        throw new Error('Get ip from docker0 interface');
      });
  }

  _loadDnsServers() {
    return async(this, function* () {
      var cf_key = 'agent:dns:nameservers';
      var nameservers = this._filderDnsServers(config(cf_key));

      if (_.isEmpty(nameservers)) {
        nameservers = this._filderDnsServers(yield this._readResolverFile());
      }

      if (_.isEmpty(nameservers)) {
        nameservers = config('agent:dns:defaultserver');
      }

      return { [cf_key]: nameservers };
    });
  }

  _filderDnsServers(nameservers) {
    return _.filter(nameservers, (server) => { return !server.match(/^127\./) });
  }

  _readResolverFile() {
    var file = "/etc/resolv.conf";
    return qfs.read(file).then(this._parseNameserver);
  }
}
<|endoftext|>


<commit_before>/*!
 * Copyright 2013-2014 Dennis Hörsch.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Mixes all given Objects or Functions (their protoype) together to one Object.
 * Methods in 'base objects' / traits can be marked as abstract vio mixin.abstract.
 * Use options.isCheckAbstractImplementations to enable
 */
var mixin = (function (options) {
	"use strict";

	var defaultOptions = {
			isCheckAbstractImplementations: false
		},

		map = function (args, fn) {
			return Array.prototype.map.call(args, fn);
		},

		asArray = function (args) {
			return Array.prototype.slice.call(args);
		},

		mergeInto = function (result, obj) {
			Object.keys(obj)
				.forEach(function (key) {
					result[key] = obj[key];
				});
			return result;
		},

		objOrPrototype = function (objOrClass) {
			return objOrClass.prototype ? objOrClass.prototype : objOrClass;
		},

		justMixin = function mixin() {
			return map(arguments, objOrPrototype)
				.reduce(mergeInto, {});
		},

		mixinWithAbstractMethodCheck = function mixinWithAbstractMethodCheck() {
			var result = justMixin.apply(null, asArray(arguments));

			Object.keys(result)
				.forEach(function (key) {
					if (result[key] === mixin.abstract) {
						throw Error("Method '" + key + "' needs to be overridden!");
					}
				});
			return result;
		},

		options_ = [defaultOptions, options].reduce(mergeInto, {}),

		mixin = options_.isCheckAbstractImplementations ?
		mixinWithAbstractMethodCheck :
		justMixin;

	/** Marks a method as abstract.
	 * This means it must be implemented at creation
	 * time (as prototype property).
	 */
	mixin.abstract = function () {
		throw new Error("Abstract method called!");
	};

	/** Marks a method as to be implemented, but possible
	 * at runtime, not creation time. */
	mixin.expectRuntimeImplementation = function () {
		throw new Error("Method not implemented!");
	};

	/** Placeholder for a hook method that might be overridden. */
	mixin.noop = function () {};

	return mixin;
}(mixinOptions));
<commit_msg>format<commit_after>/*!
 * Copyright 2013-2014 Dennis Hörsch.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Mixes all given Objects or Functions (their protoype) together to one Object.
 * Methods in 'base objects' / traits can be marked as abstract vio mixin.abstract.
 * Use options.isCheckAbstractImplementations to enable
 */
var mixin = (function (options) {
	"use strict";

	var defaultOptions = {
			isCheckAbstractImplementations: false
		},

		map = function (args, fn) {
			return Array.prototype.map.call(args, fn);
		},

		asArray = function (args) {
			return Array.prototype.slice.call(args);
		},

		mergeInto = function (result, obj) {
			Object.keys(obj).forEach(function (key) {
				result[key] = obj[key];
			});
			return result;
		},

		objOrPrototype = function (objOrClass) {
			return objOrClass.prototype ? objOrClass.prototype : objOrClass;
		},

		justMixin = function mixin() {
			return map(arguments, objOrPrototype).reduce(mergeInto, {});
		},

		mixinWithAbstractMethodCheck = function mixinWithAbstractMethodCheck() {
			var result = justMixin.apply(null, asArray(arguments));

			Object.keys(result).forEach(function (key) {
				if (result[key] === mixin.abstract) {
					throw Error("Method '" + key + "' needs to be overridden!");
				}
			});
			return result;
		},

		options_ = [defaultOptions, options].reduce(mergeInto, {}),

		mixin = options_.isCheckAbstractImplementations ? mixinWithAbstractMethodCheck : justMixin;

	/** Marks a method as abstract.
	 * This means it must be implemented at creation
	 * time (as prototype property).
	 */
	mixin.abstract = function () {
		throw new Error("Abstract method called!");
	};

	/** Marks a method as to be implemented, but possible
	 * at runtime, not creation time. */
	mixin.expectRuntimeImplementation = function () {
		throw new Error("Method not implemented!");
	};

	/** Placeholder for a hook method that might be overridden. */
	mixin.noop = function () {};

	return mixin;
}(mixinOptions));
<|endoftext|>


<commit_before>import { isObject } from './utils';
import Validator from './validator';

export default (Vue, options) => {
  const mixin = {};
  if (!options.inject) {
    mixin.provide = function providesValidator() {
      if (this.$validator) {
        return {
          $validator: this.$validator
        };
      }

      return {};
    };
  }

  mixin.beforeCreate = function beforeCreate() {
    let reactive = false;
    // if its a root instance, inject anyways, or if it requested an instance.
    if (options.inject || !this.$parent || this.$options.$validates) {
      this.$validator = new Validator(null, { init: false, vm: this });
    } else {
      const injectionOpts = this.$options.inject;
      if (! injectionOpts) {
        return;
      }

      if (Array.isArray(injectionOpts) && ! ~injectionOpts.indexOf('$validator')) {
        return;
      }

      if (isObject(injectionOpts) && ! injectionOpts.$validator) {
        return;
      }

      reactive = true;
    }

    if (! reactive) {
      Vue.util.defineReactive(this.$validator, 'errorBag', this.$validator.errorBag);
      Vue.util.defineReactive(this.$validator, 'fieldBag', this.$validator.fieldBag);
    }

    if (! this.$options.computed) {
      this.$options.computed = {};
    }

    this.$options.computed[options.errorBagName] = function errorBagGetter() {
      return this.$validator.errorBag;
    };
    this.$options.computed[options.fieldsBagName] = function fieldBagGetter() {
      return this.$validator.fieldBag;
    };
  };

  mixin.mounted = function mounted() {
    if (this.$validator) {
      this.$validator.init();
    }
  };

  return mixin;
};
<commit_msg>always provide a validator<commit_after>import { isObject } from './utils';
import Validator from './validator';

export default (Vue, options) => {
  const mixin = {};
  mixin.provide = function providesValidator() {
    if (this.$validator) {
      return {
        $validator: this.$validator
      };
    }

    return {};
  };

  mixin.beforeCreate = function beforeCreate() {
    let reactive = false;
    // if its a root instance, inject anyways, or if it requested an instance.
    if (options.inject || !this.$parent || this.$options.$validates) {
      this.$validator = new Validator(null, { init: false, vm: this });
    } else {
      const injectionOpts = this.$options.inject;
      if (! injectionOpts) {
        return;
      }

      if (Array.isArray(injectionOpts) && ! ~injectionOpts.indexOf('$validator')) {
        return;
      }

      if (isObject(injectionOpts) && ! injectionOpts.$validator) {
        return;
      }

      reactive = true;
    }

    if (! reactive) {
      Vue.util.defineReactive(this.$validator, 'errorBag', this.$validator.errorBag);
      Vue.util.defineReactive(this.$validator, 'fieldBag', this.$validator.fieldBag);
    }

    if (! this.$options.computed) {
      this.$options.computed = {};
    }

    this.$options.computed[options.errorBagName] = function errorBagGetter() {
      return this.$validator.errorBag;
    };
    this.$options.computed[options.fieldsBagName] = function fieldBagGetter() {
      return this.$validator.fieldBag;
    };
  };

  mixin.mounted = function mounted() {
    if (this.$validator) {
      this.$validator.init();
    }
  };

  return mixin;
};
<|endoftext|>


<commit_before>angular.module('FredrikSandell.worker-pool', [])
    .service('WorkerService', ['$q', function ($q) {
    var that = {};
    var urlToAngular;
    var serviceToUrlMap = {};
    /*jshint laxcomma:true */
    /*jshint quotmark: false */
    var workerTemplate = [""
        // Angular needs a global window object \
        , "var window = self;"
        // Skeleton properties to get Angular to load and bootstrap. \
        , "self.history = {};"
        , "var document = {"
        , "      readyState: 'complete',"
        , "      cookie: '',"
        , "      querySelector: function () {},"
        , "      createElement: function () {"
        , "          return {"
        , "              pathname: '',"
        , "              setAttribute: function () {}"
        , "          };"
        , "      }"
        , "};"
        // Load Angular: must be on same domain as this script \
        , "importScripts('<URL_TO_ANGULAR>');"
        , "<CUSTOM_DEP_INCLUDES>"
        // Put angular on global scope \
        , "angular = window.angular;"
        , "var workerApp = angular.module('WorkerApp', [<DEP_MODULES>]);"
        , "workerApp.run(['$q'<STRING_DEP_NAMES>, function ($q<DEP_NAMES>) {"
        , "  self.addEventListener('message', function(e) {"
        , "    var input = e.data;"
        , "    var output = $q.defer();"
        , "    var promise = output.promise;"
        , "    promise.then(function(success) {"
        , "      self.postMessage({event:'success', data : success});"
        , "    }, function(reason) {"
        , "      self.postMessage({event:'failure', data : reason});"
        , "    }, function(update) {"
        , "      self.postMessage({event:'update', data : update});"
        , "    });"
        , "    <WORKER_FUNCTION>;"
        , "  });"
        , "  self.postMessage({event:'initDone'});"
        , "}]);"
        , "angular.bootstrap(null, ['WorkerApp']);"].join("\n");

        that.setAngularUrl = function(urlToAngularJs) {
        urlToAngular = urlToAngularJs;
        return that;
    };

    that.addDependency = function (serviceName, moduleName, url) {
        serviceToUrlMap[serviceName] = {
            url : url,
            moduleName: moduleName
        };
        return that;
    };

    that.createAngularWorker = function (depFuncList) {
        //validate the input

        if (!Array.isArray(depFuncList) ||
            depFuncList.length < 3 ||
            typeof depFuncList[depFuncList.length - 1] !== 'function') {
            throw 'Input needs to be: [\'input\',\'output\'\/*optional additional dependencies*\/,\n' +
                '    function(workerInput, deferredOutput \/*optional additional dependencies*\/)\n' +
                '        {\/*worker body*\/}' +
                ']';
        }
        if(typeof urlToAngular !== 'string') {
            throw 'The url to angular must be defined before worker creation';
        }
        var deferred = $q.defer();

        var dependencyMetaData = createDependencyMetaData(extractDependencyList(depFuncList));

        var blobURL = (window.webkitURL ? webkitURL : URL).createObjectURL(new Blob([
            populateWorkerTemplate(
                workerFunctionToString(
                    depFuncList[depFuncList.length - 1],
                    dependencyMetaData.workerFuncParamList),
                dependencyMetaData
            )], { type: 'application/javascript' }));

        var worker = new Worker(blobURL);

        //wait for the worker to load resources
        worker.addEventListener('message', function (e) {
            var eventId = e.data.event;
            console.log(e.data);
            if (eventId === 'initDone') {
                deferred.resolve(buildAngularWorker(worker));
            } else {
                deferred.reject(e);
            }
        });

        return deferred.promise;
    };

    function createIncludeStatements(listOfServiceNames) {
        var includeString = '';
        angular.forEach(listOfServiceNames, function (serviceName) {
            if (serviceToUrlMap[serviceName]) {
                includeString += 'importScripts(\''+serviceToUrlMap[serviceName].url+'\');';
            }
        });
        return includeString;
    }

    function createModuleList(listOfServiceNames) {
        var moduleNameList = [];
        angular.forEach(listOfServiceNames, function (serviceName) {
            if (serviceToUrlMap[serviceName]) {
                moduleNameList.push('\'' + serviceToUrlMap[serviceName].moduleName + '\'');
            }
        });
        return moduleNameList.join(',');
    }

    function createDependencyMetaData(dependencyList) {
        var dependencyServiceNames = dependencyList.filter(function(dep) {
            return dep !== 'input' && dep !== 'output' && dep !== '$q';
        });
        var depMetaData = {
            dependencies: dependencyServiceNames,
            moduleList: createModuleList(dependencyServiceNames),
            angularDepsAsStrings: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.map(function (dep) {
                return '\'' + dep + '\'';
            }).join(',') : '',
            angularDepsAsParamList: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.join(',') : '',
            servicesIncludeStatements: createIncludeStatements(dependencyServiceNames)
        };
        depMetaData.workerFuncParamList = 'input,output'+depMetaData.angularDepsAsParamList;
        return depMetaData;
    }

    function populateWorkerTemplate(workerFunc, dependencyMetaData) {
        return workerTemplate.replace('<URL_TO_ANGULAR>', urlToAngular)
            .replace('<CUSTOM_DEP_INCLUDES>', dependencyMetaData.servicesIncludeStatements)
            .replace('<DEP_MODULES>', dependencyMetaData.moduleList)
            .replace('<STRING_DEP_NAMES>', dependencyMetaData.angularDepsAsStrings)
            .replace('<DEP_NAMES>', dependencyMetaData.angularDepsAsParamList)
            .replace('<WORKER_FUNCTION>', workerFunc.toString());
    }

    var buildAngularWorker = function (initializedWorker) {
        var that = {};
        that.worker = initializedWorker;
        that.run = function (input) {
            var deferred = $q.defer();
            initializedWorker.addEventListener('message', function (e) {
                var eventId = e.data.event;
                //console.log(e.data);
                if (eventId === 'initDone') {
                    throw 'Received worker initialization in run method. This should already have occurred!';
                } else if (eventId === 'success') {
                    deferred.resolve(e.data.data);
                } else if (eventId === 'failure') {
                    deferred.reject(e.data.data);
                } else if (eventId === 'update') {
                    deferred.notify(e.data.data);
                } else {
                    deferred.reject(e);
                }
            });
            initializedWorker.postMessage(input);
            return deferred.promise;
        };

        that.terminate = function () {
            initializedWorker.terminate();
        };

        return that;
    };

    function extractDependencyList(depFuncList) {
        return depFuncList.slice(0, depFuncList.length - 1);
    }

    function workerFunctionToString(func, paramList) {
        return '('+func.toString() + ')(' + paramList + ')';
    }

    return that;
}]);
<commit_msg>removed a couple of console output messages left by mistake<commit_after>angular.module('FredrikSandell.worker-pool', [])
    .service('WorkerService', ['$q', function ($q) {
    var that = {};
    var urlToAngular;
    var serviceToUrlMap = {};
    /*jshint laxcomma:true */
    /*jshint quotmark: false */
    var workerTemplate = [""
        // Angular needs a global window object \
        , "var window = self;"
        // Skeleton properties to get Angular to load and bootstrap. \
        , "self.history = {};"
        , "var document = {"
        , "      readyState: 'complete',"
        , "      cookie: '',"
        , "      querySelector: function () {},"
        , "      createElement: function () {"
        , "          return {"
        , "              pathname: '',"
        , "              setAttribute: function () {}"
        , "          };"
        , "      }"
        , "};"
        // Load Angular: must be on same domain as this script \
        , "importScripts('<URL_TO_ANGULAR>');"
        , "<CUSTOM_DEP_INCLUDES>"
        // Put angular on global scope \
        , "angular = window.angular;"
        , "var workerApp = angular.module('WorkerApp', [<DEP_MODULES>]);"
        , "workerApp.run(['$q'<STRING_DEP_NAMES>, function ($q<DEP_NAMES>) {"
        , "  self.addEventListener('message', function(e) {"
        , "    var input = e.data;"
        , "    var output = $q.defer();"
        , "    var promise = output.promise;"
        , "    promise.then(function(success) {"
        , "      self.postMessage({event:'success', data : success});"
        , "    }, function(reason) {"
        , "      self.postMessage({event:'failure', data : reason});"
        , "    }, function(update) {"
        , "      self.postMessage({event:'update', data : update});"
        , "    });"
        , "    <WORKER_FUNCTION>;"
        , "  });"
        , "  self.postMessage({event:'initDone'});"
        , "}]);"
        , "angular.bootstrap(null, ['WorkerApp']);"].join("\n");

        that.setAngularUrl = function(urlToAngularJs) {
        urlToAngular = urlToAngularJs;
        return that;
    };

    that.addDependency = function (serviceName, moduleName, url) {
        serviceToUrlMap[serviceName] = {
            url : url,
            moduleName: moduleName
        };
        return that;
    };

    that.createAngularWorker = function (depFuncList) {
        //validate the input

        if (!Array.isArray(depFuncList) ||
            depFuncList.length < 3 ||
            typeof depFuncList[depFuncList.length - 1] !== 'function') {
            throw 'Input needs to be: [\'input\',\'output\'\/*optional additional dependencies*\/,\n' +
                '    function(workerInput, deferredOutput \/*optional additional dependencies*\/)\n' +
                '        {\/*worker body*\/}' +
                ']';
        }
        if(typeof urlToAngular !== 'string') {
            throw 'The url to angular must be defined before worker creation';
        }
        var deferred = $q.defer();

        var dependencyMetaData = createDependencyMetaData(extractDependencyList(depFuncList));

        var blobURL = (window.webkitURL ? webkitURL : URL).createObjectURL(new Blob([
            populateWorkerTemplate(
                workerFunctionToString(
                    depFuncList[depFuncList.length - 1],
                    dependencyMetaData.workerFuncParamList),
                dependencyMetaData
            )], { type: 'application/javascript' }));

        var worker = new Worker(blobURL);

        //wait for the worker to load resources
        worker.addEventListener('message', function (e) {
            var eventId = e.data.event;
            if (eventId === 'initDone') {
                deferred.resolve(buildAngularWorker(worker));
            } else {
                deferred.reject(e);
            }
        });

        return deferred.promise;
    };

    function createIncludeStatements(listOfServiceNames) {
        var includeString = '';
        angular.forEach(listOfServiceNames, function (serviceName) {
            if (serviceToUrlMap[serviceName]) {
                includeString += 'importScripts(\''+serviceToUrlMap[serviceName].url+'\');';
            }
        });
        return includeString;
    }

    function createModuleList(listOfServiceNames) {
        var moduleNameList = [];
        angular.forEach(listOfServiceNames, function (serviceName) {
            if (serviceToUrlMap[serviceName]) {
                moduleNameList.push('\'' + serviceToUrlMap[serviceName].moduleName + '\'');
            }
        });
        return moduleNameList.join(',');
    }

    function createDependencyMetaData(dependencyList) {
        var dependencyServiceNames = dependencyList.filter(function(dep) {
            return dep !== 'input' && dep !== 'output' && dep !== '$q';
        });
        var depMetaData = {
            dependencies: dependencyServiceNames,
            moduleList: createModuleList(dependencyServiceNames),
            angularDepsAsStrings: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.map(function (dep) {
                return '\'' + dep + '\'';
            }).join(',') : '',
            angularDepsAsParamList: dependencyServiceNames.length > 0 ? ',' + dependencyServiceNames.join(',') : '',
            servicesIncludeStatements: createIncludeStatements(dependencyServiceNames)
        };
        depMetaData.workerFuncParamList = 'input,output'+depMetaData.angularDepsAsParamList;
        return depMetaData;
    }

    function populateWorkerTemplate(workerFunc, dependencyMetaData) {
        return workerTemplate.replace('<URL_TO_ANGULAR>', urlToAngular)
            .replace('<CUSTOM_DEP_INCLUDES>', dependencyMetaData.servicesIncludeStatements)
            .replace('<DEP_MODULES>', dependencyMetaData.moduleList)
            .replace('<STRING_DEP_NAMES>', dependencyMetaData.angularDepsAsStrings)
            .replace('<DEP_NAMES>', dependencyMetaData.angularDepsAsParamList)
            .replace('<WORKER_FUNCTION>', workerFunc.toString());
    }

    var buildAngularWorker = function (initializedWorker) {
        var that = {};
        that.worker = initializedWorker;
        that.run = function (input) {
            var deferred = $q.defer();
            initializedWorker.addEventListener('message', function (e) {
                var eventId = e.data.event;
                if (eventId === 'initDone') {
                    throw 'Received worker initialization in run method. This should already have occurred!';
                } else if (eventId === 'success') {
                    deferred.resolve(e.data.data);
                } else if (eventId === 'failure') {
                    deferred.reject(e.data.data);
                } else if (eventId === 'update') {
                    deferred.notify(e.data.data);
                } else {
                    deferred.reject(e);
                }
            });
            initializedWorker.postMessage(input);
            return deferred.promise;
        };

        that.terminate = function () {
            initializedWorker.terminate();
        };

        return that;
    };

    function extractDependencyList(depFuncList) {
        return depFuncList.slice(0, depFuncList.length - 1);
    }

    function workerFunctionToString(func, paramList) {
        return '('+func.toString() + ')(' + paramList + ')';
    }

    return that;
}]);
<|endoftext|>