<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 * @author bhouston / http://exocortex.com/
 */

( function ( THREE ) {

	THREE.Raycaster = function ( origin, direction, near, far ) {

		this.ray = new THREE.Ray( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if ( this.ray.direction.lengthSq() > 0 ) {

			this.ray.direction.normalize();

		}

		this.near = near || 0;
		this.far = far || Infinity;

	};

	var sphere = new THREE.Sphere();
	var localRay = new THREE.Ray();
	var facePlane = new THREE.Plane();
	var intersectPoint = new THREE.Vector3();
	var matrixPosition = new THREE.Vector3();

	var inverseMatrix = new THREE.Matrix4();

	var descSort = function ( a, b ) {

		return a.distance - b.distance;

	};

	var intersectObject = function ( object, raycaster, intersects ) {

		if ( object instanceof THREE.Particle ) {

			matrixPosition.getPositionFromMatrix( object.matrixWorld );
			var distance = raycaster.ray.distanceToPoint( matrixPosition );

			if ( distance > object.scale.x ) {

				return intersects;

			}

			intersects.push( {

				distance: distance,
				point: object.position,
				face: null,
				object: object

			} );

		} else if ( object instanceof THREE.LOD ) {

			matrixPosition.getPositionFromMatrix( object.matrixWorld );
			var distance = raycaster.ray.origin.distanceTo( matrixPosition );

			intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );

		} else if (object instanceof THREE.Mesh ) {

			// Checking boundingSphere distance to ray
			matrixPosition.getPositionFromMatrix( object.matrixWorld );
			sphere.set( matrixPosition, object.geometry.boundingSphere.radius * object.matrixWorld.getMaxScaleOnAxis() );

			if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {

				return intersects;

			}

			var geometry = object.geometry;
			var vertices = geometry.vertices;

			if ( geometry instanceof THREE.BufferGeometry ) {

				var material = object.material;

				if ( material === undefined ) return intersects;
				if ( ! geometry.dynamic ) return intersects;

				var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
				var objectMaterials = isFaceMaterial === true ? object.material.materials : null;

				var side = object.material.side;

				var a, b, c;
				var precision = raycaster.precision;

				inverseMatrix.getInverse( object.matrixWorld );

				localRay.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

				var fl;
				var indexed = false;
				if ( geometry.attributes.index ) {

					indexed = true;
					fl = geometry.attributes.index.numItems / 3;

				} else {

					fl = geometry.attributes.position.numItems / 9;
				}

				var vA = new THREE.Vector3();
				var vB = new THREE.Vector3();
				var vC = new THREE.Vector3();
				var vCB = new THREE.Vector3();
				var vAB = new THREE.Vector3();

				for ( var oi = 0; oi < geometry.offsets.length; ++oi ) {

					var start = geometry.offsets[ oi ].start;
					var count = geometry.offsets[ oi ].count;
					var index = geometry.offsets[ oi ].index;

					for ( var i = start, il = start + count; i < il; i += 3 ) {

						if ( indexed ) {
							a = index + geometry.attributes.index.array[ i ];
							b = index + geometry.attributes.index.array[ i + 1 ];
							c = index + geometry.attributes.index.array[ i + 2 ];
						} else {
							a = index;
							b = index + 1;
							c = index + 2;
						}

						vA.set( geometry.attributes.position.array[ a * 3 ],
								geometry.attributes.position.array[ a * 3 + 1 ],
								geometry.attributes.position.array[ a * 3 + 2] );
						vB.set( geometry.attributes.position.array[ b * 3 ],
								geometry.attributes.position.array[ b * 3 + 1 ],
								geometry.attributes.position.array[ b * 3 + 2] );
						vC.set( geometry.attributes.position.array[ c * 3 ],
								geometry.attributes.position.array[ c * 3 + 1 ],
								geometry.attributes.position.array[ c * 3 + 2 ] );

						facePlane.setFromCoplanarPoints( vA, vB, vC );

						var planeDistance = localRay.distanceToPlane( facePlane );

						// bail if raycaster and plane are parallel
						if ( Math.abs( planeDistance ) < precision ) continue;

						// if negative distance, then plane is behind raycaster
						if ( planeDistance < 0 ) continue;

						// check if we hit the wrong side of a single sided face
						side = material.side;
						if ( side !== THREE.DoubleSide ) {

							var planeSign = localRay.direction.dot( facePlane.normal );

							if ( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;

						}

						// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
						if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;

						intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy

						if ( ! THREE.Triangle.containsPoint( intersectPoint, vA, vB, vC ) ) continue;

						intersects.push( {

							distance: planeDistance, // this works because the original ray was normalized, and the transformed localRay wasn't
							point: raycaster.ray.at(planeDistance),
							face: null,
							faceIndex: null,
							object: object

						} );

					}
				}

			} else if ( geometry instanceof THREE.Geometry ) {

				var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
				var objectMaterials = isFaceMaterial === true ? object.material.materials : null;

				var side = object.material.side;

				var a, b, c, d;
				var precision = raycaster.precision;

				inverseMatrix.getInverse( object.matrixWorld );

				localRay.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

				for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) {

					var face = geometry.faces[ f ];

					var material = isFaceMaterial === true ? objectMaterials[ face.materialIndex ] : object.material;

					if ( material === undefined ) continue;

					facePlane.setFromNormalAndCoplanarPoint( face.normal, vertices[face.a] );

					var planeDistance = localRay.distanceToPlane( facePlane );

					// bail if raycaster and plane are parallel
					if ( Math.abs( planeDistance ) < precision ) continue;

					// if negative distance, then plane is behind raycaster
					if ( planeDistance < 0 ) continue;

					// check if we hit the wrong side of a single sided face
					side = material.side;
					if ( side !== THREE.DoubleSide ) {

						var planeSign = localRay.direction.dot( facePlane.normal );

						if ( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;

					}

					// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
					if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;

					intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy

					if ( face instanceof THREE.Face3 ) {

						a = vertices[ face.a ];
						b = vertices[ face.b ];
						c = vertices[ face.c ];

						if ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, c ) ) continue;

					} else if ( face instanceof THREE.Face4 ) {

						a = vertices[ face.a ];
						b = vertices[ face.b ];
						c = vertices[ face.c ];
						d = vertices[ face.d ];

						if ( ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, d ) ) &&
							 ( ! THREE.Triangle.containsPoint( intersectPoint, b, c, d ) ) ) continue;

					} else {

						// This is added because if we call out of this if/else group when none of the cases
						//    match it will add a point to the intersection list erroneously.
						throw Error( "face type not supported" );

					}

					intersects.push( {

						distance: planeDistance,    // this works because the original ray was normalized, and the transformed localRay wasn't
						point: raycaster.ray.at( planeDistance ),
						face: face,
						faceIndex: f,
						object: object

					} );

				}

			}

		}

	};

	var intersectDescendants = function ( object, raycaster, intersects ) {

		var descendants = object.getDescendants();

		for ( var i = 0, l = descendants.length; i < l; i ++ ) {

			intersectObject( descendants[ i ], raycaster, intersects );

		}
	};

	//

	THREE.Raycaster.prototype.precision = 0.0001;

	THREE.Raycaster.prototype.set = function ( origin, direction ) {

		this.ray.set( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if ( this.ray.direction.length() > 0 ) {

			this.ray.direction.normalize();

		}

	};

	THREE.Raycaster.prototype.intersectObject = function ( object, recursive ) {

		var intersects = [];

		if ( recursive === true ) {

			intersectDescendants( object, this, intersects );

		}

		intersectObject( object, this, intersects );

		intersects.sort( descSort );

		return intersects;

	};

	THREE.Raycaster.prototype.intersectObjects = function ( objects, recursive ) {

		var intersects = [];

		for ( var i = 0, l = objects.length; i < l; i ++ ) {

			intersectObject( objects[ i ], this, intersects );

			if ( recursive === true ) {

				intersectDescendants( objects[ i ], this, intersects );

			}
		}

		intersects.sort( descSort );

		return intersects;

	};

}( THREE ) );
<commit_msg>The raycaster can now pick lines... given a 3D precision threshold.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 * @author bhouston / http://exocortex.com/
 */

