<commit_before>'use strict';

/**
 * Triangulr class
 * instructions will follow, in an other commit, it's late now
 *
 * @param	string					containerId			Container DOM id
 */
function Triangulr (containerId) {
	this.container = document.getElementById(containerId);
	if (!this.container) {
		throw new Error ('Triangulr container "' + containerId + '" does not exists.');
	}
}

Triangulr.prototype.DEFAULT_COLOR = '#000';
Triangulr.prototype.BLANK_COLOR = '#FFF';

/**
 * Triangulr class
 * instructions will follow, in an other commit, it's late now
 *
 * @param	int							width						Triangle height
 * @param	int							height					Triangle height
 * @param	int							triangleHeight	Triangle height
 */
Triangulr.prototype.setCanvas = function (width, height, triangleWidth, isLandscape) {
	// Save input
	this.isLandscape = isLandscape;
	this.mapWidth = width;
	this.mapHeight = height;

	this.triangleWidth = triangleWidth;
	this.triangleHeight = Math.sqrt(Math.pow(triangleWidth, 2) - Math.pow(triangleWidth / 2, 2));
	this.triangleHeight = Math.round(this.triangleHeight);

	this.lines = [];
	this.exportData = [];
	this.pickedColor = this.DEFAULT_COLOR;

	this.lineMapping();
	this.createTriangles();
	this.generateDom();
}

/**
 * lineMapping
 * generate this.lines from the contructor info
 *
 */
Triangulr.prototype.lineMapping = function () {

	var x, y, line;
	var parity = this.triangleWidth / 4;
	var gap = parity;

	if (this.isLandscape) {
		for(y = 0; y<=this.mapHeight; y++) {
			line = [];
			for(x = 0; x<=this.mapWidth; x++) {
				line.push({
					x: x * this.triangleWidth + parity + gap,
					y: y * this.triangleHeight
				});
			}
			this.lines.push(line);
			parity *= -1;
		}
	}
	else {
		for(y = 0; y<=this.mapWidth; y++) {
			line = [];
			for(x = 0; x<=this.mapHeight; x++) {
				line.push({
					x: y * this.triangleHeight,
					y: x * this.triangleWidth + parity + gap
				});
			}
			this.lines.push(line);
			parity *= -1;
		}
	}
};

/**
 * createTriangles
 * use points form this.lines to generate triangles
 * and put them into this.exportData
 *
 */
Triangulr.prototype.createTriangles = function () {

	var x, parity, lineA, lineB, aIndex, bIndex, points, poly, pointsList;
	var counter = 0;
	var lineParite = true;
	this.exportData = [];

	for(x = 0; x<this.lines.length -1; x++) {
		lineA = this.lines[x];
		lineB = this.lines[x+1];
		aIndex = 0;
		bIndex = 0;
		parity = lineParite;

		do {
			// Get the good points
			points = [lineA[aIndex], lineB[bIndex]];
			if (parity) {
				bIndex++;
				points.push(lineB[bIndex]);
			}
			else {
				aIndex++;
				points.push(lineA[aIndex]);
			}
			parity = !parity;

			// Save the triangle
			pointsList = [
				points[0],
				points[1],
				points[2]
			];
			this.exportData.push({
				points: pointsList
			});
			counter++;
		} while (aIndex != lineA.length-1 && bIndex != lineA.length-1);

		lineParite = !lineParite;
	}
};

/**
 * generateDom
 * generate the SVG object from exportData content
 *
 * @return {[object]} Svg DOM object
 */
Triangulr.prototype.generateDom = function () {
	if (this.svgTag) {
		this.container.appendChild(this.svgTag);
		this.svgTag.remove();
	}

	var i, j, data, points, polygon;
	var svgTag = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
	var output = '';

	svgTag.setAttribute('version', '1.1');
	svgTag.setAttribute('preserveAspectRatio', 'xMinYMin slice');

	if (this.isLandscape) {
		svgTag.setAttribute('width', this.mapWidth * this.triangleWidth);
		svgTag.setAttribute('height', this.mapHeight * this.triangleHeight);
		svgTag.setAttribute('viewBox', '0 0 ' + (this.mapWidth * this.triangleWidth) + ' ' + (this.mapHeight * this.triangleHeight));
	}
	else {
		svgTag.setAttribute('width', this.mapWidth * this.triangleHeight);
		svgTag.setAttribute('height', this.mapHeight * this.triangleWidth);
		svgTag.setAttribute('viewBox', '0 0 ' + (this.mapWidth * this.triangleHeight) + ' ' + (this.mapHeight * this.triangleWidth));
	}

	this.color = false;
	svgTag.addEventListener('mousedown', function (e) {
		this.color = this.pickedColor;
		listener(e);
	}.bind(this));
	window.addEventListener('mouseup', function () {
		this.color = false;
	}.bind(this));

	var listener = function (e) {
		var rel = parseInt(e.target.getAttribute('rel'), 10);
		if (this.color === false || isNaN(rel)) {
			return;
		}
		this.exportData[rel].color = this.color;
		e.target.setAttribute('fill', this.color || this.BLANK_COLOR);
	}.bind(this);

	for(i in this.exportData) {
		data = this.exportData[i];
		polygon = document.createElementNS('http://www.w3.org/2000/svg','path');
		points   = 'M' + data.points[0].x + ' ' + data.points[0].y + ' ';
		points  += 'L' + data.points[1].x + ' ' + data.points[1].y + ' ';
		points  += 'L' + data.points[2].x + ' ' + data.points[2].y + ' Z';
		polygon.setAttribute('d', points);
		polygon.setAttribute('fill', data.color || this.BLANK_COLOR);
		polygon.setAttribute('rel', i);
		polygon.addEventListener('mousemove', listener);

		svgTag.appendChild(polygon);
	}

	this.svgTag = svgTag;
	this.container.appendChild(svgTag);
	return svgTag;
};

Triangulr.prototype.export = function () {
	return {
		isLandscape: this.isLandscape,
		mapWidth: this.mapWidth,
		mapHeight: this.mapHeight,
		mapData: this.exportData.map(function (e) {return e.color || null}),
		triangleWidth: this.triangleWidth
	};
};

Triangulr.prototype.import = function (data) {
	this.setCanvas(
		data.mapWidth,
		data.mapHeight,
		data.triangleWidth,
		data.isLandscape
	);

	for (var i in data.mapData) {
		this.exportData[i].color = data.mapData[i];
	}

	for (var i = 0; i < this.svgTag.childNodes.length; i++) {
		this.svgTag.childNodes[i].setAttribute('fill', this.exportData[i].color || this.BLANK_COLOR);
	}
};

Triangulr.prototype.exportSVG = function () {
	return this.svgTag.outerHTML;
};

/**
 * WARNING!!!
 * The following code is a failing work in progress
 */
Triangulr.prototype.transformer = function () {
	var blob, pathObj, pathToMerge, lineIndex, pathIndex;
	var lineLength = this.mapWidth * 2 - 1;

	console.log('linelength: ', lineLength);

	for (var i = 1; i < this.exportData.length; i++) {
		pathObj = this.exportData[i];
		lineIndex = Math.floor(i / lineLength);
		pathIndex = i % lineLength;

		console.log(i);

		// Merge with the previous item ()
		if (pathIndex !== 0) {
			this.mergePath(this.exportData[i-1], pathObj)
		}

		// Merge with previous line path
		if (lineIndex && ((lineIndex % 2) !== (pathIndex % 2))) {
			console.log('Parite', lineIndex, pathIndex);
			this.mergePath(this.exportData[i - lineIndex], pathObj);
		}
	}
};

Triangulr.prototype.mergePath = function (blob, tri) {
	// Future check : the color
	if (!tri.color || tri.color !== blob.color) {
		return;
	}

	// If they are part of the same blob, it is le pointless
	if (tri.blob && tri.blob === blob.blob) {
		return;
	}

	console.log('Merge is happening');
	var blob = merger(blob.blob || blob.points, tri.points);
	tri.blob = blob;
	blob.blob = blob;
	debugger;
};

function merger (blob, tri) {
	var d = [
		blob.indexOf(tri[0]),
		blob.indexOf(tri[1]),
		blob.indexOf(tri[2]),
	];

	var pointsNotFound = d.filter(function(e){return e === -1}).length;

	if (pointsNotFound > 1) {
		console.error('Holy shite, we have a bug');
		debugger;
	}

	var iMax, iMin, newPoint;

	if (pointsNotFound == 0) {
		iMax = Math.max.apply(null, d);
		iMin = Math.min.apply(null, d);
		// Remove the middle point
		if (iMax - iMin > 2) {
			if (d.filter(function(x){return x === 1;}).length) {
				// Remove the first point
				blob.shift();
			}
			else {
				// Remove the last
				blob.pop();
			}
		}
		else {
			blob.splice(iMin + 1, 1);
		}
	}
	else {
		newPoint = tri[d.indexOf(-1)];
		d.splice(d.indexOf(-1), 1);
		iMax = Math.max.apply(null, d);
		iMin = Math.min.apply(null, d);
		// Add the new point

		if (iMin === 0 && (iMax === blob.length - 1)) {
			blob.push(newPoint);
		}
		else {
			blob.splice(iMax, 0, newPoint);
		}
	}

	return blob;
}
<commit_msg>Clean SVG code on export<commit_after>'use strict';

/**
 * Triangulr class
 * instructions will follow, in an other commit, it's late now
 *
 * @param	string					containerId			Container DOM id
 */
function Triangulr (containerId) {
	this.container = document.getElementById(containerId);
	if (!this.container) {
		throw new Error ('Triangulr container "' + containerId + '" does not exists.');
	}
}

Triangulr.prototype.DEFAULT_COLOR = '#000';
Triangulr.prototype.BLANK_COLOR = '#FFF';

/**
 * Triangulr class
 * instructions will follow, in an other commit, it's late now
 *
 * @param	int							width						Triangle height
 * @param	int							height					Triangle height
 * @param	int							triangleHeight	Triangle height
 */
Triangulr.prototype.setCanvas = function (width, height, triangleWidth, isLandscape) {
	// Save input
	this.isLandscape = isLandscape;
	this.mapWidth = width;
	this.mapHeight = height;

	this.triangleWidth = triangleWidth;
	this.triangleHeight = Math.sqrt(Math.pow(triangleWidth, 2) - Math.pow(triangleWidth / 2, 2));
	this.triangleHeight = Math.round(this.triangleHeight);

	this.lines = [];
	this.exportData = [];
	this.pickedColor = this.DEFAULT_COLOR;

	this.lineMapping();
	this.createTriangles();
	this.generateDom();
}