( function ( THREE ) {

	THREE.Raycaster = function ( origin, direction, near, far ) {

		this.ray = new THREE.Ray( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if ( this.ray.direction.lengthSq() > 0 ) {

			this.ray.direction.normalize();

		}

		this.near = near || 0;
		this.far = far || Infinity;

	};

	var sphere = new THREE.Sphere();
	var localRay = new THREE.Ray();
	var facePlane = new THREE.Plane();
	var intersectPoint = new THREE.Vector3();
	var matrixPosition = new THREE.Vector3();

	var inverseMatrix = new THREE.Matrix4();

	var descSort = function ( a, b ) {

		return a.distance - b.distance;

	};

	var intersectObject = function ( object, raycaster, intersects ) {

		if ( object instanceof THREE.Particle ) {

			matrixPosition.getPositionFromMatrix( object.matrixWorld );
			var distance = raycaster.ray.distanceToPoint( matrixPosition );

			if ( distance > object.scale.x ) {

				return intersects;

			}

			intersects.push( {

				distance: distance,
				point: object.position,
				face: null,
				object: object

			} );

		} else if ( object instanceof THREE.LOD ) {

			matrixPosition.getPositionFromMatrix( object.matrixWorld );
			var distance = raycaster.ray.origin.distanceTo( matrixPosition );

			intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );

		} else if (object instanceof THREE.Mesh ) {

			// Checking boundingSphere distance to ray
			matrixPosition.getPositionFromMatrix( object.matrixWorld );
			sphere.set( matrixPosition, object.geometry.boundingSphere.radius * object.matrixWorld.getMaxScaleOnAxis() );

			if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {

				return intersects;

			}

			var geometry = object.geometry;
			var vertices = geometry.vertices;

			if ( geometry instanceof THREE.BufferGeometry ) {

				var material = object.material;

				if ( material === undefined ) return intersects;
				if ( ! geometry.dynamic ) return intersects;

				var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
				var objectMaterials = isFaceMaterial === true ? object.material.materials : null;

				var side = object.material.side;

				var a, b, c;
				var precision = raycaster.precision;

				inverseMatrix.getInverse( object.matrixWorld );

				localRay.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

				var fl;
				var indexed = false;
				if ( geometry.attributes.index ) {

					indexed = true;
					fl = geometry.attributes.index.numItems / 3;

				} else {

					fl = geometry.attributes.position.numItems / 9;
				}

				var vA = new THREE.Vector3();
				var vB = new THREE.Vector3();
				var vC = new THREE.Vector3();
				var vCB = new THREE.Vector3();
				var vAB = new THREE.Vector3();

				for ( var oi = 0; oi < geometry.offsets.length; ++oi ) {

					var start = geometry.offsets[ oi ].start;
					var count = geometry.offsets[ oi ].count;
					var index = geometry.offsets[ oi ].index;

					for ( var i = start, il = start + count; i < il; i += 3 ) {

						if ( indexed ) {
							a = index + geometry.attributes.index.array[ i ];
							b = index + geometry.attributes.index.array[ i + 1 ];
							c = index + geometry.attributes.index.array[ i + 2 ];
						} else {
							a = index;
							b = index + 1;
							c = index + 2;
						}

						vA.set( geometry.attributes.position.array[ a * 3 ],
								geometry.attributes.position.array[ a * 3 + 1 ],
								geometry.attributes.position.array[ a * 3 + 2] );
						vB.set( geometry.attributes.position.array[ b * 3 ],
								geometry.attributes.position.array[ b * 3 + 1 ],
								geometry.attributes.position.array[ b * 3 + 2] );
						vC.set( geometry.attributes.position.array[ c * 3 ],
								geometry.attributes.position.array[ c * 3 + 1 ],
								geometry.attributes.position.array[ c * 3 + 2 ] );

						facePlane.setFromCoplanarPoints( vA, vB, vC );

						var planeDistance = localRay.distanceToPlane( facePlane );

						// bail if raycaster and plane are parallel
						if ( Math.abs( planeDistance ) < precision ) continue;

						// if negative distance, then plane is behind raycaster
						if ( planeDistance < 0 ) continue;

						// check if we hit the wrong side of a single sided face
						side = material.side;
						if ( side !== THREE.DoubleSide ) {

							var planeSign = localRay.direction.dot( facePlane.normal );

							if ( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;

						}

						// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
						if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;

						intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy

						if ( ! THREE.Triangle.containsPoint( intersectPoint, vA, vB, vC ) ) continue;

						intersects.push( {

							distance: planeDistance, // this works because the original ray was normalized, and the transformed localRay wasn't
							point: raycaster.ray.at(planeDistance),
							face: null,
							faceIndex: null,
							object: object

						} );

					}
				}

			} else if ( geometry instanceof THREE.Geometry ) {

				var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
				var objectMaterials = isFaceMaterial === true ? object.material.materials : null;

				var side = object.material.side;

				var a, b, c, d;
				var precision = raycaster.precision;

				inverseMatrix.getInverse( object.matrixWorld );

				localRay.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

				for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) {

					var face = geometry.faces[ f ];

					var material = isFaceMaterial === true ? objectMaterials[ face.materialIndex ] : object.material;

					if ( material === undefined ) continue;

					facePlane.setFromNormalAndCoplanarPoint( face.normal, vertices[face.a] );

					var planeDistance = localRay.distanceToPlane( facePlane );

					// bail if raycaster and plane are parallel
					if ( Math.abs( planeDistance ) < precision ) continue;

					// if negative distance, then plane is behind raycaster
					if ( planeDistance < 0 ) continue;

					// check if we hit the wrong side of a single sided face
					side = material.side;
					if ( side !== THREE.DoubleSide ) {

						var planeSign = localRay.direction.dot( facePlane.normal );

						if ( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;

					}

					// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
					if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;

					intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy

					if ( face instanceof THREE.Face3 ) {

						a = vertices[ face.a ];
						b = vertices[ face.b ];
						c = vertices[ face.c ];

						if ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, c ) ) continue;

					} else if ( face instanceof THREE.Face4 ) {

						a = vertices[ face.a ];
						b = vertices[ face.b ];
						c = vertices[ face.c ];
						d = vertices[ face.d ];

						if ( ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, d ) ) &&
							 ( ! THREE.Triangle.containsPoint( intersectPoint, b, c, d ) ) ) continue;

					} else {

						// This is added because if we call out of this if/else group when none of the cases
						//    match it will add a point to the intersection list erroneously.
						throw Error( "face type not supported" );

					}

					intersects.push( {

						distance: planeDistance,    // this works because the original ray was normalized, and the transformed localRay wasn't
						point: raycaster.ray.at( planeDistance ),
						face: face,
						faceIndex: f,
						object: object

					} );

				}

			}

		} else if (object instanceof THREE.Line) {

			var precision = raycaster.linePrecision;
			if(precision < 0)
				return intersects;

			var precisionSq = precision * precision;

			// Checking boundingSphere distance to ray
			matrixPosition.getPositionFromMatrix(object.matrixWorld);
			sphere.set(matrixPosition, object.geometry.boundingSphere.radius * object.matrixWorld.getMaxScaleOnAxis());

			if(!raycaster.ray.isIntersectionSphere(sphere))
				return intersects;

			inverseMatrix.getInverse(object.matrixWorld);
			localRay.copy(raycaster.ray).applyMatrix4(inverseMatrix);
			var vertices = object.geometry.vertices;
			var nbVertices = vertices.length;
			var interPoint = new THREE.Vector3();

			for(var i = 0; i < nbVertices - 1; ++i) {

				var distTestSq = localRay.distanceSqAndPointToSegment(vertices[i], vertices[i + 1], null, interPoint);
				if(distTestSq <= precisionSq) {
					var worldPoint = interPoint.applyMatrix4(object.matrix);
					var distance = raycaster.ray.origin.distanceTo(worldPoint)
					if(raycaster.near <= distance && distance <= raycaster.far)
						intersects.push({distance: distance, point: worldPoint, object: object});
				}
			}
		}

	};

	var intersectDescendants = function ( object, raycaster, intersects ) {

		var descendants = object.getDescendants();

		for ( var i = 0, l = descendants.length; i < l; i ++ ) {

			intersectObject( descendants[ i ], raycaster, intersects );

		}
	};

	//

	THREE.Raycaster.prototype.precision = 0.0001;
	THREE.Raycaster.prototype.linePrecision = -1; // if negative, we don't pick lines

	THREE.Raycaster.prototype.set = function ( origin, direction ) {

		this.ray.set( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if ( this.ray.direction.length() > 0 ) {

			this.ray.direction.normalize();

		}

	};

	THREE.Raycaster.prototype.intersectObject = function ( object, recursive ) {

		var intersects = [];

		if ( recursive === true ) {

			intersectDescendants( object, this, intersects );

		}

		intersectObject( object, this, intersects );

		intersects.sort( descSort );

		return intersects;

	};

	THREE.Raycaster.prototype.intersectObjects = function ( objects, recursive ) {

		var intersects = [];

		for ( var i = 0, l = objects.length; i < l; i ++ ) {

			intersectObject( objects[ i ], this, intersects );

			if ( recursive === true ) {

				intersectDescendants( objects[ i ], this, intersects );

			}
		}

		intersects.sort( descSort );

		return intersects;

	};

}( THREE ) );
<|endoftext|>


<commit_before>/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
    return sequelize.define('pedidos', {
        id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        usuarioId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'usuarios',
                key: 'id'
            }
        },
        gruposDeMesaId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'gruposDeMesas',
                key: 'id'
            }
        },
        pedidoEstadoId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'pedidoEstado',
                key: 'id'
            }
        }
    }, {
        tableName: 'pedidos',
        name: {
          singular: 'pedido',
          plural: 'pedidos',
        },
        paranoid: true,
    });
};
<commit_msg>cambio de nombre campo grupoDeMesasId<commit_after>/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
    return sequelize.define('pedidos', {
        id: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        usuarioId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'usuarios',
                key: 'id'
            }
        },
        grupoDeMesasId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'gruposDeMesas',
                key: 'id'
            }
        },
        pedidoEstadoId: {
            type: DataTypes.INTEGER(11),
            allowNull: false,
            references: {
                model: 'pedidoEstado',
                key: 'id'
            }
        }
    }, {
        tableName: 'pedidos',
        name: {
          singular: 'pedido',
          plural: 'pedidos',
        },
        paranoid: true,
    });
};
<|endoftext|>


<commit_before>const Sequelize = require('sequelize');
const sequelize = require('./');

const Stage = require('./stage');

const Submission = sequelize.define('submissions', {
	name: {
		type: Sequelize.STRING,
	},
	board: {
		type: Sequelize.TEXT,
		allowNull: false,
	},
	blocks: {
		type: Sequelize.INTEGER,
		allowNull: false,
		validate: {
			min: 0,
		},
	},
	clocks: {
		type: Sequelize.INTEGER,
		allowNull: false,
		validate: {
			min: 0,
		},
	},
	score: {
		type: Sequelize.INTEGER,
		allowNull: false,
		validate: {
			min: 0,
		},
	},
	stageId: {
		type: Sequelize.INTEGER,
		references: {
			model: Stage,
			key: 'id',
		},
	},
});

Submission.belongsTo(Stage);

module.exports = Submission;
<commit_msg>Add name validation to the nsubmission.ame field<commit_after>const Sequelize = require('sequelize');
const sequelize = require('./');

const Stage = require('./stage');

const Submission = sequelize.define('submissions', {
	name: {
		type: Sequelize.STRING,
		allowNull: false,
		validate: {
			len: [1, 100],
		},
	},
	board: {
		type: Sequelize.TEXT,
		allowNull: false,
	},
	blocks: {
		type: Sequelize.INTEGER,
		allowNull: false,
		validate: {
			min: 0,
		},
	},
	clocks: {
		type: Sequelize.INTEGER,
		allowNull: false,
		validate: {
			min: 0,
		},
	},
	score: {
		type: Sequelize.INTEGER,
		allowNull: false,
		validate: {
			min: 0,
		},
	},
	stageId: {
		type: Sequelize.INTEGER,
		references: {
			model: Stage,
			key: 'id',
		},
	},
});

Submission.belongsTo(Stage);

module.exports = Submission;
<|endoftext|>


<commit_before>/* global DocumentTypes, SourceTypes */
// Exporter.js - in api/services

const lescape = require('escape-latex');

"use strict";

module.exports = {
    documentsToCsv,
    documentsToBibtex
};

function documentsToCsv(documents) {
    const rows = [[
        'Authors',
        'Titile',
        'Source',
        'Year',
        'DOI',
        'Type',
        'Source type',
        'Citations',
        'IF',
        'SNIP',
        'SJR'
    ]].concat(documents.map(d => {
        const document = d.toJSON();
        const doc = [];
        doc.push(document.authorsStr);
        doc.push(document.title);

        let source;
        if (document.type === DocumentTypes.INVITED_TALK)
            source = document.itSource;
        else
            source = document.source ? document.source.title : '';

        doc.push(source);
        doc.push(document.year);
        doc.push(document.doi);
        doc.push(document.documenttype ? document.documenttype.label : '');
        doc.push(document.sourceTypeObj ? document.sourceTypeObj.label : '');
        doc.push(Array.isArray(document.scopusCitations) ? document.scopusCitations.reduce((total, s) => total + s.value, 0) : '');
        doc.push(document.IF);
        doc.push(document.SNIP);
        doc.push(document.SJR);

        return doc;
    }));

    let csv = 'data:text/csv;charset=utf-8,';

    rows.forEach(function (rowArray) {
        csv += rowArray.map(r => r ? '"' + r.toString().replace(/"/g, '""') + '"' : '""')
            .join(',') + '\r\n';
    });

    return csv;
}

function documentsToBibtex(documents) {

    let bibtex = 'data:text/plain;charset=utf-8,';

    documents.forEach(document => {
        bibtex += getBibtex(document) + '\n\n';
    });

    return bibtex;

}

function getBibtex(document) {
    const doc = document.toJSON();

    let entryType = 'ARTICLE';

    if ([
        DocumentTypes.INVITED_TALK,
        DocumentTypes.ABSTRACT_REPORT,
        DocumentTypes.ERRATUM,
        DocumentTypes.POSTER,
        DocumentTypes.PHD_THESIS,
        DocumentTypes.REPORT
    ].includes(doc.documenttype.key)) {
        const map = {
            [DocumentTypes.PHD_THESIS]: 'PHDTHESIS',
            [DocumentTypes.ABSTRACT_REPORT]: 'TECHREPORT',
            [DocumentTypes.ERRATUM]: 'MISC',
            [DocumentTypes.REPORT]: 'MISC',
            [DocumentTypes.POSTER]: 'MISC',
            [DocumentTypes.INVITED_TALK]: 'MISC',
        };
        entryType = map[doc.documenttype.key];
    }
    else {
        const map = {
            [SourceTypes.JOURNAL]: 'ARTICLE',
            [SourceTypes.CONFERENCE]: 'CONFERENCE',
            [SourceTypes.BOOK]: 'BOOK',
            [SourceTypes.BOOKSERIES]: 'INCOLLECTION',

        };
        entryType = map[doc.source.sourcetype.key];
    }

    const entryFields = {
        'ARTICLE': {
            required: [
                'author',
                'title',
                'journal',
                'year'
            ],
            optional: [
                'volume',
                'number',
                'pages'
            ]
        },
        'CONFERENCE': {
            required: [
                'author',
                'title',
                'booktitle',
                'year'
            ],
            optional: [
                'pages'
            ]
        },
        'BOOK': {
            required: [
                'author',
                'title',
                'publisher',
                'year'
            ],
            optional: [
                'volume'
            ]
        },
        'INCOLLECTION': {
            required: [
                'author',
                'title',
                'booktitle',
                'year'
            ],
            optional: [
                'pages'
            ]
        },
        'PHDTHESIS': {
            required: [
                'author',
                'title',
                'school',
                'year'
            ],
            optional: []
        },
        'TECHREPORT': {
            required: [
                'author',
                'title',
                'institution',
                'year'
            ],
            optional: []
        },
        'MISC': {
            required: [
                'author',
                'title'
            ],
            optional: []
        },
    };

    const fieldsMapper = {
        author: getBibtexAuthors(doc),
        title: doc.title,
        journal: doc.source ? doc.source.title : '',
        booktitle: doc.source ? doc.source.title : '',
        institution: doc.source ? doc.source.title : '',
        publisher: doc.source ? doc.source.title : '',
        school: doc.source ? doc.source.title : '',
        year: doc.year,
        volume: doc.volume,
        number: doc.articleNumber,
        pages: doc.pages,
    };

    const fields = {};

    entryFields[entryType].required.forEach(f => fields[f] = fieldsMapper[f]);
    entryFields[entryType].optional.forEach(f => {
        if (fieldsMapper[f]) fields[f] = fieldsMapper[f];
    });

    return formatBibtex(getBibtexKey(doc), fields, entryType);

}

function getBibtexKey(doc) {
    return 'SCTL-' + doc.id;
}

function getBibtexAuthors(doc) {
    const authors = doc.authorsStr.split(', ');

    return authors.map(a => {
        const tokens = a.split(/\s/);

        const {names, surnames} = tokens.reduce((res, val) => {
            if (val.includes('.'))
                res.surnames.push(val.replace(/\./g, '. ').trim());
            else
                res.names.push(val.trim());

            return res;
        }, {names: [], surnames: []});

        return names.join(' ') + ', ' + surnames.join(' ');
    }).join(' and ');
}

function formatBibtex(key, fields, entryType) {
    const fieldsArr = Object.keys(fields).map(f => '  ' + f + '={' + lescape(fields[f]) + '}');
    return '@' + entryType + '{' + key + ',\n' + fieldsArr.join(',\n') + '\n}';
}
<commit_msg>Added reference on the csv export<commit_after>/* global DocumentTypes, SourceTypes */
// Exporter.js - in api/services

const lescape = require('escape-latex');
const _ = require('lodash');

"use strict";

module.exports = {
    documentsToCsv,
    documentsToBibtex
};

function documentsToCsv(documents) {
    const rows = [[
        'Authors',
        'Titile',
        'Source',
        'Year',
        'DOI',
        'Type',
        'Source type',
        'Citations',
        'IF',
        'SNIP',
        'SJR',
        'Reference'
    ]].concat(documents.map(d => {
        const document = d.toJSON();
        const doc = [];
        doc.push(document.authorsStr);
        doc.push(document.title);

        let source;
        if (document.type === DocumentTypes.INVITED_TALK)
            source = document.itSource;
        else
            source = document.source ? document.source.title : '';

        doc.push(source);
        doc.push(document.year);
        doc.push(document.doi);
        doc.push(document.documenttype ? document.documenttype.label : '');
        doc.push(document.sourceTypeObj ? document.sourceTypeObj.label : '');
        doc.push(Array.isArray(document.scopusCitations) ? document.scopusCitations.reduce((total, s) => total + s.value, 0) : '');
        doc.push(document.IF);
        doc.push(document.SNIP);
        doc.push(document.SJR);

        const reference = [
            document.authorsStr,
            document.title,
            document.sourceDetails,
            document.year,
            document.doi
        ];
        doc.push(reference.filter(r => !_.isNil(r)).join(', '));

        return doc;
    }));

    let csv = 'data:text/csv;charset=utf-8,';

    rows.forEach(function (rowArray) {
        csv += rowArray.map(r => r ? '"' + r.toString().replace(/"/g, '""') + '"' : '""')
            .join(',') + '\r\n';
    });

    return csv;
}

function documentsToBibtex(documents) {

    let bibtex = 'data:text/plain;charset=utf-8,';

    documents.forEach(document => {
        bibtex += getBibtex(document) + '\n\n';
    });

    return bibtex;

}

function getBibtex(document) {
    const doc = document.toJSON();

    let entryType = 'ARTICLE';

    if ([
        DocumentTypes.INVITED_TALK,
        DocumentTypes.ABSTRACT_REPORT,
        DocumentTypes.ERRATUM,
        DocumentTypes.POSTER,
        DocumentTypes.PHD_THESIS,
        DocumentTypes.REPORT
    ].includes(doc.documenttype.key)) {
        const map = {
            [DocumentTypes.PHD_THESIS]: 'PHDTHESIS',
            [DocumentTypes.ABSTRACT_REPORT]: 'TECHREPORT',
            [DocumentTypes.ERRATUM]: 'MISC',
            [DocumentTypes.REPORT]: 'MISC',
            [DocumentTypes.POSTER]: 'MISC',
            [DocumentTypes.INVITED_TALK]: 'MISC',
        };
        entryType = map[doc.documenttype.key];
    }
    else {
        const map = {
            [SourceTypes.JOURNAL]: 'ARTICLE',
            [SourceTypes.CONFERENCE]: 'CONFERENCE',
            [SourceTypes.BOOK]: 'BOOK',
            [SourceTypes.BOOKSERIES]: 'INCOLLECTION',

        };
        entryType = map[doc.source.sourcetype.key];
    }

    const entryFields = {
        'ARTICLE': {
            required: [
                'author',
                'title',
                'journal',
                'year'
            ],
            optional: [
                'volume',
                'number',
                'pages'
            ]
        },
        'CONFERENCE': {
            required: [
                'author',
                'title',
                'booktitle',
                'year'
            ],
            optional: [
                'pages'
            ]
        },
        'BOOK': {
            required: [
                'author',
                'title',
                'publisher',
                'year'
            ],
            optional: [
                'volume'
            ]
        },
        'INCOLLECTION': {
            required: [
                'author',
                'title',
                'booktitle',
                'year'
            ],
            optional: [
                'pages'
            ]
        },
        'PHDTHESIS': {
            required: [
                'author',
                'title',
                'school',
                'year'
            ],
            optional: []
        },
        'TECHREPORT': {
            required: [
                'author',
                'title',
                'institution',
                'year'
            ],
            optional: []
        },
        'MISC': {
            required: [
                'author',
                'title'
            ],
            optional: []
        },
    };

    const fieldsMapper = {
        author: getBibtexAuthors(doc),
        title: doc.title,
        journal: doc.source ? doc.source.title : '',
        booktitle: doc.source ? doc.source.title : '',
        institution: doc.source ? doc.source.title : '',
        publisher: doc.source ? doc.source.title : '',
        school: doc.source ? doc.source.title : '',
        year: doc.year,
        volume: doc.volume,
        number: doc.articleNumber,
        pages: doc.pages,
    };

    const fields = {};

    entryFields[entryType].required.forEach(f => fields[f] = fieldsMapper[f]);
    entryFields[entryType].optional.forEach(f => {
        if (fieldsMapper[f]) fields[f] = fieldsMapper[f];
    });

    return formatBibtex(getBibtexKey(doc), fields, entryType);

}

function getBibtexKey(doc) {
    return 'SCTL-' + doc.id;
}

function getBibtexAuthors(doc) {
    const authors = doc.authorsStr.split(', ');

    return authors.map(a => {
        const tokens = a.split(/\s/);

        const {names, surnames} = tokens.reduce((res, val) => {
            if (val.includes('.'))
                res.surnames.push(val.replace(/\./g, '. ').trim());
            else
                res.names.push(val.trim());

            return res;
        }, {names: [], surnames: []});

        return names.join(' ') + ', ' + surnames.join(' ');
    }).join(' and ');
}

function formatBibtex(key, fields, entryType) {
    const fieldsArr = Object.keys(fields).map(f => '  ' + f + '={' + lescape(fields[f]) + '}');
    return '@' + entryType + '{' + key + ',\n' + fieldsArr.join(',\n') + '\n}';
}
<|endoftext|>


<commit_before>/* eslint-env browser*/
import _ from 'underscore';
import pathwaysActions from './pathways';
import rootRef from '../libs/firebase';

const C = require('../constants').default;
const moment = require('moment');

const responsesRef = rootRef.child('responses');

export function deleteStatus(questionId) {
  return { type: C.DELETE_RESPONSE_STATUS, data: { questionId, }, };
}

export function updateStatus(questionId, status) {
  return { type: C.UPDATE_RESPONSE_STATUS, data: { questionId, status, }, };
}

export function updateData(questionId, responses) {
  return { type: C.UPDATE_RESPONSE_DATA, data: { questionId, responses, }, };
}

function responsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('questionUID').equalTo(questionId);
}

function getQuestionLoadedStatusForGroupedResponses(groupedResponses) {
  const questionsKeys = _.keys(groupedResponses);
  const statuses = {};
  questionsKeys.forEach((key) => {
    statuses[key] = 'LOADED';
  });
  console.log(statuses);
  return statuses;
}

function groupResponsesByQuestion(snapshot) {
  const groupedResponses = {};
  for (const responseKey in snapshot) {
    if (snapshot.hasOwnProperty(responseKey)) {
      const response = snapshot[responseKey];
      if (response.questionUID) {
        if (groupedResponses[response.questionUID]) {
          groupedResponses[response.questionUID][responseKey] = response;
        } else {
          groupedResponses[response.questionUID] = {};
          groupedResponses[response.questionUID][responseKey] = response;
        }
      }
    }
  }
  return groupedResponses;
}

export function loadAllResponseData() {
  return (dispatch) => {
    responsesRef.once('value', (snapshot) => {
      const data = groupResponsesByQuestion(snapshot.val());
      const status = getQuestionLoadedStatusForGroupedResponses(data);
      dispatch({ type: 'BULK UPDATE', data: { data, status, }, });
    });
  };
}

export function loadResponseData(questionId) {
  return (dispatch) => {
    // dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      // dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function loadMultipleResponses(arrayOfQuestionIDs, cb) {
  return (dispatch) => {
    const newValues = {};
    const it = makeIterator(arrayOfQuestionIDs);
    const firstID = it.next().value;
    const doneTask = (newResponseData) => {
      dispatch({ type: 'BULK UPDATE', data: { data: newResponseData, status: {}, }, });
      cb();
    };
    loadResponseDataAndCallback(firstID, newValues, it, doneTask);
  };
}

function loadResponseDataAndCallback(questionId, dataHash, iterator, cb) {
  if (questionId === undefined) {
    cb(dataHash);
  } else {
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dataHash[questionId] = snapshot.val();
      loadResponseDataAndCallback(iterator.next().value, dataHash, iterator, cb);
    });
  }
}

export function loadResponseDataAndListen(questionId) {
  return (dispatch) => {
    dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).on('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function stopListeningToResponses(questionId) {
  return () => {
    responsesForQuestionRef(questionId).off('value');
  };
}

export function submitNewResponse(content, prid) {
  const newResponse = Object.assign({}, content,
    {
      createdAt: moment().format('x'),
    }
  );
  return (dispatch) => {
    // dispatch({ type: C.AWAIT_NEW_QUESTION_RESPONSE, });
    const newRef = responsesRef.push(newResponse, (error) => {
      // dispatch({ type: C.RECEIVE_NEW_QUESTION_RESPONSE, });
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
      } else {
        dispatch(pathwaysActions.submitNewPathway(newRef.key, prid, newResponse.questionUID));
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
      }
    });
  };
}

export function deleteResponse(qid, rid) {
  return (dispatch) => {
    responsesRef.child(rid).remove((error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Deletion failed! ${error}`, });
      } else {
        responsesForQuestionRef(qid).on('value', (data) => {
          const childResponseKeys = _.keys(data.val().responses).filter(
            key => data.val().responses[key].parentID === rid
          );
          childResponseKeys.forEach((childKey) => {
            dispatch(module.exports.deleteResponse(qid, childKey));
          });
        });
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully deleted!', });
      }
    });
  };
}

export function setUpdatedResponse(rid, content) {
  return (dispatch) => {
    responsesRef.child(rid).set(content, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Update failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Update successfully saved!', });
      }
    });
  };
}

export function submitResponseEdit(rid, content) {
  return (dispatch) => {
    responsesRef.child(rid).update(content, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Update failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Update successfully saved!', });
      }
    });
  };
}

export function incrementResponseCount(qid, rid, prid) {
  return (dispatch) => {
    const responseRef = responsesRef.child(rid);
    responseRef.child('/count').transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch(pathwaysActions.submitNewPathway(rid, prid, qid));
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully incremented!', });
      }
    });
    responseRef.child('parentID').once('value', (snap) => {
      if (snap.val()) {
        dispatch(incrementChildResponseCount(snap.val()));
      }
    });
  };
}

export function incrementChildResponseCount(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/childCount`).transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Child Response successfully incremented!', });
      }
    });
  };
}