/**
 * lineMapping
 * generate this.lines from the contructor info
 *
 */
Triangulr.prototype.lineMapping = function () {

	var x, y, line;
	var parity = this.triangleWidth / 4;
	var gap = parity;

	if (this.isLandscape) {
		for(y = 0; y<=this.mapHeight; y++) {
			line = [];
			for(x = 0; x<=this.mapWidth; x++) {
				line.push({
					x: x * this.triangleWidth + parity + gap,
					y: y * this.triangleHeight
				});
			}
			this.lines.push(line);
			parity *= -1;
		}
	}
	else {
		for(y = 0; y<=this.mapWidth; y++) {
			line = [];
			for(x = 0; x<=this.mapHeight; x++) {
				line.push({
					x: y * this.triangleHeight,
					y: x * this.triangleWidth + parity + gap
				});
			}
			this.lines.push(line);
			parity *= -1;
		}
	}
};

/**
 * createTriangles
 * use points form this.lines to generate triangles
 * and put them into this.exportData
 *
 */
Triangulr.prototype.createTriangles = function () {

	var x, parity, lineA, lineB, aIndex, bIndex, points, poly, pointsList;
	var counter = 0;
	var lineParite = true;
	this.exportData = [];

	for(x = 0; x<this.lines.length -1; x++) {
		lineA = this.lines[x];
		lineB = this.lines[x+1];
		aIndex = 0;
		bIndex = 0;
		parity = lineParite;

		do {
			// Get the good points
			points = [lineA[aIndex], lineB[bIndex]];
			if (parity) {
				bIndex++;
				points.push(lineB[bIndex]);
			}
			else {
				aIndex++;
				points.push(lineA[aIndex]);
			}
			parity = !parity;

			// Save the triangle
			pointsList = [
				points[0],
				points[1],
				points[2]
			];
			this.exportData.push({
				points: pointsList
			});
			counter++;
		} while (aIndex != lineA.length-1 && bIndex != lineA.length-1);

		lineParite = !lineParite;
	}
};

/**
 * generateDom
 * generate the SVG object from exportData content
 *
 * @return {[object]} Svg DOM object
 */
Triangulr.prototype.generateDom = function () {
	if (this.svgTag) {
		this.container.appendChild(this.svgTag);
		this.svgTag.remove();
	}

	var svgTag = this.generateSVG();

	this.color = false;
	svgTag.addEventListener('mousedown', function (e) {
		this.color = this.pickedColor;
		listener(e);
	}.bind(this));
	window.addEventListener('mouseup', function () {
		this.color = false;
	}.bind(this));

	var listener = function (e) {
		var rel = parseInt(e.target.getAttribute('rel'), 10);
		if (this.color === false || isNaN(rel)) {
			return;
		}
		this.exportData[rel].color = this.color;
		e.target.setAttribute('fill', this.color || this.BLANK_COLOR);
	}.bind(this);

	for(var i = svgTag.childNodes.length - 1; i >= 0; i--) {
		svgTag.childNodes[i].addEventListener('mousemove', listener);
	}

	this.svgTag = svgTag;
	this.container.appendChild(svgTag);
	return svgTag;
};

Triangulr.prototype.generateSVG = function (isClean) {
	var i, data, points, polygon;
	var svgTag = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

	svgTag.setAttribute('version', '1.1');
	svgTag.setAttribute('preserveAspectRatio', 'xMinYMin slice');

	if (this.isLandscape) {
		svgTag.setAttribute('width', this.mapWidth * this.triangleWidth);
		svgTag.setAttribute('height', this.mapHeight * this.triangleHeight);
		svgTag.setAttribute('viewBox', '0 0 ' + (this.mapWidth * this.triangleWidth) + ' ' + (this.mapHeight * this.triangleHeight));
	}
	else {
		svgTag.setAttribute('width', this.mapWidth * this.triangleHeight);
		svgTag.setAttribute('height', this.mapHeight * this.triangleWidth);
		svgTag.setAttribute('viewBox', '0 0 ' + (this.mapWidth * this.triangleHeight) + ' ' + (this.mapHeight * this.triangleWidth));
	}

	for(i in this.exportData) {
		data = this.exportData[i];
		if (isClean && !data.color) {
			continue;
		}
		polygon = document.createElementNS('http://www.w3.org/2000/svg','path');
		points   = 'M' + data.points[0].x + ' ' + data.points[0].y + ' ';
		points  += 'L' + data.points[1].x + ' ' + data.points[1].y + ' ';
		points  += 'L' + data.points[2].x + ' ' + data.points[2].y + ' Z';
		polygon.setAttribute('d', points);
		polygon.setAttribute('fill', data.color || this.BLANK_COLOR);
		polygon.setAttribute('rel', i);
		svgTag.appendChild(polygon);
	}
	return svgTag;
}

Triangulr.prototype.export = function () {
	return {
		isLandscape: this.isLandscape,
		mapWidth: this.mapWidth,
		mapHeight: this.mapHeight,
		mapData: this.exportData.map(function (e) {return e.color || null}),
		triangleWidth: this.triangleWidth
	};
};

Triangulr.prototype.import = function (data) {
	this.setCanvas(
		data.mapWidth,
		data.mapHeight,
		data.triangleWidth,
		data.isLandscape
	);

	for (var i in data.mapData) {
		this.exportData[i].color = data.mapData[i];
	}

	for (var i = 0; i < this.svgTag.childNodes.length; i++) {
		this.svgTag.childNodes[i].setAttribute('fill', this.exportData[i].color || this.BLANK_COLOR);
	}
};

Triangulr.prototype.exportSVG = function () {
	return this.generateSVG(true).outerHTML;
};

/**
 * WARNING!!!
 * The following code is a failing work in progress
 */
Triangulr.prototype.transformer = function () {
	var blob, pathObj, pathToMerge, lineIndex, pathIndex;
	var lineLength = this.mapWidth * 2 - 1;

	console.log('linelength: ', lineLength);

	for (var i = 1; i < this.exportData.length; i++) {
		pathObj = this.exportData[i];
		lineIndex = Math.floor(i / lineLength);
		pathIndex = i % lineLength;

		console.log(i);

		// Merge with the previous item ()
		if (pathIndex !== 0) {
			this.mergePath(this.exportData[i-1], pathObj)
		}

		// Merge with previous line path
		if (lineIndex && ((lineIndex % 2) !== (pathIndex % 2))) {
			console.log('Parite', lineIndex, pathIndex);
			this.mergePath(this.exportData[i - lineIndex], pathObj);
		}
	}
};

Triangulr.prototype.mergePath = function (blob, tri) {
	// Future check : the color
	if (!tri.color || tri.color !== blob.color) {
		return;
	}

	// If they are part of the same blob, it is le pointless
	if (tri.blob && tri.blob === blob.blob) {
		return;
	}

	console.log('Merge is happening');
	var blob = merger(blob.blob || blob.points, tri.points);
	tri.blob = blob;
	blob.blob = blob;
	debugger;
};

function merger (blob, tri) {
	var d = [
		blob.indexOf(tri[0]),
		blob.indexOf(tri[1]),
		blob.indexOf(tri[2]),
	];

	var pointsNotFound = d.filter(function(e){return e === -1}).length;

	if (pointsNotFound > 1) {
		console.error('Holy shite, we have a bug');
		debugger;
	}

	var iMax, iMin, newPoint;

	if (pointsNotFound == 0) {
		iMax = Math.max.apply(null, d);
		iMin = Math.min.apply(null, d);
		// Remove the middle point
		if (iMax - iMin > 2) {
			if (d.filter(function(x){return x === 1;}).length) {
				// Remove the first point
				blob.shift();
			}
			else {
				// Remove the last
				blob.pop();
			}
		}
		else {
			blob.splice(iMin + 1, 1);
		}
	}
	else {
		newPoint = tri[d.indexOf(-1)];
		d.splice(d.indexOf(-1), 1);
		iMax = Math.max.apply(null, d);
		iMin = Math.min.apply(null, d);
		// Add the new point

		if (iMin === 0 && (iMax === blob.length - 1)) {
			blob.push(newPoint);
		}
		else {
			blob.splice(iMax, 0, newPoint);
		}
	}

	return blob;
}
<|endoftext|>


<commit_before>/*
Name:         europeana.js
Description:  Unofficial node.js module for the Europeana API
Author:       Franklin van de Meent - https://frankl.in
Source:       https://github.com/fvdm/nodejs-europeana
Feedback:     https://github.com/fvdm/nodejs-europeana/issues
License:      Public Domain / Unlicense (see UNLICENSE file)
              (https://github.com/fvdm/nodejs-europeana/raw/master/UNLICENSE)
*/

var http = require ('http');
var querystring = require ('querystring');

var settings = {
  apikey: null,
  timeout: 5000
};

// config
module.exports = function setup (apikey, timeout) {
  settings.apikey = apikey || null;
  settings.timeout = timeout || settings.timeout;
  return talk;
};

// errors
// http://www.europeana.eu/portal/api-working-with-api.html#Error-Codes

var errors = {
  400: 'The request sent by the client was syntactically incorrect',
  401: 'Authentication credentials were missing or authentication failed.',
  404: 'The requested record was not found.',
  429: 'The request could be served because the application has reached its usage limit.',
  500: 'Internal Server Error. Something has gone wrong, please report to us.'
};

// communicate with the API
function talk (path, fields, callback) {
  if (typeof fields === 'function') {
    callback = fields;
    fields = {};
  }

  // prevent multiple callbacks
  var complete = false;
  function doCallback (err, res) {
    if (!complete) {
      complete = true;
      callback (err, res);
    }
  }

  // Request

  // check API key
  if (!settings.apikey) {
    doCallback (new Error ('apikey missing'));
    return;
  }

  // build request
  fields.wskey = settings.apikey;
  var query = '?'+ querystring.stringify (fields);

  var options = {
    protocol: 'http:',
    host: 'europeana.eu',
    path: '/api/v2/'+ path +'.json'+ query,
    method: 'GET',
    headers: {
      'User-Agent': 'europeana.js'
    }
  };

  var request = http.request (options);

  // Handlers
  request.on ('socket', function onSocket (socket) {
    socket.setTimeout (parseInt (settings.timeout));
    socket.on ('timeout', function () {
      doCallback (new Error ('request timeout'));
      request.abort ();
    });
  });

  request.on ('error', function onError (error) {
    var err = new Error ('request failed');
    err.error = error;
    doCallback (err);
  });

  request.on ('response', function onResponse (response) {
    var data = [];
    var size = 0;

    response.on ('close', function onClose () {
      doCallback (new Error ('request dropped'));
    });

    response.on ('data', function onData (ch) {
      data.push (ch);
      size += ch.length;
    });

    response.on ('end', function onEnd () {
      var er = null;
      data = Buffer.concat (data, size) .toString () .trim ();

      if (response.statusCode !== 200) {
        er = new Error ('API error');
        er.code = response.statusCode;
        er.error = errors [response.statusCode];

        if (data.match (/
HTTP Status /)) {
          er.error = data.replace (/.*description<\/b> (.+)<\/u><\/p>.*/, '$1');
        }
      } else {
        try {
          data = JSON.parse (data);

          if (data.apikey) {
            delete data.apikey;
          }

          if (!data.success && data.error) {
            er = new Error ('API error');
            err.error = data.error;
            err.data = data;
            data = null;
          }
        } catch (reason) {
          // can't read this
          er = new Error ('invalid response');
          er.error = reason;
          er.data = data;
          data = null;
        }
      }

      doCallback (er, data);
    });
  });

  request.end ();
}
<commit_msg>Replaced HTTP bits with httpreq module<commit_after>/*
Name:         europeana.js
Description:  Unofficial node.js module for the Europeana API
Author:       Franklin van de Meent - https://frankl.in
Source:       https://github.com/fvdm/nodejs-europeana
Feedback:     https://github.com/fvdm/nodejs-europeana/issues
License:      Public Domain / Unlicense (see UNLICENSE file)
              (https://github.com/fvdm/nodejs-europeana/raw/master/UNLICENSE)
*/

var http = require ('httpreq');

var settings = {
  apikey: null,
  timeout: 5000
};

// config
module.exports = function setup (apikey, timeout) {
  settings.apikey = apikey || null;
  settings.timeout = timeout || settings.timeout;
  return talk;
};

// errors
// http://www.europeana.eu/portal/api-working-with-api.html#Error-Codes

var errors = {
  400: 'The request sent by the client was syntactically incorrect',
  401: 'Authentication credentials were missing or authentication failed.',
  404: 'The requested record was not found.',
  429: 'The request could be served because the application has reached its usage limit.',
  500: 'Internal Server Error. Something has gone wrong, please report to us.'
};

// communicate with the API
function talk (path, fields, callback) {
  if (typeof fields === 'function') {
    callback = fields;
    fields = {};
  }

  // Request

  // check API key
  if (!settings.apikey) {
    callback (new Error ('apikey missing'));
    return;
  }

  // build request
  var options = {
    url: 'http://europeana.eu/api/v2/' + path + '.json',
    parameters: fields,
    headers: {
      'User-Agent': 'europeana.js'
    }
  };

  options.parameters.wskey = settings.apikey;

  http.get (options, function (err, res) {
    var data = res && res.body || '';
    var error = null;

    // client failed
    if (err) {
      error = new Error ('request failed');
      error.error = err;
      callback (error);
      return;
    }

    // http error
    if (response.statusCode !== 200) {
      error = new Error ('API error');
      error.code = response.statusCode;
      error.error = errors [response.statusCode];

      if (data.match (/
HTTP Status /)) {
        error.error = data.replace (/.*description<\/b> (.+)<\/u><\/p>.*/, '$1');
      }

      callback (error);
      return;
    }

    try {
      data = JSON.parse (data);

      if (data.apikey) {
        delete data.apikey;
      }

      // API error
      if (!data.success && data.error) {
        error = new Error ('API error');
        error.error = data.error;
        error.data = data;

        callback (error);
        return;
      }
    } catch (reason) {
      error = new Error ('invalid response');
      error.error = reason;
      error.data = data;

      callback (error);
      return;
    }

    // all good
    callback (null, data);
  });
}
<|endoftext|>


<commit_before>import React  from 'react'
import { connect } from 'react-redux'

import { fetchProjects, updateProject, createProject, saveProject } from '../actions/projects'
import { setVisibilitySearchText } from '../actions/visibilityFilter'
import ProjectsList  from '../components/ProjectsList'

const mapStateToProps = (state, ownProps) => {
  return {
    projects: state.projects.all ? state.projects.all.filter(p => p.isCreating || state.user.permissions.isApplicationAdmin() || state.user.permissions.hasProject(p.id)) : [],
    visibilitySearchText: state.projects.filter.searchText
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onComponentMount: (initialProps) => {
      dispatch(setVisibilitySearchText(null))
      dispatch(fetchProjects())
    },
    onNewProjectClick: () => { dispatch(createProject()) },
    newProjectNamed: (name) => {
      dispatch(saveProject({ name }))
    },
    projectNameChanged: (project, newName) => {
      dispatch(updateProject(project, { name : newName }))
    },
    searchTextChanged: (text) => { dispatch(setVisibilitySearchText(text))}
  }
}

const ActiveProjectsList = connect(
  mapStateToProps,
  mapDispatchToProps
)(ProjectsList)

export default ActiveProjectsList
<commit_msg>manager client permissions for projects list<commit_after>import React  from 'react'
import { connect } from 'react-redux'

import { fetchProjects, updateProject, createProject, saveProject } from '../actions/projects'
import { setVisibilitySearchText } from '../actions/visibilityFilter'
import ProjectsList  from '../components/ProjectsList'

const mapStateToProps = (state, ownProps) => {
  return {
    projects: state.projects.all ? state.projects.all.filter(p => p.isCreating || state.user.permissions.isApplicationAdmin() || state.user.permissions.hasProject(p.id)) : [],
    visibilitySearchText: state.projects.filter.searchText,
    user: state.user
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onComponentMount: (initialProps) => {
      dispatch(setVisibilitySearchText(null))
      dispatch(fetchProjects())
    },
    onNewProjectClick: () => { dispatch(createProject()) },
    newProjectNamed: (name) => {
      dispatch(saveProject({ name }))
    },
    projectNameChanged: (project, newName) => {
      dispatch(updateProject(project, { name : newName }))
    },
    searchTextChanged: (text) => { dispatch(setVisibilitySearchText(text))}
  }
}

const ActiveProjectsList = connect(
  mapStateToProps,
  mapDispatchToProps
)(ProjectsList)

export default ActiveProjectsList
<|endoftext|>


<commit_before>window.UserActivitiesView = Backbone.Marionette.CompositeView.extend({

  template: 'activities/user-activities',
  className: 'activity-block',

  initialize: function(opts) {
    this.itemView = ActivityItemView;
  },

  appendable: function(model) {
    return this.model.get('username') === model.get('username');
  },

  appendHtml: function(collectionView, itemView){
    collectionView.$(".the-activities").append(itemView.el);
  }

});
<commit_msg>Only append Channel activities<commit_after>window.UserActivitiesView = Backbone.Marionette.CompositeView.extend({

  template: 'activities/user-activities',
  className: 'activity-block',

  initialize: function(opts) {
    this.itemView = ActivityItemView;
  },

  appendable: function(model) {
    var same_user           = this.model.get('username') === model.get('username');
    var is_channel_activity = model.get('subject_class') === "Channel";
    return same_user && is_channel_activity;
  },

  appendHtml: function(collectionView, itemView){
    collectionView.$(".the-activities").append(itemView.el);
  }

});
<|endoftext|>


<commit_before>Package.describe({
	summary: 'Notifications - Add reactive notifications to any meteor template',
	version: '1.0.6',
	git: 'https://github.com/gfk-ba/meteor-notifications'
});

Package.on_use(function(api) {
	api.versionsFrom('METEOR@0.9.0');

	api.use([
		'templating',
		'underscore',
		'less',
		'mongo@1.0.4'
	], 'client');

	api.add_files(
			[
				'notifications.less',
				'notifications.html',
				'notifications.js',
				'notification.html',
				'notification.js'
			],
			['client']);

	api.export && api.export('Notifications', ['client']);
});

Package.on_test(function(api) {
	api.use([
		'tinytest',
		'underscore',
		'gfk:notifications'
	], 'client');

	api.use(['gfk:munit@1.0.0', 'mdj:chai@1.0.0', 'mdj:sinon@1.0.0'], 'client');

	api.add_files('notifications_tests.js', ['client']);
});
<commit_msg>Version 1.0.6 breaks in meteor 0.9.0 so it now depends on meteor 0.9.1<commit_after>Package.describe({
	summary: 'Notifications - Add reactive notifications to any meteor template',
	version: '1.0.7',
	git: 'https://github.com/gfk-ba/meteor-notifications'
});

Package.on_use(function(api) {
	api.versionsFrom('METEOR@0.9.1');

	api.use([
		'templating',
		'underscore',
		'less',
		'mongo@1.0.4'
	], 'client');

	api.add_files(
			[
				'notifications.less',
				'notifications.html',
				'notifications.js',
				'notification.html',
				'notification.js'
			],
			['client']);

	api.export && api.export('Notifications', ['client']);
});

Package.on_test(function(api) {
	api.use([
		'tinytest',
		'underscore',
		'gfk:notifications'
	], 'client');

	api.use(['gfk:munit@1.0.0', 'mdj:chai@1.0.0', 'mdj:sinon@1.0.0'], 'client');

	api.add_files('notifications_tests.js', ['client']);
});
<|endoftext|>


<commit_before>Package.describe({
  summary: "Meteor smart package for full authentication pages styled with Semantic UI"
});

Package.on_use(function (api, where) {

  // client
  api.use([
    'handlebars',
    'less',
    'templating'
    ], 'client');

  api.add_files([
    'client/views/account_button.html',
    'client/views/account_button.js',
    'client/views/sign_in.html',
    'client/views/sign_in.js',
    'client/views/forgot_password.html',
    'client/views/forgot_password.js',
    'client/views/sign_up.html',
    'client/views/sign_up.js'
  ], 'client');

  // client and server
  api.export('AccountsPages', ['client', 'server']);
  api.use('iron-router', ['client', 'server']);
  api.add_files('lib/router.js', ['client', 'server']);

});

Package.on_test(function (api) {

});
<commit_msg>Added new files to package.js<commit_after>Package.describe({
  summary: "Meteor smart package for full authentication pages styled with Semantic UI"
});

Package.on_use(function (api, where) {

  // client
  api.use([
    'handlebars',
    'less',
    'templating'
    ], 'client');

  api.add_files([
    'client/views/account_button.html',
    'client/views/account_button.js',
    'client/views/sign_in.html',
    'client/views/sign_in.js',
    'client/views/sign_up.html',
    'client/views/sign_up.js',
    'client/views/forgot_password.html',
    'client/views/forgot_password.js',
    'client/views/reset_password.html',
    'client/views/reset_password.js',
    'client/views/error.html',
    'client/views/error.js'
  ], 'client');

  // server
  api.add_files([
    'server/startup.js'
  ], 'server');

  // client and server
  api.export('AccountsPages', ['client', 'server']);
  api.use('iron-router', ['client', 'server']);
  api.add_files('lib/router.js', ['client', 'server']);

});