export function removeLinkToParentID(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/parentID`).remove((error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Deletion failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully deleted!', });
      }
    });
  };
}

export function submitNewConceptResult(qid, rid, data) {
  return () => {
    responsesRef.child(`${rid}/conceptResults`).push(data, (error) => {
      if (error) {
        alert(`Submission failed! ${error}`);
      }
    });
  };
}

export function deleteConceptResult(qid, rid, crid) {
  return () => {
    responsesRef.child(`${rid}/conceptResults/${crid}`).remove((error) => {
      if (error) {
        alert(`Delete failed! ${error}`);
      }
    });
  };
}

function makeIterator(array) {
  let nextIndex = 0;

  return {
    next() {
      return nextIndex < array.length ?
               { value: array[nextIndex++], done: false, } :
               { done: true, };
    },
  };
}

export function getResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).once('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Loaded responses for ', questionID);
  });
}

export function listenToResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).on('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Listened to responses for ', questionID);
  });
}

function gradedResponsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('gradeIndex').equalTo(`human${questionId}`);
}

window.acc = gradedResponsesForQuestionRef;

export function getGradedResponsesForQuestionRef(questionID, callback) {
  gradedResponsesForQuestionRef(questionID).once('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Loaded responses for ', questionID);
  });
}

window.bcc = getGradedResponsesForQuestionRef;

window.ccc = (data) => {
  console.log('data');
  console.log(data);
  console.log(_.keys(data).length);
};
<commit_msg>Update response actions to get just graded responses if desired.<commit_after>/* eslint-env browser*/
import _ from 'underscore';
import pathwaysActions from './pathways';
import rootRef from '../libs/firebase';
import { hashToCollection } from '../libs/hashToCollection.js';

const C = require('../constants').default;
const moment = require('moment');

const responsesRef = rootRef.child('responses');

export function deleteStatus(questionId) {
  return { type: C.DELETE_RESPONSE_STATUS, data: { questionId, }, };
}

export function updateStatus(questionId, status) {
  return { type: C.UPDATE_RESPONSE_STATUS, data: { questionId, status, }, };
}

export function updateData(questionId, responses) {
  return { type: C.UPDATE_RESPONSE_DATA, data: { questionId, responses, }, };
}

function responsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('questionUID').equalTo(questionId);
}

function getQuestionLoadedStatusForGroupedResponses(groupedResponses) {
  const questionsKeys = _.keys(groupedResponses);
  const statuses = {};
  questionsKeys.forEach((key) => {
    statuses[key] = 'LOADED';
  });
  console.log(statuses);
  return statuses;
}

function groupResponsesByQuestion(snapshot) {
  const groupedResponses = {};
  for (const responseKey in snapshot) {
    if (snapshot.hasOwnProperty(responseKey)) {
      const response = snapshot[responseKey];
      if (response.questionUID) {
        if (groupedResponses[response.questionUID]) {
          groupedResponses[response.questionUID][responseKey] = response;
        } else {
          groupedResponses[response.questionUID] = {};
          groupedResponses[response.questionUID][responseKey] = response;
        }
      }
    }
  }
  return groupedResponses;
}

export function loadAllResponseData() {
  return (dispatch) => {
    responsesRef.once('value', (snapshot) => {
      const data = groupResponsesByQuestion(snapshot.val());
      const status = getQuestionLoadedStatusForGroupedResponses(data);
      dispatch({ type: 'BULK UPDATE', data: { data, status, }, });
    });
  };
}

export function loadResponseData(questionId) {
  return (dispatch) => {
    // dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      // dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function loadMultipleResponses(arrayOfQuestionIDs, cb) {
  return (dispatch) => {
    const newValues = {};
    const it = makeIterator(arrayOfQuestionIDs);
    const firstID = it.next().value;
    const doneTask = (newResponseData) => {
      dispatch({ type: 'BULK UPDATE', data: { data: newResponseData, status: {}, }, });
      cb();
    };
    loadResponseDataAndCallback(firstID, newValues, it, doneTask);
  };
}

function loadResponseDataAndCallback(questionId, dataHash, iterator, cb) {
  if (questionId === undefined) {
    cb(dataHash);
  } else {
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dataHash[questionId] = snapshot.val();
      loadResponseDataAndCallback(iterator.next().value, dataHash, iterator, cb);
    });
  }
}

export function loadResponseDataAndListen(questionId) {
  return (dispatch) => {
    dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).on('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function stopListeningToResponses(questionId) {
  return () => {
    responsesForQuestionRef(questionId).off('value');
  };
}

export function submitNewResponse(content, prid) {
  const newResponse = Object.assign({}, content,
    {
      createdAt: moment().format('x'),
    }
  );
  return (dispatch) => {
    // dispatch({ type: C.AWAIT_NEW_QUESTION_RESPONSE, });
    const newRef = responsesRef.push(newResponse, (error) => {
      // dispatch({ type: C.RECEIVE_NEW_QUESTION_RESPONSE, });
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
      } else {
        dispatch(pathwaysActions.submitNewPathway(newRef.key, prid, newResponse.questionUID));
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
      }
    });
  };
}

export function deleteResponse(qid, rid) {
  return (dispatch) => {
    responsesRef.child(rid).remove((error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Deletion failed! ${error}`, });
      } else {
        responsesForQuestionRef(qid).on('value', (data) => {
          const childResponseKeys = _.keys(data.val().responses).filter(
            key => data.val().responses[key].parentID === rid
          );
          childResponseKeys.forEach((childKey) => {
            dispatch(module.exports.deleteResponse(qid, childKey));
          });
        });
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully deleted!', });
      }
    });
  };
}