Package.on_test(function (api) {

});
<|endoftext|>


<commit_before>Package.describe({
  name: 'comerc:autoform-fixtures',
  summary: 'Get fixtures data from SimpleSchema with AutoForm',
  version: '1.2.0',
  git: 'https://github.com/comerc/meteor-autoform-fixtures.git'
});

Package.onUse(function(api) {
  api.versionsFrom('1.0.2.1');
  api.use('coffeescript');
  api.use('momentjs:moment@2.8.4', 'client');
  api.use('aldeed:autoform@4.0.0');
  api.addFiles([
    'autoform-fixtures.coffee',
  ], 'client');
});
<commit_msg>compatible with autoform 5.0<commit_after>Package.describe({
  name: 'comerc:autoform-fixtures',
  summary: 'Get fixtures data from SimpleSchema with AutoForm',
  version: '1.2.1',
  git: 'https://github.com/comerc/meteor-autoform-fixtures.git'
});

Package.onUse(function(api) {
  api.versionsFrom('1.0.2.1');
  api.use('coffeescript');
  api.use('momentjs:moment@2.8.4', 'client');
  api.use('aldeed:autoform@5.0.0');
  api.addFiles([
    'autoform-fixtures.coffee',
  ], 'client');
});
<|endoftext|>


<commit_before>'use strict';
const path = require('path');
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
const DEFAULT_OPTIONS = {
  outputPath: 'public',
  clean: {
    path: [],
    options: {
      root: process.cwd()
    }
  },
  uglify: {
    compress: {
      warnings: false
    },
    comments: false,
    sourceMap: true
  }
};
module.exports = function (options = {}) {
  const env = process.env.NODE_ENV || 'development';
  options = webpackMerge({}, DEFAULT_OPTIONS, options);
  const config = {
    devtool: '#source-map',
    output: {
      path: path.join(process.cwd(), options.outputPath),
      publicPath: '/',
      filename: "assets/js/[name].js",
      jsonpFunction: 'fr',
      library: '[name]_library'
    },
    resolve: {
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.sass', '.scss', '.ejs', '.html'],
      modules: [
        path.join(process.cwd(), 'src'),
        path.join(process.cwd(), 'node_modules')
      ]
    },
    stats: {
      assets: false,
      modules: false,
      children: false,
    },
    watchOptions: {
      ignored: /node_modules/
    },
    performance: {
      hints: false
    },
    plugins: [
      new webpack.NoEmitOnErrorsPlugin(),
      new webpack.DefinePlugin({
        'process.env': {
          'NODE_ENV': JSON.stringify(env)
        }
      }),
      new ProgressPlugin({profile:options.verbose, colors: true }),
      new webpack.LoaderOptionsPlugin({
        options: {
          context: process.cwd(),
          output: {
            path: path.join(process.cwd(),options.outputPath)
          }
        }
      })
    ]
  };

  if (env === 'production') { // for production
    options.clean.path.push(options.outputPath);
    config.plugins.push(
      new CleanWebpackPlugin(options.clean.path, options.clean.options),
      new webpack.optimize.AggressiveMergingPlugin(),
      new webpack.optimize.UglifyJsPlugin(options.uglify)
    );
  } else {  // for development
    try {
      let manifest = require.resolve(path.join(process.cwd(), 'vendor-manifest.json'));
      config.plugins.push(new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: path.join(process.cwd(), 'vendor-manifest.json')
      }));
    } catch (e) {
      console.log('Not found vendor-manifest.json');
    }
  }
  return config;
};<commit_msg>ProgressPluginがプラグインとバッティングしてcssのビルドがループする<commit_after>'use strict';
const path = require('path');
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const DEFAULT_OPTIONS = {
  outputPath: 'public',
  clean: {
    path: [],
    options: {
      root: process.cwd()
    }
  },
  uglify: {
    compress: {
      warnings: false
    },
    comments: false,
    sourceMap: true
  }
};
module.exports = function (options = {}) {
  const env = process.env.NODE_ENV || 'development';
  options = webpackMerge({}, DEFAULT_OPTIONS, options);
  const config = {
    devtool: '#source-map',
    output: {
      path: path.join(process.cwd(), options.outputPath),
      publicPath: '/',
      filename: "assets/js/[name].js",
      jsonpFunction: 'fr',
      library: '[name]_library'
    },
    resolve: {
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.sass', '.scss', '.ejs', '.html'],
      modules: [
        path.join(process.cwd(), 'src'),
        path.join(process.cwd(), 'node_modules')
      ]
    },
    stats: {
      assets: false,
      modules: false,
      children: false,
    },
    watchOptions: {
      ignored: /node_modules/
    },
    performance: {
      hints: false
    },
    plugins: [
      new webpack.NoEmitOnErrorsPlugin(),
      new webpack.DefinePlugin({
        'process.env': {
          'NODE_ENV': JSON.stringify(env)
        }
      }),
      new webpack.LoaderOptionsPlugin({
        options: {
          context: process.cwd(),
          output: {
            path: path.join(process.cwd(),options.outputPath)
          }
        }
      })
    ]
  };

  if (env === 'production') { // for production
    options.clean.path.push(options.outputPath);
    config.plugins.push(
      new CleanWebpackPlugin(options.clean.path, options.clean.options),
      new webpack.optimize.AggressiveMergingPlugin(),
      new webpack.optimize.UglifyJsPlugin(options.uglify)
    );
  } else {  // for development
    try {
      let manifest = require.resolve(path.join(process.cwd(), 'vendor-manifest.json'));
      config.plugins.push(new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: path.join(process.cwd(), 'vendor-manifest.json')
      }));
    } catch (e) {
      console.log('Not found vendor-manifest.json');
    }
  }
  return config;
};<|endoftext|>


<commit_before>/*
 * General specifications GridGallery
 * 1- creates a grid using elements that will be in different heights and widths
 * 2- will enable gallery view on click to an element of the grid (dialog)
 * 3- the dialog will trigger custom events to control data in dialog
 * 4- nav of items in grid (disable/enable) depending on initialization
 */

describe('GridGallery', function(){
  describe('GridGallery initialization', function(){
    var x, options = { lightBox: true };
    var container;

    beforeAll(function() {
      container = document.createElement('div');
      container.className = 'grid-gallery';

      for (var i = 0; i < 5; i++) {
        var element = document.createElement('div');
        element.className = 'grid-gallery__item';
        container.appendChild(element);
      }

      x = new GridGallery(container, options);
    });

    it('Global must have the GridGallery as a property', function() {
     expect(GridGallery).not.toBeUndefined();
    });

    it('should manipulate the default options to the created instance', function() {
      var y = new GridGallery();
      expect(y.options).toEqual({'lightBox': false});
    });

    it('should extend the default options and icludes the new one', function() {
      expect(x.options).toEqual({'lightBox': true});
    });

    it('should store the container as a property', function() {
      expect(x.element).toEqual(container);
    });

    it('should have method init', function() {
      expect(x.init).toBeDefined();
      expect(typeof x.init).toBe('function');
    });
  });
});
<commit_msg>init the classes and demo content to use in test<commit_after>/*
 * General specifications GridGallery
 * 1- creates a grid using elements that will be in different heights and widths
 * 2- will enable gallery view on click to an element of the grid (dialog)
 * 3- the dialog will trigger custom events to control data in dialog
 * 4- nav of items in grid (disable/enable) depending on initialization
 */

describe('GridGallery', function(){
  describe('GridGallery initialization', function(){
    var x, options = { lightBox: true };
    var container;
    document.body.className = 'grid-gallery__example';

    beforeAll(function() {
      var wrapper = document.createElement('div');
      wrapper.className = 'container';

      container = document.createElement('div');
      container.className = 'grid-gallery';

      for (var i = 0; i < 5; i++) {
        var element = document.createElement('div');
        var p = document.createElement('p');
        p.textContent = 'lorem nav of items in grid (disable/enable) depending on initialization';
        element.className = 'grid-gallery__item grid-gallery__dummy';
        element.appendChild(p);
        container.appendChild(element);
      }

      wrapper.appendChild(container);
      document.body.appendChild(wrapper);

      x = new GridGallery(container, options);
    });

    it('Global must have the GridGallery as a property', function() {
     expect(GridGallery).not.toBeUndefined();
    });

    it('should manipulate the default options to the created instance', function() {
      var y = new GridGallery( container, {});
      expect(y.options).toEqual({'lightBox': false});
    });

    it('should extend the default options and icludes the new one', function() {
      expect(x.options).toEqual({'lightBox': true});
    });

    it('should store the container as a property', function() {
      expect(x.element).toEqual(container);
    });

    it('should have method init', function() {
      expect(x.init).toBeDefined();
      expect(typeof x.init).toBe('function');
    });
  });
});
<|endoftext|>


<commit_before>/**
 * Video widget
 * show stream from erlyvideo and publish stream to erlyvideo
 */
$.uce.widget("video", {
    /**
     * Internal state: current publishing or not
     */
    _publish : false,
    /**
     * Internal state: should we show receive flash widget
     */
    _showReceive : false,
    // ucengine events
    meetingsEvents: {
        'video.stream.new'   : 'onStreamNew',
        'video.stream.start' : 'onStreamStarted',
        'video.stream.stop'  : 'onStreamStopped'
    },
    // Default options
    options: {
        title      : 'Video',
        ucemeeting : null,
        domain : "localhost",
        stream : "ucengine",
        width  : null,
        height : null,
        ratio  : 0.75,
        buttons: {left: [], right: []}
    },
    labels : {
        "button.publish"     : "Publish",
        "button.stoppublish" : "Stop publish",
        "content.nostream"   : "No stream is available"
    },
    _getFlashSrc: function() {
        if (this._publish)
            return '/lib/video/publish_video.swf';
        else
            return '/lib/video/receive_video.swf';
    },
    _getFlashVar: function() {
        return $.param({wmode      : 'opaque',
                        stream     : this.options.stream,
                        server     : "rtmp://" + this.options.domain,
                        streamtype : "live",
                        token      : this.options.token,
                        width      : this.options.width - 40,
                        height     : this.options.height - 20});
    },
    _create: function() {
        var that = this;

        /* create dock */
        if (this.options.dock) {
            var dock = $('<a>')
                .attr('class', 'ui-dock-button')
                .attr('href', '#')
                .attr('title', this.options.title)
                .button({
                    text: false,
                    icons: {primary: "ui-icon-person"}
                }).click(function() {
                    that.element.effect('bounce');
                    $(window).scrollTop(that.element.offset().top);
                    return false;
                });
            dock.addClass('ui-video-dock');
            dock.appendTo(this.options.dock);
        }

        this.element.addClass('ui-widget ui-video');
        this._button = $('<a>').attr('href', '#')
            .button({label: 'Publish'})
            .click($.proxy(this._onClickButton, this));
        var rightButtons = [this._button].concat(this.options.buttons.right);
        this._addHeader(this.options.title, {left: this.options.buttons.left,
                                             right: rightButtons});
        this._content = $('<div>').addClass('ui-widget-content').appendTo(this.element);

        if (!this.options.width && !this.options.height) {
            this.options.width = this.element.width();
        }
        if (!this.options.width && this.options.height) {
            this.options.width = this.options.height / this.options.ratio;
        }
        if (this.options.height) {
            this.options.ratio = this.options.height / this.options.width;
        }

        this.options.height = parseInt(this.options.width * this.options.ratio, 10);
        this._content.css('width', this.options.width);
        this._content.css('min-height', this.options.height);

        if (this.options.ucemeeting == null) {
            this._showReceive = true;
            this._updateEmbed();
        }
    },
    _onClickButton: function(e) {
        e.preventDefault();
        if (this._button.button('option', 'disabled'))
            return;
        if (this._button.button('option', 'label') == this.labels["button.publish"]) {
            this.publish();
            this._button.button('option', 'label', this.labels["button.stoppublish"]);
        } else {
            this._button.button('option', 'label', this.labels["button.publish"]);
            this.receive();
        }
    },
    _videoAttr: function() {
        return {src       : this._getFlashSrc(),
                flashvars : this._getFlashVar(),
                quality   : 75,
                width     : this.options.width,
                height    : this.options.height,
                type      : 'application/x-shockwave-flash'};
    },
    _setOption: function(key, value) {
        $.Widget.prototype._setOption.apply(this, arguments);
        this.element.find("embed").attr(this._videoAttr());
    },
    _updateEmbed: function() {
        this._content.children().remove();
        if (this._showReceive || this._publish) {
            $('<embed>').attr(this._videoAttr()).appendTo(this._content);
        } else {
            $('<p>')
                .attr('class', 'ui-video-error')
                .text(this.labels["content.nostream"])
                .appendTo(this._content);
        }
    },
    publish: function() {
        this._publish = true;
        this._updateEmbed();
    },
    receive: function() {
        this._publish = false;
        this._updateEmbed();
    },
    onStreamNew: function(event) {
        this.options.stream = event.metadata.channel;
        this.options.token  = event.metadata.token;
        this._updateEmbed();
    },
    onStreamStarted: function(event) {
        if (event.metadata.broadcaster != this.options.ucemeeting.uid) {
            this._button.button("disable");
            this._showReceive = true;
            this._updateEmbed();
        }
    },
    onStreamStopped: function(event) {
        this._button.button("enable");
        this._showReceive = false;
        this._updateEmbed();
    },
    reduce: function() {
        this._resize();
        this._updateEmbed();
    },
    expand: function() {
        this._resize();
        this._updateEmbed();
    },
    _resize: function() {
        this.options.width = this.element.width();
        this.options.height = parseInt(this.options.width * this.options.ratio, 10);
        this._content.css('width', this.options.width);
        this._content.css('min-height', this.options.height);
    },
    destroy: function() {
        this.element.children().remove();
        this.element.removeClass('ui-widget ui-video');
        $.Widget.prototype.destroy.apply(this, arguments); // default destroy
    }
});
<commit_msg>Video: No stream is available => No stream available.<commit_after>/**
 * Video widget
 * show stream from erlyvideo and publish stream to erlyvideo
 */
$.uce.widget("video", {
    /**
     * Internal state: current publishing or not
     */
    _publish : false,
    /**
     * Internal state: should we show receive flash widget
     */
    _showReceive : false,
    // ucengine events
    meetingsEvents: {
        'video.stream.new'   : 'onStreamNew',
        'video.stream.start' : 'onStreamStarted',
        'video.stream.stop'  : 'onStreamStopped'
    },
    // Default options
    options: {
        title      : 'Video',
        ucemeeting : null,
        domain : "localhost",
        stream : "ucengine",
        width  : null,
        height : null,
        ratio  : 0.75,
        buttons: {left: [], right: []}
    },
    labels : {
        "button.publish"     : "Publish",
        "button.stoppublish" : "Stop publish",
        "content.nostream"   : "No stream available"
    },
    _getFlashSrc: function() {
        if (this._publish)
            return '/lib/video/publish_video.swf';
        else
            return '/lib/video/receive_video.swf';
    },
    _getFlashVar: function() {
        return $.param({wmode      : 'opaque',
                        stream     : this.options.stream,
                        server     : "rtmp://" + this.options.domain,
                        streamtype : "live",
                        token      : this.options.token,
                        width      : this.options.width - 40,
                        height     : this.options.height - 20});
    },
    _create: function() {
        var that = this;

        /* create dock */
        if (this.options.dock) {
            var dock = $('<a>')
                .attr('class', 'ui-dock-button')
                .attr('href', '#')
                .attr('title', this.options.title)
                .button({
                    text: false,
                    icons: {primary: "ui-icon-person"}
                }).click(function() {
                    that.element.effect('bounce');
                    $(window).scrollTop(that.element.offset().top);
                    return false;
                });
            dock.addClass('ui-video-dock');
            dock.appendTo(this.options.dock);
        }

        this.element.addClass('ui-widget ui-video');
        this._button = $('<a>').attr('href', '#')
            .button({label: 'Publish'})
            .click($.proxy(this._onClickButton, this));
        var rightButtons = [this._button].concat(this.options.buttons.right);
        this._addHeader(this.options.title, {left: this.options.buttons.left,
                                             right: rightButtons});
        this._content = $('<div>').addClass('ui-widget-content').appendTo(this.element);

        if (!this.options.width && !this.options.height) {
            this.options.width = this.element.width();
        }
        if (!this.options.width && this.options.height) {
            this.options.width = this.options.height / this.options.ratio;
        }
        if (this.options.height) {
            this.options.ratio = this.options.height / this.options.width;
        }

        this.options.height = parseInt(this.options.width * this.options.ratio, 10);
        this._content.css('width', this.options.width);
        this._content.css('min-height', this.options.height);

        if (this.options.ucemeeting == null) {
            this._showReceive = true;
            this._updateEmbed();
        }
    },
    _onClickButton: function(e) {
        e.preventDefault();
        if (this._button.button('option', 'disabled'))
            return;
        if (this._button.button('option', 'label') == this.labels["button.publish"]) {
            this.publish();
            this._button.button('option', 'label', this.labels["button.stoppublish"]);
        } else {
            this._button.button('option', 'label', this.labels["button.publish"]);
            this.receive();
        }
    },
    _videoAttr: function() {
        return {src       : this._getFlashSrc(),
                flashvars : this._getFlashVar(),
                quality   : 75,
                width     : this.options.width,
                height    : this.options.height,
                type      : 'application/x-shockwave-flash'};
    },
    _setOption: function(key, value) {
        $.Widget.prototype._setOption.apply(this, arguments);
        this.element.find("embed").attr(this._videoAttr());
    },
    _updateEmbed: function() {
        this._content.children().remove();
        if (this._showReceive || this._publish) {
            $('<embed>').attr(this._videoAttr()).appendTo(this._content);
        } else {
            $('<p>')
                .attr('class', 'ui-video-error')
                .text(this.labels["content.nostream"])
                .appendTo(this._content);
        }
    },
    publish: function() {
        this._publish = true;
        this._updateEmbed();
    },
    receive: function() {
        this._publish = false;
        this._updateEmbed();
    },
    onStreamNew: function(event) {
        this.options.stream = event.metadata.channel;
        this.options.token  = event.metadata.token;
        this._updateEmbed();
    },
    onStreamStarted: function(event) {
        if (event.metadata.broadcaster != this.options.ucemeeting.uid) {
            this._button.button("disable");
            this._showReceive = true;
            this._updateEmbed();
        }
    },
    onStreamStopped: function(event) {
        this._button.button("enable");
        this._showReceive = false;
        this._updateEmbed();
    },
    reduce: function() {
        this._resize();
        this._updateEmbed();
    },
    expand: function() {
        this._resize();
        this._updateEmbed();
    },
    _resize: function() {
        this.options.width = this.element.width();
        this.options.height = parseInt(this.options.width * this.options.ratio, 10);
        this._content.css('width', this.options.width);
        this._content.css('min-height', this.options.height);
    },
    destroy: function() {
        this.element.children().remove();
        this.element.removeClass('ui-widget ui-video');
        $.Widget.prototype.destroy.apply(this, arguments); // default destroy
    }
});
<|endoftext|>


<commit_before>
/**
    Requires Jquery 1.x or greater
    To use:
    1. Create html template using data-gui-* tags
    2. Populate json object data (manually or using an ajax call).
        var my_data = {'name': 'Turtle Soup', 'ingredients': [{'name': 'water'}, {'name': 'turtle'}]}
    3. Turtlegui evaluates js strings, i.e. "my_data.name" is used to populate
    4. Whenever a change occurs (data load or user change), call:
        turtlegui.reload()
       which reloads the gui
    4. The html on the page will be populated with the loaded data, as per template.

    Example html template:

    -----

                <input type="button" data-gui-click="i_was_clicked(ingredient)" value="Info"></input>
                <input type="button" data-gui-click="remove_ingredient(ingredient)" value="Remove"></input>

        <input type='button' onclick='add_ingredient()' value='Add'></input>

    -----

    Turtlegui uses "data-" element fields which resolve js, (function call or dot notation path to data)

    Types of supported fields:
        data-gui-text: populates element.text() with the evaluated value
        data-gui-list: creates copies of its subelement, one for each item in the list, stores item as local variable, as named by field 'data-gui-item'
        data-gui-show: shows or hides based on evaluated value (true/false)
        data-gui-click: evaluates js on click (normally a function call)
        data-gui-include: include an html snippet
        data-gui-class: sets classname(s) on element
        data-gui-val: sets value on element

*/

$.ajaxSetup ({
    // Disable caching of AJAX responses
    cache: false
});

var turtlegui = {};

turtlegui.root_element = $(document);