export function setUpdatedResponse(rid, content) {
  return (dispatch) => {
    responsesRef.child(rid).set(content, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Update failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Update successfully saved!', });
      }
    });
  };
}

export function submitResponseEdit(rid, content) {
  return (dispatch) => {
    responsesRef.child(rid).update(content, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Update failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Update successfully saved!', });
      }
    });
  };
}

export function incrementResponseCount(qid, rid, prid) {
  return (dispatch) => {
    const responseRef = responsesRef.child(rid);
    responseRef.child('/count').transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch(pathwaysActions.submitNewPathway(rid, prid, qid));
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully incremented!', });
      }
    });
    responseRef.child('parentID').once('value', (snap) => {
      if (snap.val()) {
        dispatch(incrementChildResponseCount(snap.val()));
      }
    });
  };
}

export function incrementChildResponseCount(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/childCount`).transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Child Response successfully incremented!', });
      }
    });
  };
}

export function removeLinkToParentID(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/parentID`).remove((error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Deletion failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully deleted!', });
      }
    });
  };
}

export function submitNewConceptResult(qid, rid, data) {
  return () => {
    responsesRef.child(`${rid}/conceptResults`).push(data, (error) => {
      if (error) {
        alert(`Submission failed! ${error}`);
      }
    });
  };
}

export function deleteConceptResult(qid, rid, crid) {
  return () => {
    responsesRef.child(`${rid}/conceptResults/${crid}`).remove((error) => {
      if (error) {
        alert(`Delete failed! ${error}`);
      }
    });
  };
}

function makeIterator(array) {
  let nextIndex = 0;

  return {
    next() {
      return nextIndex < array.length ?
               { value: array[nextIndex++], done: false, } :
               { done: true, };
    },
  };
}

export function getResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).once('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Loaded responses for ', questionID);
  });
}

export function listenToResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).on('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Listened to responses for ', questionID);
  });
}

function gradedResponsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('gradeIndex').equalTo(`human${questionId}`);
}

export function getGradedResponsesWithCallback(questionID, callback) {
  gradedResponsesForQuestionRef(questionID).once('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Loaded responses for ', questionID);
  });
}

export function findResponseByText(text, questionUID, cb) {
  responsesRef.orderByChild('text').equalTo(text).once('value', (snapshot) => {
    const response = _.findWhere(hashToCollection(snapshot.val()), { questionUID, });
    cb(response);
  });
}
<|endoftext|>


<commit_before>/*
The files in this directory are part of node-ansible-test, a javascript-based library.
Copyright (C) 2016 Daniel Bush
This program is distributed under the terms of the BSD-2-Clause License.
*/
// File for using cucumber-mink.
// Cucumber-mink will run webdriverio and give you a bunch of pre-defined step definitions.
// You just need something like phantomjs --webdriver or similar.
// See 'npm run test:acceptance'.

var Mink = require('cucumber-mink');
var username  = process.env.SAUCE_USERNAME;
var accessKey = process.env.SAUCE_ACCESS_KEY;

// Phantomjs - GhostDriver
var parameters = {
  driver: {
    desiredCapabilities: {
      browserName: 'internet explorer',
      platform: 'Windows 10',
      version: '11.103',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      build: process.env.TRAVIS_BUILD_NUMBER,
      name: 'integration'

      //username: username,
      //accessKey: accessKey
    },
    //host: username + ':' + accessKey + '@ondemand.saucelabs.com/wd/hub'
    //host: username + ':' + accessKey + '@ondemand.saucelabs.com',
    //host: username + ':' + accessKey + '@localhost',
    host: username + ':' + accessKey + '@localhost',
    port: 4445,
    path: '/wd/hub'
//"http://" + username + ":" + accessKey + "@ondemand.saucelabs.com:80/wd/hub"
  }
};
console.log('<<<< host', host);

module.exports = function () {
  Mink.init(this, parameters);
};
<commit_msg>Trying to add saucelabs.<commit_after>/*
The files in this directory are part of node-ansible-test, a javascript-based library.
Copyright (C) 2016 Daniel Bush
This program is distributed under the terms of the BSD-2-Clause License.
*/
// File for using cucumber-mink.
// Cucumber-mink will run webdriverio and give you a bunch of pre-defined step definitions.
// You just need something like phantomjs --webdriver or similar.
// See 'npm run test:acceptance'.

var Mink = require('cucumber-mink');
var username  = process.env.SAUCE_USERNAME;
var accessKey = process.env.SAUCE_ACCESS_KEY;

// Phantomjs - GhostDriver
var parameters = {
  driver: {
    desiredCapabilities: {
      browserName: 'internet explorer',
      platform: 'Windows 10',
      version: '11.103',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      build: process.env.TRAVIS_BUILD_NUMBER,
      name: 'integration'

      //username: username,
      //accessKey: accessKey
    },
    //host: username + ':' + accessKey + '@ondemand.saucelabs.com/wd/hub'
    //host: username + ':' + accessKey + '@ondemand.saucelabs.com',
    //host: username + ':' + accessKey + '@localhost',
    host: username + ':' + accessKey + '@localhost',
    port: 4445,
    path: '/wd/hub'
//"http://" + username + ":" + accessKey + "@ondemand.saucelabs.com:80/wd/hub"
  }
};
console.log('<<<< parameters', parameters);

module.exports = function () {
  Mink.init(this, parameters);
};
<|endoftext|>


<commit_before>var winston = require('winston');

var logger = function(api, next){

  var transports = [], i;
  for(i in api.config.logger.transports){
    var t = api.config.logger.transports[i];
    if(typeof t == 'function'){
      transports.push(t(api, winston));
    } else {
      transports.push(t);
    }
  }

  api.logger = new (winston.Logger)({
    // TODO We need to manually make these levels until winston switches the order back
    levels: {
      emerg: 7,
      alert: 6,
      crit: 5,
      error: 4,
      warning: 3,
      notice: 2,
      info: 1,
      debug: 0
    },
    transports: transports
  });

  if(api.config.logger.levels != null){
    api.logger.setLevels(winston.config.syslog.levels);
  }

  api.log = function(message, severity, data){
    if(severity == null || api.logger.levels[severity] == null){ severity = 'info' }
    if(data != null){
      api.logger.log(severity, message, data);
    } else {
      api.logger.log(severity, message);
    }
  }

  var logLevels = [];
  for(i in api.logger.levels){ logLevels.push(i) }

  api.log("*** starting actionhero ***", 'notice')
  api.log('Logger loaded.  Possible levels include: ', 'debug', logLevels);

  next();

}

/////////////////////////////////////////////////////////////////////
// exports
exports.logger = logger;
<commit_msg>Added support for winston's string interpolation<commit_after>var winston = require('winston');

var logger = function(api, next){

  var transports = [], i;
  for(i in api.config.logger.transports){
    var t = api.config.logger.transports[i];
    if(typeof t == 'function'){
      transports.push(t(api, winston));
    } else {
      transports.push(t);
    }
  }

  api.logger = new (winston.Logger)({
    // TODO We need to manually make these levels until winston switches the order back
    levels: {
      emerg: 7,
      alert: 6,
      crit: 5,
      error: 4,
      warning: 3,
      notice: 2,
      info: 1,
      debug: 0
    },
    transports: transports
  });

  if(api.config.logger.levels != null){
    api.logger.setLevels(winston.config.syslog.levels);
  }

  api.log = function(message, severity){
    if(severity == null || api.logger.levels[severity] == null){ severity = 'info' }
    var args = [ severity, message ];
    args.push.apply(args, Array.prototype.slice.call(arguments, 2));
    api.logger.log.apply(api.logger, args);
  }

  var logLevels = [];
  for(i in api.logger.levels){ logLevels.push(i) }

  api.log("*** starting actionhero ***", 'notice')
  api.log('Logger loaded.  Possible levels include: ', 'debug', logLevels);

  next();

}

/////////////////////////////////////////////////////////////////////
// exports
exports.logger = logger;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'

import StyledItem from './StyledItem'
import {design} from '../utilStyles'

/**
 * Wrap all <Button> and <ButtonLink> in <Item>.
 */
class Item extends React.Component {
  constructor(props) {
    super(props)
    this.ref = React.createRef()
    this.state = {isOpen: props.isOpen}
  }

  getChildren = () => {
    // eslint-disable-next-line
    return React.Children.map(this.props.children, child => {
      return React.cloneElement(child, {look: this.props.look})
    })
  }

  handleClickOutside = event => {
    if (!this.node.contains(event.target)) {
      this.toggleOpenState()
    }
  }

  toggleOpenState = () => {
    if (this.props.onToggle) {
      this.props.onToggle(this.state.isOpen)
    }

    if (this.props.isToggleable) {
      if (this.state.isOpen) {
        document.removeEventListener('mousedown', this.handleClickOutside, false)
      } else {
        document.addEventListener('mousedown', this.handleClickOutside, false)
      }

      this.setState(prevState => ({
        isOpen: !prevState.isOpen
      }))
    }
  }

  componentDidMount() {
    if (this.props.isToggleable && this.state.isOpen) {
      document.addEventListener('mousedown', this.handleClickOutside, false)
    }
  }

  componentWillUnmount() {
    if (this.props.isToggleable && this.state.isOpen) {
      document.removeEventListener('mousedown', this.handleClickOutside, false)
    }
  }

  render() {
    return (
      <StyledItem
        ref={this.ref}
        isOpen={this.state.isOpen}
      >
        {this.getChildren()}
      </StyledItem>
    )
  }
}

Item.defaultProps = {
  isOpen: true,
  isToggleable: false
}

Item.propTypes = {
  /**
   * Boolean to control if a submenu is initially opened. Default value is 'true'.
   */
  isOpen: PropTypes.bool,
  /**
   * Boolean to control if a user can change the open state. Default value is 'false'.
   */
  isToggleable: PropTypes.bool,
  /**
   * Look of menu item. Default value is 'flat'. Value is always overridden by parent element.
   */
  look: PropTypes.oneOf([design.look.FLAT, design.look.RAISED]),
  /**
   * Optional callback that is called, if menu changes state between open / close.
   */
  onToggle: PropTypes.func

}

export default Item
<commit_msg>refactor(tocco-ui): typo<commit_after>import PropTypes from 'prop-types'
import React from 'react'

import StyledItem from './StyledItem'
import {design} from '../utilStyles'

/**
 * Wrap all <Button> and <ButtonLink> in <Item>.
 */
class Item extends React.Component {
  constructor(props) {
    super(props)
    this.ref = React.createRef()
    this.state = {isOpen: props.isOpen}
  }

  getChildren = () => {
    // eslint-disable-next-line
    return React.Children.map(this.props.children, child => {
      return React.cloneElement(child, {look: this.props.look})
    })
  }

  handleClickOutside = event => {
    if (!this.node.contains(event.target)) {
      this.toggleOpenState()
    }
  }

  toggleOpenState = () => {
    if (this.props.onToggle) {
      this.props.onToggle(this.state.isOpen)
    }

    if (this.props.isToggleable) {
      if (this.state.isOpen) {
        document.removeEventListener('mousedown', this.handleClickOutside, false)
      } else {
        document.addEventListener('mousedown', this.handleClickOutside, false)
      }

      this.setState(prevState => ({
        isOpen: !prevState.isOpen
      }))
    }
  }

  componentDidMount() {
    if (this.props.isToggleable && this.state.isOpen) {
      document.addEventListener('mousedown', this.handleClickOutside, false)
    }
  }

  componentWillUnmount() {
    if (this.props.isToggleable && this.state.isOpen) {
      document.removeEventListener('mousedown', this.handleClickOutside, false)
    }
  }

  render() {
    return (
      <StyledItem
        ref={this.ref}
        isOpen={this.state.isOpen}
      >
        {this.getChildren()}
      </StyledItem>
    )
  }
}

Item.defaultProps = {
  isOpen: true,
  isToggleable: false
}

Item.propTypes = {
  /**
   * Boolean to control if a submenu is initially opened. Default value is 'true'.
   */
  isOpen: PropTypes.bool,
  /**
   * Boolean to control if a user can change the open state. Default value is 'false'.
   */
  isToggleable: PropTypes.bool,
  /**
   * Look of menu item. Default value is 'flat'. Value is always overridden by parent element.
   */
  look: PropTypes.oneOf([design.look.FLAT, design.look.RAISED]),
  /**
   * Optional callback when menu changes state between open / close.
   */
  onToggle: PropTypes.func
}

export default Item
<|endoftext|>


<commit_before>var Web3 = require("web3");

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

module.exports = {
  wrap: function(provider, options) {
    return wrapper.wrap(provider, options);
  },

  create: function(options) {
    var provider;

    if (options.provider && typeof options.provider == "function") {
      provider = options.provider();
    } else if (options.provider) {
      provider = options.provider;
    } else {
      provider = new Web3.providers.HttpProvider("http://" + options.host + ":" + options.port);
    }

    return this.wrap(provider, options);
  },

  test_connection: function(provider, callback) {
    var web3 = new Web3();
    var fail = new Error("Could not connect to your RPC client. Please check your RPC configuration.");

    web3.setProvider(provider);

    web3
      .eth
      .getCoinbase()
      .then(coinbase => callback(null, coinbase))
      .catch(e => callback(fail, null));
  }
};
<commit_msg>Enable a websockets config option<commit_after>var Web3 = require("web3");

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

module.exports = {
  wrap: function(provider, options) {
    return wrapper.wrap(provider, options);
  },

  create: function(options) {
    var provider;

    if (options.provider && typeof options.provider == "function") {
      provider = options.provider();
    } else if (options.provider) {
      provider = options.provider;
    } else if (options.websockets) {
      provider = new Web3.providers.WebsocketProvider("ws://" + options.host + ":" + options.port);
    } else {
      provider = new Web3.providers.HttpProvider("http://" + options.host + ":" + options.port);
    }

    return this.wrap(provider, options);
  },

  test_connection: function(provider, callback) {
    var web3 = new Web3();
    var fail = new Error("Could not connect to your RPC client. Please check your RPC configuration.");

    web3.setProvider(provider);

    web3
      .eth
      .getCoinbase()
      .then(coinbase => callback(null, coinbase))
      .catch(e => callback(fail, null));
  }
};
<|endoftext|>


<commit_before>/* globals module, require */
'use strict';
const MergeTrees = require('broccoli-merge-trees');
const Funnel = require('broccoli-funnel');
const Rollup = require('broccoli-rollup');
const path = require('path');
const typescript = require('broccoli-typescript-compiler').typescript;

module.exports = function () {
  const src = new MergeTrees([
    new Funnel(path.dirname(require.resolve('@types/qunit/package')), {
      include: [ 'index.d.ts' ],
      destDir: 'qunit'
    }),
    new Funnel(path.join(__dirname, '/lib'), {
      include: [ '**/*.ts' ],
      destDir: 'lib'
    }),
    new Funnel('tests', {
      include: [ '**/*.ts' ],
      destDir: 'tests'
    })
  ]);

  const compiled = typescript(src, {
    tsconfig: {
      compilerOptions: {
        module: 'es2015',
        target: 'es2015',
        moduleResolution: 'node',
        strictNullChecks: true,
        baseUrl: '.',
        paths: {
          backburner: ['lib/index.ts']
        }
      },
      files: ['qunit/index.d.ts', 'lib/index.ts', 'tests/index.ts']
    }
  });

  return new MergeTrees([
    new Rollup(compiled, {
      rollup: {
        entry: 'lib/index.js',
        targets: [{
          dest: 'es6/backburner.js',
          format: 'es',
        }, {
          dest: 'named-amd/backburner.js',
          format: 'amd',
          moduleId: 'backburner',
          exports: 'named'
        }, {
          dest: 'backburner.js',
          format: 'cjs'
        }]
      }
    }),
    new Rollup(compiled, {
      rollup: {
        entry: 'tests/index.js',
        external: ['backburner'],
        targets: [{
          dest: 'tests/tests.js',
          format: 'amd',
          moduleId: 'backburner-tests'
        }]
      },
      annotation: 'tests/tests.js'
    }),
    new Funnel(path.dirname(require.resolve('qunitjs')), {
      annotation: 'tests/qunit.{js,css}',
      files: ['qunit.css', 'qunit.js'],
      destDir: 'tests'
    }),
    new Funnel(path.dirname(require.resolve('loader.js')), {
      annotation: 'tests/loader.js',
      files: ['loader.js'],
      destDir: 'tests'
    }),
    new Funnel(path.join(__dirname, '/tests'), {
      files: ['index.html'],
      destDir: 'tests'
    })
  ], {
    annotation: 'dist'
  });
};
<commit_msg>Remove over filtering<commit_after>/* globals module, require */
'use strict';
const MergeTrees = require('broccoli-merge-trees');
const Funnel = require('broccoli-funnel');
const Rollup = require('broccoli-rollup');
const path = require('path');
const typescript = require('broccoli-typescript-compiler').typescript;

module.exports = function () {
  const src = new MergeTrees([
    new Funnel(path.dirname(require.resolve('@types/qunit/package')), {
      include: [ 'index.d.ts' ],
      destDir: 'qunit'
    }),
    new Funnel(__dirname + '/lib', {
      destDir: 'lib'
    }),
    new Funnel(__dirname + '/tests', {
      destDir: 'tests'
    })
  ]);

  const compiled = typescript(src, {
    tsconfig: {
      compilerOptions: {
        module: 'es2015',
        target: 'es2015',
        moduleResolution: 'node',
        strictNullChecks: true,
        baseUrl: '.',
        paths: {
          backburner: ['lib/index.ts']
        }
      },
      files: ['qunit/index.d.ts', 'lib/index.ts', 'tests/index.ts']
    }
  });

  return new MergeTrees([
    new Rollup(compiled, {
      rollup: {
        entry: 'lib/index.js',
        targets: [{
          dest: 'es6/backburner.js',
          format: 'es',
        }, {
          dest: 'named-amd/backburner.js',
          format: 'amd',
          moduleId: 'backburner',
          exports: 'named'
        }, {
          dest: 'backburner.js',
          format: 'cjs'
        }]
      }
    }),
    new Rollup(compiled, {
      rollup: {
        entry: 'tests/index.js',
        external: ['backburner'],
        targets: [{
          dest: 'tests/tests.js',
          format: 'amd',
          moduleId: 'backburner-tests'
        }]
      },
      annotation: 'tests/tests.js'
    }),
    new Funnel(path.dirname(require.resolve('qunitjs')), {
      annotation: 'tests/qunit.{js,css}',
      files: ['qunit.css', 'qunit.js'],
      destDir: 'tests'
    }),
    new Funnel(path.dirname(require.resolve('loader.js')), {
      annotation: 'tests/loader.js',
      files: ['loader.js'],
      destDir: 'tests'
    }),
    new Funnel(__dirname + '/tests', {
      files: ['index.html'],
      destDir: 'tests'
    })
  ], {
    annotation: 'dist'
  });
};
<|endoftext|>


<commit_before>/* eslint-env node */
const EmberAddon = require('ember-cli/lib/broccoli/ember-addon')
const Funnel   = require('broccoli-funnel')
const fs       = require('fs')

const environment   = process.env.EMBER_ENV || 'development'
const defaultTarget = environment === 'production' ? 'prod' : 'localhost-4200'
const target        = process.env.HB_DEPLOY_TARGET || defaultTarget
const dotEnvFile    = `./.env-${target}`
if (!fs.existsSync(dotEnvFile)) throw new Error(`ember-cli-build.js: dot-env file not found: ${dotEnvFile}`)

module.exports = function (defaults) {
  var app = new EmberAddon(defaults, {
    babel : {
      plugins : [
        'transform-object-rest-spread',
      ],
    },

    'ember-cli-babel' : {
      // includePolyfill : true,
    },

    dotEnv : {
      clientAllowedKeys : [
        'HB_DEPLOY_TARGET',
        'HB_GITHUB_CLIENT_ID',
        'HB_GATEKEEPER_URL',
      ],
      path : dotEnvFile,
    },

    nodeModulesToVendor : [
      new Funnel('node_modules/lodash', {
        destDir : 'lodash',
        files   : ['lodash.js'],
      }),
    ],
  })

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree()
}
<commit_msg>Don't crash on missing dot-env file unless its name was explicitly provided<commit_after>/* eslint-env node */
const EmberAddon = require('ember-cli/lib/broccoli/ember-addon')
const Funnel   = require('broccoli-funnel')
const fs       = require('fs')

const environment   = process.env.EMBER_ENV || 'development'
const defaultTarget = environment === 'production' ? 'prod' : 'localhost-4200'
const target        = process.env.HB_DEPLOY_TARGET || defaultTarget
const dotEnvFile    = `./.env-${target}`

if (!fs.existsSync(dotEnvFile)) {
  if (process.env.HB_DEPLOY_TARGET) {
    throw new Error(`dot-env file specified but not found: ${dotEnvFile}`)
  } else {
    console.warn(`default dot-env file not found: ${dotEnvFile}, assuming env vars are passed manually`)
  }
}