turtlegui._get_safe_value = function(elem, rel_data, datasrc) {
    var gres = elem.attr(datasrc);
    if (!gres) {
        throw "No " + datasrc + " field on element " + elem.attr('id');
    }
    return turtlegui._relative_eval(elem, gres);
}

turtlegui._relative_eval = function(elem, gres) {
    var rel = elem.data('data-rel');
    var switcharoo = {};
    for (var key in rel) {
        if (key in window) {
            switcharoo[key] = window[key];
        }
        window[key] = rel[key];
    }
    result = eval(gres);
    for (var key in switcharoo) {
        window[key] = switcharoo[key];
    }
    return result;
}

turtlegui.load_snippet = function(elem, url, rel_data) {
    elem.load(url, function(response, status, xhr) {
        if (status == 'success') {
            turtlegui.reload(elem, rel_data);
        } else {
            console.log("Could not load html snippet: " + url + " - " + xhr.status + " " + xhr.statusText);
        }
    });
}

turtlegui.reload = function(elem, rel_data) {
    if (!rel_data) rel_data = {};

    if (!elem) {
        elem = turtlegui.root_element;
    }
    if (rel_data) {
        elem.data('data-rel', rel_data);
    }
    if (elem.attr('data-gui-text')) {
        value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-text');
        elem.text(value);
    }
    if (elem.attr('data-gui-class')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-class');
        elem.addClass(value);
    }
    if (elem.attr('data-gui-id')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-id');
        $(elem).attr('id', value);
    }
    if (elem.attr('data-gui-show')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-show');
        if (value) {
            elem.show();
        } else {
            elem.hide();
            if (elem.attr('data-gui-id')) {
                $(elem).attr('id', null);
            }
            return;
        }
    }
    if (elem.attr('data-gui-click')) {
        elem.unbind('click').click(function() {
            return turtlegui._get_safe_value(elem, rel_data, 'data-gui-click');
        });
    }
    if (elem.attr('data-gui-list')) {
        var list = turtlegui._get_safe_value(elem, rel_data, 'data-gui-list');
        var rel_item = elem.attr('data-gui-item');
        var rel_key = elem.attr('data-gui-key');
        var orig_elems = elem.children();
        var first_elem = $(orig_elems[0]);
        first_elem.hide();
        var new_elems = [];
        for (var i in list) {
            var new_elem = $(first_elem).clone();
            new_elems[new_elems.length] = new_elem;
        }
        for (var i in new_elems) {
            var item = list[i];
            var new_elem = new_elems[i];
            elem.append(new_elem);
            new_elem.show();
            var rel_data = jQuery.extend({}, rel_data);
            rel_data[rel_item] = item;
            if (rel_key != null) {
                rel_data[rel_key] = i;
            }
            turtlegui.reload(new_elem, rel_data);
        }
        orig_elems.remove();
        elem.prepend(first_elem);
    }
    else if (elem.attr('data-gui-tree')) {
        var tree = turtlegui._get_safe_value(elem, rel_data, 'data-gui-tree');
        var rel_item = elem.attr('data-gui-nodeitem');

        var orig_elems = elem.children();
        var first_elem = $(orig_elems[0]);
        first_elem.hide();
        var rel_data = jQuery.extend({}, rel_data);
        rel_data[rel_item] = tree;
        rel_data['_last_tree_elem'] = first_elem;
        rel_data['_last_tree_item'] = rel_item;

        var new_elem = $(first_elem).clone();
        elem.append(new_elem);
        new_elem.show();
        turtlegui.reload(new_elem, rel_data);

        orig_elems.remove();
        elem.prepend(first_elem);
    }
    else if (elem.attr('data-gui-node')) {
        var node = turtlegui._get_safe_value(elem, rel_data, 'data-gui-node');

        var orig_elems = elem.children();
        var first_elem = rel_data['_last_tree_elem'];
        first_elem.hide();
        var rel_data = jQuery.extend({}, rel_data);
        rel_data[rel_item] = node;
        rel_data[rel_data['_last_tree_item']] = node;

        var new_elem = $(first_elem).clone();
        elem.append(new_elem);
        new_elem.show();
        turtlegui.reload(new_elem, rel_data);

        orig_elems.remove();
        elem.prepend(first_elem);
    }
    else if (elem.attr('data-gui-include') && !elem.attr('data-gui-included')) {
        elem.attr('data-gui-included', true);
        var url = elem.attr('data-gui-include');
        turtlegui.load_snippet(elem, url, rel_data);
    }
    else {
        elem.children().each(function() {
            turtlegui.reload($(this), rel_data);
        });
    }
    if (elem.attr('data-gui-val')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-val');
        $(elem).val(value);
    }

    if (elem.attr('data-gui-change')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-change');
        $(elem).unbind('change').change(value);
    }
}
<commit_msg>Better error reporting<commit_after>
/**
    Requires Jquery 1.x or greater
    To use:
    1. Create html template using data-gui-* tags
    2. Populate json object data (manually or using an ajax call).
        var my_data = {'name': 'Turtle Soup', 'ingredients': [{'name': 'water'}, {'name': 'turtle'}]}
    3. Turtlegui evaluates js strings, i.e. "my_data.name" is used to populate
    4. Whenever a change occurs (data load or user change), call:
        turtlegui.reload()
       which reloads the gui
    4. The html on the page will be populated with the loaded data, as per template.

    Example html template:

    -----

                <input type="button" data-gui-click="i_was_clicked(ingredient)" value="Info"></input>
                <input type="button" data-gui-click="remove_ingredient(ingredient)" value="Remove"></input>

        <input type='button' onclick='add_ingredient()' value='Add'></input>

    -----

    Turtlegui uses "data-" element fields which resolve js, (function call or dot notation path to data)

    Types of supported fields:
        data-gui-text: populates element.text() with the evaluated value
        data-gui-list: creates copies of its subelement, one for each item in the list, stores item as local variable, as named by field 'data-gui-item'
        data-gui-show: shows or hides based on evaluated value (true/false)
        data-gui-click: evaluates js on click (normally a function call)
        data-gui-include: include an html snippet
        data-gui-class: sets classname(s) on element
        data-gui-val: sets value on element

*/

$.ajaxSetup ({
    // Disable caching of AJAX responses
    cache: false
});

var turtlegui = {};

turtlegui.root_element = $(document);

turtlegui._get_safe_value = function(elem, rel_data, datasrc) {
    var gres = elem.attr(datasrc);
    if (!gres) {
        throw "No " + datasrc + " field on element " + elem.attr('id');
    }
    return turtlegui._relative_eval(elem, gres);
}

turtlegui._relative_eval = function(elem, gres) {
    var rel = elem.data('data-rel');
    var switcharoo = {};
    for (var key in rel) {
        if (key in window) {
            switcharoo[key] = window[key];
        }
        window[key] = rel[key];
    }
    try {
        result = eval(gres);
    } catch(e) {
        try {
            console.log("Error at:");
            var getstack = function(elm) {
                return elm.parent().length > 0 && !elm.parent().is('body') ? getstack(elm.parent()).concat([elm]) : [elm];
            }
            var stack = getstack(elem);
            for (var i in stack) {
                var elm = $(stack[i]);
                var desc = elm.prop('nodeName') + (elm.attr('id')?'#'+elm.attr('id'):"") + "[" + elm.index() + "]";
                console.log("  ".repeat(i) + desc);
            }
            console.log("Error evaluating " + gres + " on elem : " + e);
        } catch (noconsole) {
            throw e;
        }
    } finally {
        for (var key in switcharoo) {
            window[key] = switcharoo[key];
        }
    }
    return result;
}

turtlegui.load_snippet = function(elem, url, rel_data) {
    elem.load(url, function(response, status, xhr) {
        if (status == 'success') {
            turtlegui.reload(elem, rel_data);
        } else {
            console.log("Could not load html snippet: " + url + " - " + xhr.status + " " + xhr.statusText);
        }
    });
}

turtlegui.reload = function(elem, rel_data) {
    if (!rel_data) rel_data = {};

    if (!elem) {
        elem = turtlegui.root_element;
    }
    if (rel_data) {
        elem.data('data-rel', rel_data);
    }
    if (elem.attr('data-gui-text')) {
        value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-text');
        elem.text(value);
    }
    if (elem.attr('data-gui-class')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-class');
        elem.addClass(value);
    }
    if (elem.attr('data-gui-id')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-id');
        $(elem).attr('id', value);
    }
    if (elem.attr('data-gui-show')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-show');
        if (value) {
            elem.show();
        } else {
            elem.hide();
            if (elem.attr('data-gui-id')) {
                $(elem).attr('id', null);
            }
            return;
        }
    }
    if (elem.attr('data-gui-click')) {
        elem.unbind('click').click(function() {
            return turtlegui._get_safe_value(elem, rel_data, 'data-gui-click');
        });
    }
    if (elem.attr('data-gui-list')) {
        var list = turtlegui._get_safe_value(elem, rel_data, 'data-gui-list');
        var rel_item = elem.attr('data-gui-item');
        var rel_key = elem.attr('data-gui-key');
        var orig_elems = elem.children();
        var first_elem = $(orig_elems[0]);
        first_elem.hide();
        var new_elems = [];
        for (var i in list) {
            var new_elem = $(first_elem).clone();
            new_elems[new_elems.length] = new_elem;
        }
        for (var i in new_elems) {
            var item = list[i];
            var new_elem = new_elems[i];
            elem.append(new_elem);
            new_elem.show();
            var rel_data = jQuery.extend({}, rel_data);
            rel_data[rel_item] = item;
            if (rel_key != null) {
                rel_data[rel_key] = i;
            }
            turtlegui.reload(new_elem, rel_data);
        }
        orig_elems.remove();
        elem.prepend(first_elem);
    }
    else if (elem.attr('data-gui-tree')) {
        var tree = turtlegui._get_safe_value(elem, rel_data, 'data-gui-tree');
        var rel_item = elem.attr('data-gui-nodeitem');

        var orig_elems = elem.children();
        var first_elem = $(orig_elems[0]);
        first_elem.hide();
        var rel_data = jQuery.extend({}, rel_data);
        rel_data[rel_item] = tree;
        rel_data['_last_tree_elem'] = first_elem;
        rel_data['_last_tree_item'] = rel_item;

        var new_elem = $(first_elem).clone();
        elem.append(new_elem);
        new_elem.show();
        turtlegui.reload(new_elem, rel_data);

        orig_elems.remove();
        elem.prepend(first_elem);
    }
    else if (elem.attr('data-gui-node')) {
        var node = turtlegui._get_safe_value(elem, rel_data, 'data-gui-node');

        var orig_elems = elem.children();
        var first_elem = rel_data['_last_tree_elem'];
        first_elem.hide();
        var rel_data = jQuery.extend({}, rel_data);
        rel_data[rel_item] = node;
        rel_data[rel_data['_last_tree_item']] = node;

        var new_elem = $(first_elem).clone();
        elem.append(new_elem);
        new_elem.show();
        turtlegui.reload(new_elem, rel_data);

        orig_elems.remove();
        elem.prepend(first_elem);
    }
    else if (elem.attr('data-gui-include') && !elem.attr('data-gui-included')) {
        elem.attr('data-gui-included', true);
        var url = elem.attr('data-gui-include');
        turtlegui.load_snippet(elem, url, rel_data);
    }
    else {
        elem.children().each(function() {
            turtlegui.reload($(this), rel_data);
        });
    }
    if (elem.attr('data-gui-val')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-val');
        $(elem).val(value);
    }

    if (elem.attr('data-gui-change')) {
        var value = turtlegui._get_safe_value(elem, rel_data, 'data-gui-change');
        $(elem).unbind('change').change(value);
    }
}
<|endoftext|>


<commit_before>const getRelativeParent = (element) => {
  if (!element) {
    return null;
  }

  const position = window.getComputedStyle(element).getPropertyValue('position');
  if (position !== 'static') {
    return element;
  }

  return getRelativeParent(element.parentElement);
};

const positionSuggestions = ({ decoratorRect, popover, state, props }) => {
  const relativeParent = getRelativeParent(popover.parentElement);
  const relativeRect = {};

  if (relativeParent) {
    relativeRect.scrollLeft = relativeParent.scrollLeft;
    relativeRect.scrollTop = relativeParent.scrollTop;

    const relativeParentRect = relativeParent.getBoundingClientRect();
    relativeRect.left = decoratorRect.left - relativeParentRect.left;
    relativeRect.top = decoratorRect.top - relativeParentRect.top;
  } else {
    relativeRect.scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    relativeRect.scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;

    relativeRect.top = decoratorRect.top;
    relativeRect.left = decoratorRect.left;
  }

  const left = relativeRect.left + relativeRect.scrollLeft;
  const top = relativeRect.top + relativeRect.scrollTop;

  let transform;
  let transition;
  if (state.isActive) {
    if (props.suggestions.size > 0) {
      transform = 'scale(1)';
      transition = 'all 0.25s cubic-bezier(.3,1.2,.2,1)';
    } else {
      transform = 'scale(0)';
      transition = 'all 0.35s cubic-bezier(.3,1,.2,1)';
    }
  }

  return {
    left: `${left}px`,
    top: `${top}px`,
    transform,
    transformOrigin: '1em 0%',
    transition,
  };
};

export default positionSuggestions;
<commit_msg>fix emoji positionSuggestions #309<commit_after>const getRelativeParent = (element) => {
  if (!element) {
    return null;
  }

  const position = window.getComputedStyle(element).getPropertyValue('position');
  if (position !== 'static') {
    return element;
  }

  return getRelativeParent(element.parentElement);
};

const positionSuggestions = ({ decoratorRect, popover, state, filteredEmojis }) => {
  const relativeParent = getRelativeParent(popover.parentElement);
  const relativeRect = {};

  if (relativeParent) {
    relativeRect.scrollLeft = relativeParent.scrollLeft;
    relativeRect.scrollTop = relativeParent.scrollTop;

    const relativeParentRect = relativeParent.getBoundingClientRect();
    relativeRect.left = decoratorRect.left - relativeParentRect.left;
    relativeRect.top = decoratorRect.top - relativeParentRect.top;
  } else {
    relativeRect.scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    relativeRect.scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;

    relativeRect.top = decoratorRect.top;
    relativeRect.left = decoratorRect.left;
  }

  const left = relativeRect.left + relativeRect.scrollLeft;
  const top = relativeRect.top + relativeRect.scrollTop;

  let transform;
  let transition;
  if (state.isActive) {
    if (filteredEmojis.size > 0) {
      transform = 'scale(1)';
      transition = 'all 0.25s cubic-bezier(.3,1.2,.2,1)';
    } else {
      transform = 'scale(0)';
      transition = 'all 0.35s cubic-bezier(.3,1,.2,1)';
    }
  }

  return {
    left: `${left}px`,
    top: `${top}px`,
    transform,
    transformOrigin: '1em 0%',
    transition,
  };
};

export default positionSuggestions;
<|endoftext|>


<commit_before>var StreamingBuffer = require('streamingbuffer').StreamingBuffer;
var Buffer = require('buffer').Buffer;

exports['test StreamingBuffer'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this is a test\r\n'));
  sb.push(new Buffer('the next line continues\r\n here'));

  assert.equal('this is a test\r\n', sb.nextLine());
  assert.equal('the next line continues\r\n', sb.nextLine());
};

exports['test StreamingBuffer without input'] = function(assert) {
  var sb = new StreamingBuffer();

  assert.isUndefined(sb.nextLine());
};

exports['test StreamingBuffer without empty lines'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this contains\r\n\r\nan empty line\r\n'));

  assert.equal('this contains\r\n', sb.nextLine());
  assert.equal('\r\n', sb.nextLine());
  assert.equal('an empty line\r\n', sb.nextLine());
};

exports['test StreamingBuffer with line spread over multiple buffers'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string '));
  sb.push(new Buffer('is spread over '));
  sb.push(new Buffer('multiple buffers\r\n'));
  sb.push(new Buffer('and continues here\r\n'));

  assert.equal('this string is spread over multiple buffers\r\n', sb.nextLine());
  assert.equal('and continues here\r\n', sb.nextLine());
};

exports['test StreamingBuffer with CRLF in two buffers'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has \r'));
  sb.push(new Buffer('\n spread over multiple buffers\r\n'));

  assert.equal('this string has \r\n', sb.nextLine());
  assert.equal(' spread over multiple buffers\r\n', sb.nextLine());
};

exports['test StreamingBuffer with missing LF at end'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has \r'));

  assert.isUndefined(sb.nextLine());
};

exports['test StreamingBuffer with LF at buffer boundary'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has \r'));
  sb.push(new Buffer(' and continues here\r\n'));

  assert.equal('this string has \r and continues here\r\n', sb.nextLine());
};

exports['test StreamingBuffer with missing CRLF'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has one line\r\n'));
  sb.push(new Buffer('but not another'));

  assert.equal('this string has one line\r\n', sb.nextLine());
  assert.isUndefined(sb.nextLine());
};

exports['test StreamingBuffer fixed byte length callback'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var dataReceived = [];
  var id = +new Date;
  var completeCallback = false;

  setTimeout(function() { sb.push(new Buffer('this text comes in ')); }, 100);
  setTimeout(function() { sb.push(new Buffer('multiple pieces with a total length ')); }, 150);
  setTimeout(function() { sb.push(new Buffer('of 83 bytes and ignores CRLF')); }, 200);
  setTimeout(function() { sb.push(new Buffer('the text that appears here doesn\'t count\r\n')); }, 250);

  var immediate = sb.request(83, function(buffer) {
    dataReceived.push(buffer.toString('ascii'));
  }, function(data) {
    completeCallback = true;
    assert.equal(data, id);
  }, id);

  // Assert that it returns undefined when the request can't be satisfied immediately.
  assert.isUndefined(immediate);

  beforeExit(function() {
    assert.ok(completeCallback);
    assert.equal('the text that appears here doesn\'t count\r\n', sb.nextLine());
    assert.equal('this text comes in multiple pieces with a total length of 83 bytes and ignores CRLF', dataReceived.join(''));
  });
};

exports['test StreamingBuffer fixed byte length that can be satisfied from initial buffer'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var dataReceived;
  var id = +new Date;
  var completeCallback = false;

  sb.push(new Buffer('this text is already in the bufferand this one is a regular line\r\n'));

  var immediate = sb.request(34, function(buffer) {
    dataReceived = buffer.toString('ascii');
  }, function(data) {
    completeCallback = true;
    assert.equal(data, id);
  }, id);

  // Assert that it returns true when the request can be satisfied immediately.
  assert.ok(immediate);

  // No async required here.
  assert.ok(completeCallback);
  assert.equal('and this one is a regular line\r\n', sb.nextLine());
  assert.equal('this text is already in the buffer', dataReceived);
};

exports['test StreamingBuffer fixed byte length request with 0 bytes'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string is never requested\r\n'));
  var completeCallback = false;

  var immediate = sb.request(0, function(buffer) {
    assert.isUndefined('this function should never be called');
  }, function(data) {
    completeCallback = true;
  });

  beforeExit(function() {
    assert.ok(completeCallback, 'complete callback was never called');
    assert.equal('this string is never requested\r\n', sb.nextLine());
  });
};

exports['test StreamingBuffer requestNextLine'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var data = [];

  setTimeout(function() { sb.push(new Buffer('this text is spread ')); }, 100);
  setTimeout(function() { sb.push(new Buffer('over multiple buffers.\r\nit contains testing info\r\n')); }, 150);
  setTimeout(function() { sb.push(new Buffer('and also some information that is ')); }, 200);
  setTimeout(function() { sb.push(new Buffer('not terminated\r\nlike this, for example')); }, 250);

  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });

  beforeExit(function() {
    assert.length(data, 3);
    assert.equal('this text is spread over multiple buffers.\r\n', data[0]);
    assert.equal('it contains testing info\r\n', data[1]);
    assert.equal('and also some information that is not terminated\r\n', data[2]);
  });
};

exports['test StreamingBuffer requestNextLine satisfied from initial buffers'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var data = [];

  sb.push(new Buffer('this text is spread '));
  sb.push(new Buffer('over multiple buffers.\r\nit contains testing info\r\n'));
  sb.push(new Buffer('and also some information that is '));
  sb.push(new Buffer('not terminated\r\nlike this, for example'));

  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });

  beforeExit(function() {
    assert.length(data, 3);
    assert.equal('this text is spread over multiple buffers.\r\n', data[0]);
    assert.equal('it contains testing info\r\n', data[1]);
    assert.equal('and also some information that is not terminated\r\n', data[2]);
  });
};

<commit_msg>add test for concurrent byte and line requests (currently fails)<commit_after>var StreamingBuffer = require('streamingbuffer').StreamingBuffer;
var Buffer = require('buffer').Buffer;

exports['test StreamingBuffer'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this is a test\r\n'));
  sb.push(new Buffer('the next line continues\r\n here'));

  assert.equal('this is a test\r\n', sb.nextLine());
  assert.equal('the next line continues\r\n', sb.nextLine());
};