module.exports = function (defaults) {
  const options = {
    babel : {
      plugins : [
        'transform-object-rest-spread',
      ],
    },

    'ember-cli-babel' : {
      // includePolyfill : true,
    },

    nodeModulesToVendor : [
      new Funnel('node_modules/lodash', {
        destDir : 'lodash',
        files   : ['lodash.js'],
      }),
    ],
  }

  if (fs.existsSync(dotEnvFile)) {
    options.dotEnv = {
      clientAllowedKeys : [
        'HB_DEPLOY_TARGET',
        'HB_GITHUB_CLIENT_ID',
        'HB_GATEKEEPER_URL',
      ],
      path : dotEnvFile,
    }
  }

  const app = new EmberAddon(defaults, options)

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree()
}
<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { _ } from 'meteor/erasaur:meteor-lodash';
import SimpleSchema from 'simpl-schema';
import { Courses } from '../../../api/course/CourseCollection.js';
import { MentorQuestions } from '../../../api/mentor/MentorQuestionCollection';
import { Opportunities } from '../../../api/opportunity/OpportunityCollection.js';
import { Reviews } from '../../../api/review/ReviewCollection.js';
import { updateMethod } from '../../../api/base/BaseCollection.methods';
import { Semesters } from '../../../api/semester/SemesterCollection';
import { Slugs } from '../../../api/slug/SlugCollection';
import { Users } from '../../../api/user/UserCollection';
import * as FormUtils from '../admin/form-fields/form-field-utilities.js';
import { getRouteUserName } from './route-user-name';
import { appLog } from '../../../api/log/AppLogCollection';

const noSlugSchema = new SimpleSchema({
  moderatorComments: { type: String, optional: true },
});

const withSlugSchema = new SimpleSchema({
  moderatorComments: { type: String, optional: true },
  slug: { type: String, optional: true, custom: FormUtils.slugFieldValidator },
});

Template.Moderation.onCreated(function ModerationOnCreated() {
  FormUtils.setupFormWidget(this, noSlugSchema);
  FormUtils.setupFormWidget(this, withSlugSchema);
});

/**
 * Return the data from the submitted form corresponding to the fields in the passed schema.
 * @param schema The simple schema.
 * @param event The event holding the form data.
 * @returns {Object} An object whose keys are the schema keys and whose values are the corresponding form values.
 * @memberOf ui/components/shared
 */
function getSchemaDataFromEvent(schema, event) {
  const eventData = {};
  _.forEach(schema._firstLevelSchemaKeys, function (key) {
    eventData[key] = event.target.form[key].value;
  });
  return eventData;
}

Template.Moderation.helpers({
  noSlug(question) {
    return !question.slugID;
  },
  moderatorComments(review) {
    return review.moderatorComments;
  },
  pendingCourseReviews() {
    return Reviews.find({ moderated: false, reviewType: 'course' }).fetch();
  },
  pendingOpportunityReviews() {
    return Reviews.find({ moderated: false, reviewType: 'opportunity' }).fetch();
  },
  pendingQuestions() {
    return MentorQuestions.find({ moderated: false, visible: false }).fetch();
  },
  rating(review) {
    return review.rating;
  },
  revieweeName(review) {
    let reviewee;
    if (review.reviewType === 'course') {
      reviewee = Courses.findDoc(review.revieweeID);
    } else if (review.reviewType === 'opportunity') {
      reviewee = Opportunities.findDoc(review.revieweeID);
    }
    return reviewee.name;
  },
  semester(review) {
    return Semesters.toString(review.semesterID);
  },
  slug(question) {
    if (question.slugID) {
      return Slugs.findDoc(question.slugID).name;
    }
    return '';
  },
  studentName(review) {
    return Users.getFullName(review.studentID);
  },
  studentComments(review) {
    return review.comments;
  },
});

Template.Moderation.events({
  'click button': function clickButton(event, instance) {
    event.preventDefault();
    const split = event.target.id.split('-');
    const itemID = split[0];
    let newData;
    let item;
    if (split[1] === 'review') {
      newData = getSchemaDataFromEvent(noSlugSchema, event);
      instance.context.reset();
      noSlugSchema.clean(newData);
    } else if (split[3]) {
      newData = getSchemaDataFromEvent(withSlugSchema, event);
      instance.context.reset();
      withSlugSchema.clean(newData);
    } else {
      newData = getSchemaDataFromEvent(noSlugSchema, event);
      instance.context.reset();
      noSlugSchema.clean(newData);
    }
    instance.context.validate(newData);
    if (instance.context.isValid()) {
      let message = `${getRouteUserName()}`;
      if (split[1] === 'review') {
        item = Reviews.findDoc(itemID);
      } else {
        item = MentorQuestions.findDoc(itemID);
      }
      if (split[2] === 'accept') {
        item.moderated = true;
        item.visible = true;
        message = `${message} accepted`;
      } else {
        item.moderated = true;
        item.visible = false;
        message = `${message} rejected`;
      }
      const moderatorComments = newData.moderatorComments;
      const moderated = item.moderated;
      const visible = item.visible;
      if (split[1] === 'review') {
        const updateData = { id: itemID, moderated, visible, moderatorComments };
        updateMethod.call({ collectionName: Reviews.getCollectionName(), updateData });
        const studentName = Users.getProfile(Reviews.getDoc(itemID).studentID).username;
        message = `${message} ${studentName}'s review`;
      } else {
        const updateData = { id: itemID, moderated, visible, moderatorComments };
        updateMethod.call({ collectionName: MentorQuestions.getCollectionName(), updateData });
        const studentName = Users.getProfile(MentorQuestions.getDoc(itemID).studentID).username;
        message = `${message} ${studentName}'s mentor question`;
      }
      message = `${message} with comments: '${moderatorComments}'.`;
      appLog.info(message);
    } else {
      FormUtils.indicateError(instance);
    }
  },
});
<commit_msg>add whitespace<commit_after>import { Template } from 'meteor/templating';
import { _ } from 'meteor/erasaur:meteor-lodash';
import SimpleSchema from 'simpl-schema';
import { Courses } from '../../../api/course/CourseCollection.js';
import { MentorQuestions } from '../../../api/mentor/MentorQuestionCollection';
import { Opportunities } from '../../../api/opportunity/OpportunityCollection.js';
import { Reviews } from '../../../api/review/ReviewCollection.js';
import { updateMethod } from '../../../api/base/BaseCollection.methods';
import { Semesters } from '../../../api/semester/SemesterCollection';
import { Slugs } from '../../../api/slug/SlugCollection';
import { Users } from '../../../api/user/UserCollection';
import * as FormUtils from '../admin/form-fields/form-field-utilities.js';
import { getRouteUserName } from './route-user-name';
import { appLog } from '../../../api/log/AppLogCollection';

const noSlugSchema = new SimpleSchema({
  moderatorComments: { type: String, optional: true },
});

const withSlugSchema = new SimpleSchema({
  moderatorComments: { type: String, optional: true },
  slug: { type: String, optional: true, custom: FormUtils.slugFieldValidator },
});

Template.Moderation.onCreated(function ModerationOnCreated() {
  FormUtils.setupFormWidget(this, noSlugSchema);
  FormUtils.setupFormWidget(this, withSlugSchema);
});

/**
 * Return the data from the submitted form corresponding to the fields in the passed schema.
 * @param schema The simple schema.
 * @param event The event holding the form data.
 * @returns {Object} An object whose keys are the schema keys and whose values are the corresponding form values.
 * @memberOf ui/components/shared
 */
function getSchemaDataFromEvent(schema, event) {
  const eventData = {};
  _.forEach(schema._firstLevelSchemaKeys, function (key) {
    eventData[key] = event.target.form[key].value;
  });
  return eventData;
}

Template.Moderation.helpers({
  noSlug(question) {
    return !question.slugID;
  },
  moderatorComments(review) {
    return review.moderatorComments;
  },
  pendingCourseReviews() {
    return Reviews.find({ moderated: false, reviewType: 'course' }).fetch();
  },
  pendingOpportunityReviews() {
    return Reviews.find({ moderated: false, reviewType: 'opportunity' }).fetch();
  },
  pendingQuestions() {
    return MentorQuestions.find({ moderated: false, visible: false }).fetch();
  },
  rating(review) {
    return review.rating;
  },
  revieweeName(review) {
    let reviewee;
    if (review.reviewType === 'course') {
      reviewee = Courses.findDoc(review.revieweeID);
    } else if (review.reviewType === 'opportunity') {
      reviewee = Opportunities.findDoc(review.revieweeID);
    }
    return reviewee.name;
  },
  semester(review) {
    return Semesters.toString(review.semesterID);
  },
  slug(question) {
    if (question.slugID) {
      return Slugs.findDoc(question.slugID).name;
    }
    return '';
  },
  studentName(review) {
    return Users.getFullName(review.studentID);
  },
  studentComments(review) {
    return review.comments;
  },
});

Template.Moderation.events({
  'click button': function clickButton(event, instance) {
    event.preventDefault();

    const split = event.target.id.split('-');
    const itemID = split[0];
    let newData;
    let item;
    if (split[1] === 'review') {
      newData = getSchemaDataFromEvent(noSlugSchema, event);
      instance.context.reset();
      noSlugSchema.clean(newData);
    } else if (split[3]) {
      newData = getSchemaDataFromEvent(withSlugSchema, event);
      instance.context.reset();
      withSlugSchema.clean(newData);
    } else {
      newData = getSchemaDataFromEvent(noSlugSchema, event);
      instance.context.reset();
      noSlugSchema.clean(newData);
    }
    instance.context.validate(newData);
    if (instance.context.isValid()) {
      let message = `${getRouteUserName()}`;
      if (split[1] === 'review') {
        item = Reviews.findDoc(itemID);
      } else {
        item = MentorQuestions.findDoc(itemID);
      }
      if (split[2] === 'accept') {
        item.moderated = true;
        item.visible = true;
        message = `${message} accepted`;
      } else {
        item.moderated = true;
        item.visible = false;
        message = `${message} rejected`;
      }
      const moderatorComments = newData.moderatorComments;
      const moderated = item.moderated;
      const visible = item.visible;
      if (split[1] === 'review') {
        const updateData = { id: itemID, moderated, visible, moderatorComments };
        updateMethod.call({ collectionName: Reviews.getCollectionName(), updateData });
        const studentName = Users.getProfile(Reviews.getDoc(itemID).studentID).username;
        message = `${message} ${studentName}'s review`;
      } else {
        const updateData = { id: itemID, moderated, visible, moderatorComments };
        updateMethod.call({ collectionName: MentorQuestions.getCollectionName(), updateData });
        const studentName = Users.getProfile(MentorQuestions.getDoc(itemID).studentID).username;
        message = `${message} ${studentName}'s mentor question`;
      }
      message = `${message} with comments: '${moderatorComments}'.`;
      appLog.info(message);
    } else {
      FormUtils.indicateError(instance);
    }
  },
});
<|endoftext|>


<commit_before>var Funnel = require('broccoli-funnel');
var mergeTrees = require('broccoli-merge-trees');
var Babel = require('broccoli-babel-transpiler');
var concat   = require('broccoli-concat');
var eslint = require('broccoli-lint-eslint');
var existsSync = require('exists-sync');

module.exports = function(options) {
  var project = options.project;
  project.initializeAddons();

  function addonTreesFor(type) {
    return project.addons.map(function(addon) {
      if (addon.treeFor) {
        return addon.treeFor(type);
      }
    }).filter(Boolean);
  }

  // --- Dependencies ---
  var addonVendorTrees = mergeTrees(addonTreesFor('vendor'));
  var loader = new Funnel(addonVendorTrees, {
    srcDir: 'loader',
    files: ['loader.js'],
    destDir: '/assets'
  });

  // --- Project Files  ---

  var lib = new Funnel('lib', {
    srcDir: '/',
    include: ['**/*.js'],
    destDir: '/'
  });

  var tests = new Funnel('tests', {
    srcDir: '/',
    include: ['**/*.js'],
    destDir: '/tests'
  });

  var libESLint = eslint(lib, { testGenerator: 'qunit' });
  var testESLint = eslint(tests, { testGenerator: 'qunit' });

  var mainTrees = [lib, tests, libESLint, testESLint];
  var addonTree = mergeTrees(addonTreesFor('addon'));
  var addonModulesTree = new Funnel(addonTree, {
    srcDir: 'modules',
    destDir: '/',
    allowEmpty: true,
  });

  var main = mergeTrees(mainTrees.concat(addonModulesTree));
  // --- Compile ES6 modules ---

  main = new Babel(main, {
    loose: true,
    moduleIds: true,
    modules: 'amdStrict'
  });

  main = concat(main, {
    inputFiles: ['**/*.js'],
    outputFile: '/assets/ember-test-helpers-tests.amd.js'
  });

  // --- Select and concat vendor / support files ---

  var inputFiles = ['jquery/dist/jquery.js',
                    'ember/ember-template-compiler.js',
                    'ember/ember.debug.js',
                    'FakeXMLHttpRequest/fake_xml_http_request.js',
                    'route-recognizer/dist/route-recognizer.js',
                    'pretender/pretender.js'];

  if (existsSync('bower_components/ember-data/ember-data.js')) {
    inputFiles.push('ember-data/ember-data.js');
  }

  var vendor = concat('bower_components', {
    headerFiles: inputFiles,
    outputFile: '/assets/vendor.js'
  });

  var qunit = new Funnel('bower_components', {
    srcDir: '/qunit/qunit',
    files: ['qunit.js', 'qunit.css'],
    destDir: '/assets'
  });

  var testIndex = new Funnel('tests', {
    srcDir: '/',
    files: ['index.html'],
    destDir: '/tests'
  });

  var testSupport = concat('bower_components', {
    headerFiles: ['ember-cli-shims/app-shims.js',
                 'ember-cli-test-loader/test-loader.js'],
    outputFile: '/assets/test-support.js'
  });

  return mergeTrees([main, vendor, testIndex, qunit, loader, testSupport]);
};
<commit_msg>Updates to ensure ember-data from npm works properly.<commit_after>var Funnel = require('broccoli-funnel');
var mergeTrees = require('broccoli-merge-trees');
var Babel = require('broccoli-babel-transpiler');
var concat   = require('broccoli-concat');
var eslint = require('broccoli-lint-eslint');
var existsSync = require('exists-sync');

module.exports = function(options) {
  var project = options.project;
  project.initializeAddons();

  function eachAddonInvoke(method, args) {
    return project.addons.map(function(addon) {
      if (addon[method]) {
        return addon[method].apply(addon, args);
      }
    });
  }

  function addonTreesFor(type) {
    return eachAddonInvoke('treeFor', [type]).filter(Boolean);
  }

  var fakeApp = {
    import() { }
  };

  project.addons.map(function(addon) { addon.app = fakeApp; });

  eachAddonInvoke('included', [{ import() { }}]);

  // --- Dependencies ---
  var addonVendorTrees = mergeTrees(addonTreesFor('vendor'));
  var loader = new Funnel(addonVendorTrees, {
    srcDir: 'loader',
    files: ['loader.js'],
    destDir: '/assets'
  });

  // --- Project Files  ---

  var lib = new Funnel('lib', {
    srcDir: '/',
    include: ['**/*.js'],
    destDir: '/'
  });

  var tests = new Funnel('tests', {
    srcDir: '/',
    include: ['**/*.js'],
    destDir: '/tests'
  });

  var libESLint = eslint(lib, { testGenerator: 'qunit' });
  var testESLint = eslint(tests, { testGenerator: 'qunit' });

  var mainTrees = [lib, tests, libESLint, testESLint];
  var addonTree = mergeTrees(addonTreesFor('addon'));

  var main = mergeTrees(mainTrees);
  // --- Compile ES6 modules ---

  main = new Babel(main, {
    loose: true,
    moduleIds: true,
    modules: 'amdStrict'
  });

  main = mergeTrees([main, addonTree]);

  main = concat(main, {
    inputFiles: ['**/*.js'],
    outputFile: '/assets/ember-test-helpers-tests.amd.js'
  });

  // --- Select and concat vendor / support files ---

  var inputFiles = ['jquery/dist/jquery.js',
                    'ember/ember-template-compiler.js',
                    'ember/ember.debug.js',
                    'FakeXMLHttpRequest/fake_xml_http_request.js',
                    'route-recognizer/dist/route-recognizer.js',
                    'pretender/pretender.js'];

  if (existsSync('bower_components/ember-data/ember-data.js')) {
    inputFiles.push('ember-data/ember-data.js');
  }

  var vendor = concat('bower_components', {
    headerFiles: inputFiles,
    outputFile: '/assets/vendor.js'
  });

  var qunit = new Funnel('bower_components', {
    srcDir: '/qunit/qunit',
    files: ['qunit.js', 'qunit.css'],
    destDir: '/assets'
  });

  var testIndex = new Funnel('tests', {
    srcDir: '/',
    files: ['index.html'],
    destDir: '/tests'
  });

  var testSupport = concat('bower_components', {
    headerFiles: ['ember-cli-shims/app-shims.js',
                 'ember-cli-test-loader/test-loader.js'],
    outputFile: '/assets/test-support.js'
  });

  return mergeTrees([main, vendor, testIndex, qunit, loader, testSupport]);
};
<|endoftext|>


<commit_before>/* globals cordova */

import Ember from 'ember';

const { run } = Ember;

export function initialize(app) {
  let config = app.__container__.lookupFactory('config:environment');
  let env = config.environment;

  if (config.cordova && config.cordova.reloadUrl &&
     (env === 'development' || env === 'test')) {

    let url = config.cordova.reloadUrl;
    if (window.location.href.indexOf('file://') > -1) {
      run.later(function() {
        window.location.replace(url);
      }, 50);
    }
  }
};

export default {
  name: 'cordova:in-app-livereload',
  initialize: initialize
};
<commit_msg>style: rm unused global declaration<commit_after>import Ember from 'ember';

const { run } = Ember;

export function initialize(app) {
  let config = app.__container__.lookupFactory('config:environment');
  let env = config.environment;

  if (config.cordova && config.cordova.reloadUrl &&
     (env === 'development' || env === 'test')) {

    let url = config.cordova.reloadUrl;
    if (window.location.href.indexOf('file://') > -1) {
      run.later(function() {
        window.location.replace(url);
      }, 50);
    }
  }
};

export default {
  name: 'cordova:in-app-livereload',
  initialize: initialize
};
<|endoftext|>


<commit_before>'use strict';

const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  let app = new EmberAddon(defaults, {
    // Add options here
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree();
};
<commit_msg>Try fixing the production build/deploy<commit_after>'use strict';

const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  let app = new EmberAddon(defaults, {
    // Add options here
    'ember-cli-uglify': {
      uglify: {
        compress: {
          collapse_vars: false
        }
      }
    },
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree();
};
<|endoftext|>


<commit_before>/*jshint node:true*/
/* global require, module */
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  var app = new EmberAddon(defaults, {
    jscsOptions: {
      enabled: true,
      esnext: true,
      configPath: '.jscsrc'
    }
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  if (app.env !== 'production') {
    app.import('bower_components/jquery-mockjax/jquery.mockjax.js');
  }

  return app.toTree();
};
<commit_msg>Fix configPath for jscs<commit_after>/*jshint node:true*/
/* global require, module */
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  var app = new EmberAddon(defaults, {
    jscsOptions: {
      enabled: true,
      esnext: true,
      configPath: './.jscsrc'
    }
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  if (app.env !== 'production') {
    app.import('bower_components/jquery-mockjax/jquery.mockjax.js');
  }

  return app.toTree();
};
<|endoftext|>


<commit_before>/* eslint-env node */
const EmberAddon = require('ember-cli/lib/broccoli/ember-addon')

module.exports = function (defaults) {
  const app = new EmberAddon(defaults, {
    babel: {
      optional: ['es7.decorators']
    },
    snippetSearchPaths: [
      'addon',
      'tests/dummy'
    ],
    svgstore: {
       files: [{
         sourceDirs: 'tests/dummy/frost-icon-svgs',
         outputFile: '/assets/icon-packs/dummy.svg'
       }]
     }
  })

  return app.toTree()
}
<commit_msg>Add svgstoreOpts<commit_after>/* eslint-env node */
const EmberAddon = require('ember-cli/lib/broccoli/ember-addon')

module.exports = function (defaults) {
  const app = new EmberAddon(defaults, {
    babel: {
      optional: ['es7.decorators']
    },
    snippetSearchPaths: [
      'addon',
      'tests/dummy'
    ],
    svgstore: {
      files: [{
        sourceDirs: 'tests/dummy/frost-icon-svgs',
        outputFile: '/assets/icon-packs/dummy.svg'
      }],
      svgstoreOpts: {
        copyAttrs: ['preserveAspectRatio']
      }
    }
  })

  return app.toTree()
}
<|endoftext|>