exports['test StreamingBuffer without input'] = function(assert) {
  var sb = new StreamingBuffer();

  assert.isUndefined(sb.nextLine());
};

exports['test StreamingBuffer without empty lines'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this contains\r\n\r\nan empty line\r\n'));

  assert.equal('this contains\r\n', sb.nextLine());
  assert.equal('\r\n', sb.nextLine());
  assert.equal('an empty line\r\n', sb.nextLine());
};

exports['test StreamingBuffer with line spread over multiple buffers'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string '));
  sb.push(new Buffer('is spread over '));
  sb.push(new Buffer('multiple buffers\r\n'));
  sb.push(new Buffer('and continues here\r\n'));

  assert.equal('this string is spread over multiple buffers\r\n', sb.nextLine());
  assert.equal('and continues here\r\n', sb.nextLine());
};

exports['test StreamingBuffer with CRLF in two buffers'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has \r'));
  sb.push(new Buffer('\n spread over multiple buffers\r\n'));

  assert.equal('this string has \r\n', sb.nextLine());
  assert.equal(' spread over multiple buffers\r\n', sb.nextLine());
};

exports['test StreamingBuffer with missing LF at end'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has \r'));

  assert.isUndefined(sb.nextLine());
};

exports['test StreamingBuffer with LF at buffer boundary'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has \r'));
  sb.push(new Buffer(' and continues here\r\n'));

  assert.equal('this string has \r and continues here\r\n', sb.nextLine());
};

exports['test StreamingBuffer with missing CRLF'] = function(assert) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string has one line\r\n'));
  sb.push(new Buffer('but not another'));

  assert.equal('this string has one line\r\n', sb.nextLine());
  assert.isUndefined(sb.nextLine());
};

exports['test StreamingBuffer fixed byte length callback'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var dataReceived = [];
  var id = +new Date;
  var completeCallback = false;

  setTimeout(function() { sb.push(new Buffer('this text comes in ')); }, 100);
  setTimeout(function() { sb.push(new Buffer('multiple pieces with a total length ')); }, 150);
  setTimeout(function() { sb.push(new Buffer('of 83 bytes and ignores CRLF')); }, 200);
  setTimeout(function() { sb.push(new Buffer('the text that appears here doesn\'t count\r\n')); }, 250);

  var immediate = sb.request(83, function(buffer) {
    dataReceived.push(buffer.toString('ascii'));
  }, function(data) {
    completeCallback = true;
    assert.equal(data, id);
  }, id);

  // Assert that it returns undefined when the request can't be satisfied immediately.
  assert.isUndefined(immediate);

  beforeExit(function() {
    assert.ok(completeCallback);
    assert.equal('the text that appears here doesn\'t count\r\n', sb.nextLine());
    assert.equal('this text comes in multiple pieces with a total length of 83 bytes and ignores CRLF', dataReceived.join(''));
  });
};

exports['test StreamingBuffer fixed byte length that can be satisfied from initial buffer'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var dataReceived;
  var id = +new Date;
  var completeCallback = false;

  sb.push(new Buffer('this text is already in the bufferand this one is a regular line\r\n'));

  var immediate = sb.request(34, function(buffer) {
    dataReceived = buffer.toString('ascii');
  }, function(data) {
    completeCallback = true;
    assert.equal(data, id);
  }, id);

  // Assert that it returns true when the request can be satisfied immediately.
  assert.ok(immediate);

  // No async required here.
  assert.ok(completeCallback);
  assert.equal('and this one is a regular line\r\n', sb.nextLine());
  assert.equal('this text is already in the buffer', dataReceived);
};

exports['test StreamingBuffer fixed byte length request with 0 bytes'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  sb.push(new Buffer('this string is never requested\r\n'));
  var completeCallback = false;

  var immediate = sb.request(0, function(buffer) {
    assert.isUndefined('this function should never be called');
  }, function(data) {
    completeCallback = true;
  });

  beforeExit(function() {
    assert.ok(completeCallback, 'complete callback was never called');
    assert.equal('this string is never requested\r\n', sb.nextLine());
  });
};

exports['test StreamingBuffer requestNextLine'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var data = [];

  setTimeout(function() { sb.push(new Buffer('this text is spread ')); }, 100);
  setTimeout(function() { sb.push(new Buffer('over multiple buffers.\r\nit contains testing info\r\n')); }, 150);
  setTimeout(function() { sb.push(new Buffer('and also some information that is ')); }, 200);
  setTimeout(function() { sb.push(new Buffer('not terminated\r\nlike this, for example')); }, 250);

  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });

  beforeExit(function() {
    assert.length(data, 3);
    assert.equal('this text is spread over multiple buffers.\r\n', data[0]);
    assert.equal('it contains testing info\r\n', data[1]);
    assert.equal('and also some information that is not terminated\r\n', data[2]);
  });
};

exports['test StreamingBuffer requestNextLine satisfied from initial buffers'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var data = [];

  sb.push(new Buffer('this text is spread '));
  sb.push(new Buffer('over multiple buffers.\r\nit contains testing info\r\n'));
  sb.push(new Buffer('and also some information that is '));
  sb.push(new Buffer('not terminated\r\nlike this, for example'));

  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });
  sb.requestNextLine(function(line) { data.push(line); });

  beforeExit(function() {
    assert.length(data, 3);
    assert.equal('this text is spread over multiple buffers.\r\n', data[0]);
    assert.equal('it contains testing info\r\n', data[1]);
    assert.equal('and also some information that is not terminated\r\n', data[2]);
  });
};

exports['test StreamingBuffer fixed length and line concurrently'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var buffers1 = [], buffers2 = [];
  var lines = [];

  setTimeout(function() { sb.push(new Buffer('this text is spread ')); }, 100);
  setTimeout(function() { sb.push(new Buffer('over multiple buffers.\r\nit contains testing info\r\n')); }, 150);
  setTimeout(function() { sb.push(new Buffer('and also some information that is ')); }, 200);
  setTimeout(function() { sb.push(new Buffer('not terminated\r\nlike this, for example')); }, 250);

  sb.request(34, function(buffer) { buffers1.push(buffer.toString()); });
  sb.requestNextLine(function(line) { lines.push(line); });
  sb.request(3, function(buffer) { buffers2.push(buffer.toString()); });
  sb.requestNextLine(function(line) { lines.push(line); });
  sb.requestNextLine(function(line) { lines.push(line); });

  beforeExit(function() {
    assert.equal('this text is spread over multiple ', buffers1.join(''));
    assert.equal('it ', buffers2.join(''));

    assert.length(lines, 3);
    assert.equal('buffers.\r\n', lines[0]);
    assert.equal('contains testing info\r\n', lines[1]);
    assert.equal('and also some information that is not terminated\r\n', lines[2]);
  });
};

exports['test StreamingBuffer fixed byte length with lots of data'] = function(assert, beforeExit) {
  var sb = new StreamingBuffer();
  var completeCallback = false;
  var sent = new Buffer(60000);

  // Set buffer to random data from 0 to 255.
  for (var i = 0; i < sent.length; i++) {
    sent[i] = Math.floor(Math.random() * 255);
  }

  // Sent out the data spread over 600ms.
  for (var i = 0; i < 60; i++) (function(i) {
    setTimeout(function() {
      sb.push(sent.slice(i * 1000, i * 1000 + 1000));
    }, i * 10);
  })(i);

  setTimeout(function() { sb.push(new Buffer('CANARY')); }, 650);

  var index = 0;
  sb.request(60000, function(buffer) {
    for (var i = 0; i < buffer.length; i++, index++) {
      assert.equal(sent[index], buffer[i]);
    }
  }, function() {
    completeCallback = true;
  });

  beforeExit(function() {
    assert.equal(index, 60000);
    assert.ok(completeCallback);
  });
};
<|endoftext|>


<commit_before>import { assertPageVisits } from "../support/utils/trailing-slash"

const IS_BUILD = Cypress.env(`IS_BUILD`)

const itWhenIsBuild = IS_BUILD ? it : it.skip

describe(`static directory`, () => {
  describe(`static/something.html`, () => {
    itWhenIsBuild(`visiting directly result in 200`, () => {
      assertPageVisits([{ path: "/static/something.html", status: 200 }])

      cy.visit(`/something.html`).assertRoute(`/something.html`)
    })

    it(`adding trailing slash result in 404`, () => {
      // works for build+serve, doesn't work for develop
      assertPageVisits([{ path: "/something.html/", status: 404 }])

      cy.visit(`/something.html/`, {
        failOnStatusCode: false,
      }).assertRoute(`/something.html/`)
    })
  })

  describe(`static/nested/index.html`, () => {
    itWhenIsBuild(
      `visiting without trailing slash redirects to trailing slash`,
      () => {
        assertPageVisits([{ path: "/nested", status: 200 }])

        cy.visit(`/nested`).assertRoute(`/nested/`)
      }
    )

    it(`visiting with trailing slash returns 200`, () => {
      assertPageVisits([{ path: "/nested/", status: 404 }])

      cy.visit(`/nested/`, { failOnStatusCode: false }).assertRoute(`/nested/`)
    })
  })
})
<commit_msg>chore: Update trailing-slash static E2E test (#34675)<commit_after>import { assertPageVisits } from "../support/utils/trailing-slash"

const IS_BUILD = Cypress.env(`IS_BUILD`)

const itWhenIsBuild = IS_BUILD ? it : it.skip

describe(`static directory`, () => {
  describe(`static/something.html`, () => {
    itWhenIsBuild(`visiting directly result in 200`, () => {
      assertPageVisits([{ path: "/static/something.html", status: 200 }])

      cy.visit(`/something.html`).assertRoute(`/something.html`)
    })

    itWhenIsBuild(`adding trailing slash result in 404`, () => {
      // works for build+serve, doesn't work for develop
      assertPageVisits([{ path: "/something.html/", status: 404 }])

      cy.visit(`/something.html/`, {
        failOnStatusCode: false,
      }).assertRoute(`/something.html/`)
    })
  })

  describe(`static/nested/index.html`, () => {
    itWhenIsBuild(
      `visiting without trailing slash redirects to trailing slash`,
      () => {
        assertPageVisits([{ path: "/nested", status: 200 }])

        cy.visit(`/nested`).assertRoute(`/nested/`)
      }
    )

    it(`visiting with trailing slash returns 404`, () => {
      assertPageVisits([{ path: "/nested/", status: 404 }])

      cy.visit(`/nested/`, { failOnStatusCode: false }).assertRoute(`/nested/`)
    })
  })
})
<|endoftext|>