<commit_before>/**
 * Table
 *
 * @module      :: Model
 * @description :: This model represents a table with scores in the database
 * @docs		:: http://sailsjs.org/#!documentation/models
 */

var _ = require('lodash');

module.exports = {

	tableName: 'tables',

	types: {
		// Returns if the method exists (default), or works (function)
		oneOfMethods: function(val){
			var method = getMethodFor(val);
			return (method ? true : false);
		}
	},

	attributes: {
		name: {
			type: 'string',
			defaultsTo: '[Table Name]'
		},

		/*
			Scores data are inserted in another table, and linked with this
			with the tableId field.
			In order to compute the table data, it's needed to 'associate'
			this object with the found with 'Scores' model, and set on this object
			with key 'scores'.

			Ex:
			Scores.find({tableId: 'id'}).done(function(collection){
				table.scores = collection;
			});

			var tableData = Scores.computeTable();
		*/

		/*
			Just to help views, disabling/enabling some actions
		*/
		locked: {
			type: 'string',
			in: ['yes', 'no'],
			defaultsTo: 'no',
		},

		/*
			Name for 'Rank' heading
		*/
		headerRank: {
			type: 'string',
			defaultsTo: 'Rank',
		},
		/*
			Name for 'Team' heading
		*/
		headerTeam: {
			type: 'string',
			defaultsTo: 'Team',
		},
		/*
			Prepended value for scores.
			in case this equals to 'Score', headers will be generated as follows:
				'Score 1', 'Score 2', 'Score 3'
		*/
		headerScore: {
			type: 'string',
			defaultsTo: 'Score',
		},
		/*
			Name for 'Final' score heading
		*/
		headerFinal: {
			type: 'string',
			defaultsTo: 'Final',
		},

		/*
			This field, represents 'how many' scores will a single
			Team in the row have.

			The minimum is one, since a table with no scores doesn't make sense
		*/
		columns: {
			type: 'int',
			defaultsTo: 1,
			min: 1,
		},

		/*
			This affects how the 'Ranking' will be exposed.
			Wheater a 'lower' final score will be ranked better,
			or an 'higher' final score will be ranked better.
		*/
		sort: {
			type: 'string',
			in: ['asc', 'desc'],
			defaultsTo: 'desc',
		},

		/*
			evaluateMethod is what actualy 'computes' the final score
			for each row (team) in the table. There are some 'default'
			function used to help, you also can 'write' your JavaScript
			method for that.

			Available default methods:
			+ sum    - sum all scores
			+ max    - the maximum value within scores
			+ min    - the minimum value within scores
			+ Anything else is threated as a literal function, with the following pattern:

			  	function(scores){
					// Literal method is inserted here
					// ...do calculation...
					// return final value
			  	}

			  	example:
			  	evaluateMethod =
			  	"var finalScore = 0;
				for(var k in scores){
					finalScore += scores[k]*1;
				}
				return finalScore;";

		*/
		evaluateMethod: {
			type: 'string',
			defaultsTo: 'sum',
			oneOfMethods: true // <- type of validation
		},

		/*
			This method will generate the table with all it's fields.

			return data will be on the following format:

			{
				headers: {'rank': 'Rank', 'team': 'Team', 'score.1': 'Score 1', 'final': 'Final'},
				data: [
					{'rank': 1, 'team':Team...'[,..] ],
					{'rank': 2, 'team':Team...'[,..] ],
					[...]
				],
			}

		*/
		calculate: generateTableDataInsideScores,
		// headers: generateTableHeaders,

	},

	beforeUpdate: function(attrs, next){
		removeBadFields(attrs);
		next();
	},

	beforeCreate: function(attrs, next){
		removeBadFields(attrs);
		next();
	},

};

/*
	Generate the table headers
*/
function generateTableHeaders(){
	// Save to allow in function referencte
	var table = this;
	var columns = table.columns*1;

	/*
		Create headers array
		Rank | Team | Score 1 | Score N | Final
	*/

	var headers = {};

	headers['rank'] = table.headerRank;
	headers['team'] = table.headerTeam;

	// Create Scores header
	for(var i = 1; i <= columns; i++)
		headers['score.'+(i)] = table.headerScore + ' ' + i;

	// Add last header (Final score)
	headers['final'] = table.headerFinal;

	// Self assign headers and return
	this.headers = headers;
	return headers;
}

/*
	Generates the table data inside scores objects
*/
function generateTableDataInsideScores(){
	// Save to allow in function referencte
	var table = this;
	var columns = table.columns*1;

	/*
		Create data table
	*/
	var scores = table.scores;

	// Just warn (DEBUG mode...)
	if(!scores)
		console.log('Table is empty!');

	// Get evaluation method ('min', 'max', custom...)
	var evalMethod = getMethodFor(table.evaluateMethod);

	// Go through all scores, creating a unique row
	_(scores).forEach(function(score){
		/*
			Notice score structure:

			{
				tableId: [this table id]
				teamId: xxx,
				scores: {
					  0: {value: xxx, data: {}},
					'1': {value: xxx, data: {}},
					  2: {value: xxx, data: {}}
					  [...],
				}
			}
		*/

		// This will be the object inserted in the table's data array
		// var scoreData = {};

		// Add simple attributes
		// scoreData['id'] = score.id || null;
		// scoreData['teamId'] = score.teamId || null;
		// scoreData['tableId'] = score.tableId || null;
		// scoreData['team'] = score.teamId || null;
		// scoreData.team: score.team.name
		// scoreData.country: score.team.country

		// Add scores data
		var scoreValues = [];
		for(var i = 0; i < columns; i++){

			// Get value and add to scoreValues
			var value = null;
			if(score.scores[i])
				value = score.scores[i].value;

			scoreValues.push(value);

			// Generate field key and saves
			// var field = 'score.'+(i+1);
			// score[field] = score.scores.value || null;
		}

		// Compute final score and adds to scoreData
		score['final'] = evalMethod(scoreValues);

		// Add to table data
		// tableRows.push(score)
	});

	// Sort by 'final' field and reverse if needed
	var finalData = _.sortBy(scores, 'score');

	if(table.order == 'asc')
		finalData = finalTable.reverse()

	// Rank Table
	var pos = 0;
	var lastScore = -1;

	_.forEach(finalData, function(row){
		// Keeps the same ranking if scores is the same
		if(lastScore != row.score){
			pos++;
			lastScore = row.score;
		}

		row.rank = pos;
	});

	// Self assign the table
	this.scores = finalData;

	// Return the table
	return this.scores;
}

/*
	Default methods instantiation
*/
var evaluateMethods = {};

// Max method
evaluateMethods.max = function(scores){
	return _.max(scores, function(val) {
		return val*1;
	});
};

// Min method
evaluateMethods.min = function(scores){
	return _.min(scores, function(val) {
		return val*1;
	});
};

// Sum method
evaluateMethods.sum = function(scores){
	return _.reduce(scores, function(sum, num) {
		return sum + num*1;
	});
};

/*
	This will try to find a default method.
	If not succeed, will try to parse as a function.
	If not succeeded, will return null.

	In sum: Will return a function if succeeds, otherwise, 'null'
*/
function getMethodFor(methodRaw){
	// Try to find in defaults
	if(evaluateMethods[methodRaw])
		return evaluateMethods[methodRaw];

	// Else, try to return a new function with it
	try{
		var method = Function('scores', methodRaw);
		method();
		return method;
	}catch(err){
	}
	return null;
}

/*
	Method used to remove fields that are not supposed to
	be there, on create and update.
*/
function removeBadFields(attrs){
	var badList = ['scores', 'table', 'headers'];
	for(var k in badList){
		if(attrs[badList[k]])
			delete attrs[badList[k]];
	}
}

/*
	Tests
*/
// var testCase = {0: 100, 1: 213, '2':'5'};

// var methods = [
// 	'sum',
// 	'min',
// 	'max',
// 	"var finalScore = 0;"+
// 	"for(var k in scores){"+
// 		"finalScore += scores[k]*1;"+
// 	"}"+
// 	"return finalScore;"
// ];

// for(var m in methods)
// 	console.log(getMethodFor(methods[m])(testCase) + ' : '+ methods[m]);
// console.log(evaluateMethodGet('max')
<commit_msg>Fixed sorting and ranking<commit_after>/**
 * Table
 *
 * @module      :: Model
 * @description :: This model represents a table with scores in the database
 * @docs		:: http://sailsjs.org/#!documentation/models
 */

var _ = require('lodash');

module.exports = {

	tableName: 'tables',

	types: {
		// Returns if the method exists (default), or works (function)
		oneOfMethods: function(val){
			var method = getMethodFor(val);
			return (method ? true : false);
		}
	},

	attributes: {
		name: {
			type: 'string',
			defaultsTo: '[Table Name]'
		},

		/*
			Scores data are inserted in another table, and linked with this
			with the tableId field.
			In order to compute the table data, it's needed to 'associate'
			this object with the found with 'Scores' model, and set on this object
			with key 'scores'.

			Ex:
			Scores.find({tableId: 'id'}).done(function(collection){
				table.scores = collection;
			});

			var tableData = Scores.computeTable();
		*/

		/*
			Just to help views, disabling/enabling some actions
		*/
		locked: {
			type: 'string',
			in: ['yes', 'no'],
			defaultsTo: 'no',
		},

		/*
			Name for 'Rank' heading
		*/
		headerRank: {
			type: 'string',
			defaultsTo: 'Rank',
		},
		/*
			Name for 'Team' heading
		*/
		headerTeam: {
			type: 'string',
			defaultsTo: 'Team',
		},
		/*
			Prepended value for scores.
			in case this equals to 'Score', headers will be generated as follows:
				'Score 1', 'Score 2', 'Score 3'
		*/
		headerScore: {
			type: 'string',
			defaultsTo: 'Score',
		},
		/*
			Name for 'Final' score heading
		*/
		headerFinal: {
			type: 'string',
			defaultsTo: 'Final',
		},

		/*
			This field, represents 'how many' scores will a single
			Team in the row have.

			The minimum is one, since a table with no scores doesn't make sense
		*/
		columns: {
			type: 'int',
			defaultsTo: 1,
			min: 1,
		},

		/*
			This affects how the 'Ranking' will be exposed.
			Wheater a 'lower' final score will be ranked better,
			or an 'higher' final score will be ranked better.
		*/
		sort: {
			type: 'string',
			in: ['asc', 'desc'],
			defaultsTo: 'desc',
		},

		/*
			evaluateMethod is what actualy 'computes' the final score
			for each row (team) in the table. There are some 'default'
			function used to help, you also can 'write' your JavaScript
			method for that.

			Available default methods:
			+ sum    - sum all scores
			+ max    - the maximum value within scores
			+ min    - the minimum value within scores
			+ Anything else is threated as a literal function, with the following pattern:

			  	function(scores){
					// Literal method is inserted here
					// ...do calculation...
					// return final value
			  	}

			  	example:
			  	evaluateMethod =
			  	"var finalScore = 0;
				for(var k in scores){
					finalScore += scores[k]*1;
				}
				return finalScore;";

		*/
		evaluateMethod: {
			type: 'string',
			defaultsTo: 'sum',
			oneOfMethods: true // <- type of validation
		},

		/*
			This method will generate the table with all it's fields.

			return data will be on the following format:

			{
				headers: {'rank': 'Rank', 'team': 'Team', 'score.1': 'Score 1', 'final': 'Final'},
				data: [
					{'rank': 1, 'team':Team...'[,..] ],
					{'rank': 2, 'team':Team...'[,..] ],
					[...]
				],
			}

		*/
		calculate: generateTableDataInsideScores,
		// headers: generateTableHeaders,

	},

	beforeUpdate: function(attrs, next){
		removeBadFields(attrs);
		next();
	},

	beforeCreate: function(attrs, next){
		removeBadFields(attrs);
		next();
	},

};

/*
	Generate the table headers
*/
function generateTableHeaders(){
	// Save to allow in function referencte
	var table = this;
	var columns = table.columns*1;

	/*
		Create headers array
		Rank | Team | Score 1 | Score N | Final
	*/

	var headers = {};

	headers['rank'] = table.headerRank;
	headers['team'] = table.headerTeam;

	// Create Scores header
	for(var i = 1; i <= columns; i++)
		headers['score.'+(i)] = table.headerScore + ' ' + i;

	// Add last header (Final score)
	headers['final'] = table.headerFinal;

	// Self assign headers and return
	this.headers = headers;
	return headers;
}

/*
	Generates the table data inside scores objects
*/
function generateTableDataInsideScores(){
	// Save to allow in function referencte
	var table = this;
	var columns = table.columns*1;

	/*
		Create data table
	*/
	var scores = table.scores;

	// Just warn (DEBUG mode...)
	if(!scores)
		console.log('Table is empty!');

	// Get evaluation method ('min', 'max', custom...)
	var evalMethod = getMethodFor(table.evaluateMethod);

	// Go through all scores, creating a unique row
	_(scores).forEach(function(score){
		/*
			Notice score structure:

			{
				tableId: [this table id]
				teamId: xxx,
				scores: {
					  0: {value: xxx, data: {}},
					'1': {value: xxx, data: {}},
					  2: {value: xxx, data: {}}
					  [...],
				}
			}
		*/

		// This will be the object inserted in the table's data array
		// var scoreData = {};

		// Add simple attributes
		// scoreData['id'] = score.id || null;
		// scoreData['teamId'] = score.teamId || null;
		// scoreData['tableId'] = score.tableId || null;
		// scoreData['team'] = score.teamId || null;
		// scoreData.team: score.team.name
		// scoreData.country: score.team.country

		// Add scores data
		var scoreValues = [];
		for(var i = 0; i < columns; i++){

			// Get value and add to scoreValues
			var value = null;
			if(score.scores[i])
				value = score.scores[i].value;

			scoreValues.push(value);

			// Generate field key and saves
			// var field = 'score.'+(i+1);
			// score[field] = score.scores.value || null;
		}

		// Compute final score and adds to scoreData
		score['final'] = evalMethod(scoreValues);

		// Add to table data
		// tableRows.push(score)
	});

	// Sort by 'final' field and reverse if needed
	var finalData = _.sortBy(scores, 'final');

	if(table.order == 'asc')
		finalData = finalTable.reverse()

	// Rank Table
	var pos = 0;
	var lastScore = -1;

	_.forEach(finalData, function(row){
		// Keeps the same ranking if scores is the same
		if(lastScore != row.final){
			pos++;
			lastScore = row.final;
		}

		row.rank = pos;
	});

	// Self assign the table
	this.scores = finalData;

	// Return the table
	return this.scores;
}

/*
	Default methods instantiation
*/
var evaluateMethods = {};

// Max method
evaluateMethods.max = function(scores){
	return _.max(scores, function(val) {
		return val*1;
	});
};

// Min method
evaluateMethods.min = function(scores){
	return _.min(scores, function(val) {
		return val*1;
	});
};

// Sum method
evaluateMethods.sum = function(scores){
	return _.reduce(scores, function(sum, num) {
		return sum + num*1;
	});
};

/*
	This will try to find a default method.
	If not succeed, will try to parse as a function.
	If not succeeded, will return null.

	In sum: Will return a function if succeeds, otherwise, 'null'
*/
function getMethodFor(methodRaw){
	// Try to find in defaults
	if(evaluateMethods[methodRaw])
		return evaluateMethods[methodRaw];

	// Else, try to return a new function with it
	try{
		var method = Function('scores', methodRaw);
		method();
		return method;
	}catch(err){
	}
	return null;
}

/*
	Method used to remove fields that are not supposed to
	be there, on create and update.
*/
function removeBadFields(attrs){
	var badList = ['scores', 'table', 'headers'];
	for(var k in badList){
		if(attrs[badList[k]])
			delete attrs[badList[k]];
	}
}

/*
	Tests
*/
// var testCase = {0: 100, 1: 213, '2':'5'};

// var methods = [
// 	'sum',
// 	'min',
// 	'max',
// 	"var finalScore = 0;"+
// 	"for(var k in scores){"+
// 		"finalScore += scores[k]*1;"+
// 	"}"+
// 	"return finalScore;"
// ];

// for(var m in methods)
// 	console.log(getMethodFor(methods[m])(testCase) + ' : '+ methods[m]);
// console.log(evaluateMethodGet('max')
<|endoftext|>


<commit_before>/*

_____                                                   ______           _   _
|  __ \                                                 |  ____|         | | | |
| |  | | ___ _ __ ___   ___   ___ _ __ __ _  ___ _   _  | |__   __ _ _ __| |_| |__
| |  | |/ _ \ '_ ` _ \ / _ \ / __| '__/ _` |/ __| | | | |  __| / _` | '__| __| '_ \
| |__| |  __/ | | | | | (_) | (__| | | (_| | (__| |_| |_| |___| (_| | |  | |_| | | |
|_____/ \___|_| |_| |_|\___/ \___|_|  \__,_|\___|\__, (_)______\__,_|_|   \__|_| |_/
                                                  __/ |
                                                 |___/

"You never change things by fighting the existing reality. To change something
build a new model that makes the existing model obsolete."
Buckminster Fuller, Great San Francisco Architect.

A Roma, <3

*/

/* global alert */

import { Meteor } from 'meteor/meteor';
import { TAPi18n } from 'meteor/tap:i18n';
import { $ } from 'meteor/jquery';
import { Session } from 'meteor/session';
import { SearchSource } from 'meteor/meteorhacks:search-source';
import { Template } from 'meteor/templating';

import { toggleSidebar } from '/imports/ui/modules/menu';
import { globalObj } from '/lib/global';
import { geo } from '/lib/geo';

import '/imports/ui/templates/layout/main.html';
import '/imports/ui/templates/widgets/modal/modal';
import '/imports/ui/templates/widgets/popup/popup';
import '/imports/ui/templates/layout/sidebar/sidebar';
import '/imports/ui/templates/layout/navigation/navigation';
import '/imports/ui/templates/layout/response/verifyEmail/verifyEmail';
import '/imports/ui/templates/layout/touchmenu/touchmenu';
import '/imports/ui/templates/components/decision/editor/editor';

Meteor.startup(() => {
  // Mail server settings
  process.env.MAIL_URL = Meteor.settings.smtpServer;

  // setup language
  Session.set('showLoadingIndicator', true);

  // internationalization library
  TAPi18n.setLanguage(Meteor.settings.public.app.language)
    .done(function () {
      Session.set('showLoadingIndicator', false);
    })
    .fail(function (errorMessage) {
      console.log(errorMessage);
    });

  // scripts
  $.getScript('js/datepicker.js', () => {});

  // time
  Meteor.setInterval(function () {
    Meteor.call('getServerTime', function (error, result) {
      Session.set('time', result);
    });
  }, 1000);

  // search Engine for Tags
  Session.set('createTag', false);
  globalObj.TagSearch = new SearchSource('tags', ['text', 'url'], {
    keepHistory: 1000 * 60 * 5,
    localSearch: true,
  });

  // search Engine for Proposals
  Session.set('createProposal', false);
  globalObj.ProposalSearch = new SearchSource('contracts', ['title', 'description'], {
    keepHistory: 1000 * 60 * 5,
    localSearch: true,
  });

  // geographical Info
  globalObj.geoJSON = geo;
  Session.set('filteredCountries', geo.country);
});

Template.main.onRendered(() => {
  if (document.getElementsByClassName('inhibitor').length > 0) {
    document.getElementsByClassName('inhibitor')[0].addEventListener('touchmove', (e) => { e.preventDefault(); });
  }

  if (!Meteor.Device.isPhone()) {
    Session.set('sidebar', false);
    toggleSidebar(true);
  }
});

Template.main.helpers({
  popupList() {
    return Session.get('popupList');
  },
  showNotice() {
    return Session.get('showNotice');
  },
});

Template.main.events({
  'click .inhibitor'() {
    toggleSidebar();
  },
});
<commit_msg>app begins on mobile mode in small desktop windows<commit_after>/*

_____                                                   ______           _   _
|  __ \                                                 |  ____|         | | | |
| |  | | ___ _ __ ___   ___   ___ _ __ __ _  ___ _   _  | |__   __ _ _ __| |_| |__
| |  | |/ _ \ '_ ` _ \ / _ \ / __| '__/ _` |/ __| | | | |  __| / _` | '__| __| '_ \
| |__| |  __/ | | | | | (_) | (__| | | (_| | (__| |_| |_| |___| (_| | |  | |_| | | |
|_____/ \___|_| |_| |_|\___/ \___|_|  \__,_|\___|\__, (_)______\__,_|_|   \__|_| |_/
                                                  __/ |
                                                 |___/

"You never change things by fighting the existing reality. To change something
build a new model that makes the existing model obsolete."
Buckminster Fuller, Great San Francisco Architect.

A Roma, <3

*/

/* global alert */

import { Meteor } from 'meteor/meteor';
import { TAPi18n } from 'meteor/tap:i18n';
import { $ } from 'meteor/jquery';
import { Session } from 'meteor/session';
import { SearchSource } from 'meteor/meteorhacks:search-source';
import { Template } from 'meteor/templating';

import { toggleSidebar } from '/imports/ui/modules/menu';
import { globalObj } from '/lib/global';
import { geo } from '/lib/geo';
import { gui } from '/lib/const';

import '/imports/ui/templates/layout/main.html';
import '/imports/ui/templates/widgets/modal/modal';
import '/imports/ui/templates/widgets/popup/popup';
import '/imports/ui/templates/layout/sidebar/sidebar';
import '/imports/ui/templates/layout/navigation/navigation';
import '/imports/ui/templates/layout/response/verifyEmail/verifyEmail';
import '/imports/ui/templates/layout/touchmenu/touchmenu';
import '/imports/ui/templates/components/decision/editor/editor';

Meteor.startup(() => {
  // Mail server settings
  process.env.MAIL_URL = Meteor.settings.smtpServer;

  // setup language
  Session.set('showLoadingIndicator', true);

  // internationalization library
  TAPi18n.setLanguage(Meteor.settings.public.app.language)
    .done(function () {
      Session.set('showLoadingIndicator', false);
    })
    .fail(function (errorMessage) {
      console.log(errorMessage);
    });

  // scripts
  $.getScript('js/datepicker.js', () => {});

  // time
  Meteor.setInterval(function () {
    Meteor.call('getServerTime', function (error, result) {
      Session.set('time', result);
    });
  }, 1000);

  // search Engine for Tags
  Session.set('createTag', false);
  globalObj.TagSearch = new SearchSource('tags', ['text', 'url'], {
    keepHistory: 1000 * 60 * 5,
    localSearch: true,
  });

  // search Engine for Proposals
  Session.set('createProposal', false);
  globalObj.ProposalSearch = new SearchSource('contracts', ['title', 'description'], {
    keepHistory: 1000 * 60 * 5,
    localSearch: true,
  });

  // geographical Info
  globalObj.geoJSON = geo;
  Session.set('filteredCountries', geo.country);
});

Template.main.onRendered(() => {
  if (document.getElementsByClassName('inhibitor').length > 0) {
    document.getElementsByClassName('inhibitor')[0].addEventListener('touchmove', (e) => { e.preventDefault(); });
  }

  console.log($(window).width());

  if (!Meteor.Device.isPhone() && $(window).width() < gui.MOBILE_MAX_WIDTH) {
    $('.navbar').css('left', 0);
    Session.set('miniWindow', true);
    Session.set('sidebar', true);
    toggleSidebar();
  } else if (!Meteor.Device.isPhone()) {
    Session.set('sidebar', false);
    toggleSidebar();
  }
});

Template.main.helpers({
  popupList() {
    return Session.get('popupList');
  },
  showNotice() {
    return Session.get('showNotice');
  },
});

Template.main.events({
  'click .inhibitor'() {
    toggleSidebar();
  },
});
<|endoftext|>


<commit_before>'use strict';

var feedbackUrl = process.env.FEEDBACK_URL;
var gateHost = process.env.API_HOST || 'http://localhost:8084';
var bakeryDetailUrl =
  process.env.BAKERY_DETAIL_URL || gateHost + '/bakery/logs/{{context.region}}/{{context.status.resourceId}}';
var authEndpoint = process.env.AUTH_ENDPOINT || gateHost + '/auth/user';
var authEnabled = process.env.AUTH_ENABLED === 'false' ? false : true;
var netflixMode = process.env.NETFLIX_MODE === 'true' ? true : false;
var chaosEnabled = netflixMode || process.env.CHAOS_ENABLED === 'true' ? true : false;
var fiatEnabled = process.env.FIAT_ENABLED === 'true' ? true : false;
var entityTagsEnabled = process.env.ENTITY_TAGS_ENABLED === 'true' ? true : false;
var debugEnabled = process.env.DEBUG_ENABLED === 'false' ? false : true;
var canaryEnabled = process.env.CANARY_ENABLED === 'true';
var infrastructureEnabled = process.env.INFRA_ENABLED === 'true' ? true : false;
var dryRunEnabled = process.env.DRYRUN_ENABLED === 'true' ? true : false;
var reduxLoggerEnabled = process.env.REDUX_LOGGER === 'true';
var defaultMetricStore = process.env.METRIC_STORE || 'atlas';
var canaryStagesEnabled = process.env.CANARY_STAGES_ENABLED === 'true';
var templatesEnabled = process.env.TEMPLATES_ENABLED === 'true';
var atlasWebComponentsUrl = process.env.ATLAS_WEB_COMPONENTS_URL;
var canaryAccount = process.env.CANARY_ACCOUNT || '';
var canaryFeatureDisabled = process.env.CANARY_FEATURE_ENABLED !== 'true';
var useClassicFirewallLabels = process.env.USE_CLASSIC_FIREWALL_LABELS === 'true';

window.spinnakerSettings = {
  checkForUpdates: true,
  debugEnabled: debugEnabled,
  defaultProviders: ['aws', 'gce', 'azure', 'cf', 'kubernetes', 'dcos', 'openstack', 'oraclebmcs', 'ecs'],
  feedbackUrl: feedbackUrl,
  gateUrl: gateHost,
  bakeryDetailUrl: bakeryDetailUrl,
  authEndpoint: authEndpoint,
  pollSchedule: 30000,
  defaultTimeZone: process.env.TIMEZONE || 'America/Los_Angeles', // see http://momentjs.com/timezone/docs/#/data-utilities/
  defaultCategory: 'serverGroup',
  defaultInstancePort: 80,
  providers: {
    azure: {
      defaults: {
        account: 'azure-test',
        region: 'westus',
      },
    },
    aws: {
      defaults: {
        account: 'test',
        region: 'us-east-1',
        iamRole: 'BaseIAMRole',
      },
      defaultSecurityGroups: [],
      loadBalancers: {
        // if true, VPC load balancers will be created as internal load balancers if the selected subnet has a purpose
        // tag that starts with "internal"
        inferInternalFlagFromSubnet: false,
      },
      useAmiBlockDeviceMappings: false,
    },
    ecs: {
      defaults: {
        account: 'test',
        region: 'us-east-1',
        iamRole: 'BaseIAMRole',
      },
      defaultSecurityGroups: [],
    },
    gce: {
      defaults: {
        account: 'my-google-account',
        instanceTypeStorage: {
          count: 1,
          defaultSettings: {
            disks: [
              {
                type: 'pd-ssd',
                sizeGb: 10,
              },
            ],
          },
          localSSDSupported: false,
          size: 10,
        },
        region: 'us-central1',
        zone: 'us-central1-f',
      },
      associatePublicIpAddress: true,
    },
    titus: {
      defaults: {
        account: 'titustestvpc',
        region: 'us-east-1',
        iamProfile: '{{application}}InstanceProfile',
      },
    },
    oraclebmcs: {
      defaults: {
        account: 'DEFAULT',
        region: 'us-phoenix-1',
        bakeryRegions: ['us-phoenix-1'],
      },
    },
    openstack: {
      defaults: {
        account: 'test',
        region: 'us-west-1',
      },
    },
    kubernetes: {
      defaults: {
        account: 'my-kubernetes-account',
        namespace: 'default',
        proxy: 'localhost:8001',
        internalDNSNameTemplate: '{{name}}.{{namespace}}.svc.cluster.local',
        instanceLinkTemplate: '{{host}}/api/v1/proxy/namespaces/{{namespace}}/pods/{{name}}',
        apiPrefix: 'api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#',
      },
    },
    dcos: {
      defaults: {
        account: 'my-dcos-account',
      },
    },
    appengine: {
      defaults: {
        account: 'my-appengine-account',
        containerImageUrlDeployments: false,
      },
    },
  },
  whatsNew: {
    gistId: '32526cd608db3d811b38',
    fileName: 'news.md',
  },
  notifications: {
    email: {
      enabled: true,
    },
    hipchat: {
      enabled: true,
      botName: 'Skynet T-800',
    },
    sms: {
      enabled: true,
    },
    slack: {
      enabled: true,
      botName: 'spinnakerbot',
    },
  },
  pagerDuty: {
    required: false,
  },
  authEnabled: authEnabled,
  authTtl: 600000,
  gitSources: ['stash', 'github', 'bitbucket', 'gitlab'],
  pubsubProviders: ['google'], // TODO(joonlim): Add amazon once it is confirmed that amazon pub/sub works.
  triggerTypes: ['git', 'pipeline', 'docker', 'cron', 'jenkins', 'travis', 'pubsub'],
  searchVersion: 1,
  useClassicFirewallLabels: useClassicFirewallLabels,
  canary: {
    reduxLogger: reduxLoggerEnabled,
    metricsAccountName: canaryAccount,
    storageAccountName: canaryAccount,
    defaultJudge: 'NetflixACAJudge-v1.0',
    metricStore: defaultMetricStore,
    stagesEnabled: canaryStagesEnabled,
    atlasWebComponentsUrl: atlasWebComponentsUrl,
    templatesEnabled: templatesEnabled,
    showAllConfigs: true,
    featureDisabled: canaryFeatureDisabled,
  },
  feature: {
    artifacts: false,
    canary: canaryEnabled,
    chaosMonkey: chaosEnabled,
    clusterDiff: false,
    dryRunEnabled: dryRunEnabled,
    entityTags: entityTagsEnabled,
    fastProperty: true,
    fiatEnabled: fiatEnabled,
    // whether stages affecting infrastructure (like "Create Load Balancer") should be enabled or not
    infrastructureStages: infrastructureEnabled,
    jobs: false,
    netflixMode: netflixMode,
    notifications: false,
    pagerDuty: false,
    pipelineTemplates: false,
    pipelines: true,
    roscoMode: false,
    snapshots: false,
    travis: false,
    versionedProviders: true,
    vpcMigrator: true,
  },
};
<commit_msg>chore(build): Add ARTIFACTS_ENABLED env variable. (#5381)<commit_after>'use strict';

var feedbackUrl = process.env.FEEDBACK_URL;
var gateHost = process.env.API_HOST || 'http://localhost:8084';
var bakeryDetailUrl =
  process.env.BAKERY_DETAIL_URL || gateHost + '/bakery/logs/{{context.region}}/{{context.status.resourceId}}';
var authEndpoint = process.env.AUTH_ENDPOINT || gateHost + '/auth/user';
var authEnabled = process.env.AUTH_ENABLED === 'false' ? false : true;
var netflixMode = process.env.NETFLIX_MODE === 'true' ? true : false;
var chaosEnabled = netflixMode || process.env.CHAOS_ENABLED === 'true' ? true : false;
var fiatEnabled = process.env.FIAT_ENABLED === 'true' ? true : false;
var entityTagsEnabled = process.env.ENTITY_TAGS_ENABLED === 'true' ? true : false;
var debugEnabled = process.env.DEBUG_ENABLED === 'false' ? false : true;
var canaryEnabled = process.env.CANARY_ENABLED === 'true';
var infrastructureEnabled = process.env.INFRA_ENABLED === 'true' ? true : false;
var dryRunEnabled = process.env.DRYRUN_ENABLED === 'true' ? true : false;
var reduxLoggerEnabled = process.env.REDUX_LOGGER === 'true';
var defaultMetricStore = process.env.METRIC_STORE || 'atlas';
var canaryStagesEnabled = process.env.CANARY_STAGES_ENABLED === 'true';
var templatesEnabled = process.env.TEMPLATES_ENABLED === 'true';
var atlasWebComponentsUrl = process.env.ATLAS_WEB_COMPONENTS_URL;
var canaryAccount = process.env.CANARY_ACCOUNT || '';
var canaryFeatureDisabled = process.env.CANARY_FEATURE_ENABLED !== 'true';
var useClassicFirewallLabels = process.env.USE_CLASSIC_FIREWALL_LABELS === 'true';
var artifactsEnabled = process.env.ARTIFACTS_ENABLED === 'true';

window.spinnakerSettings = {
  checkForUpdates: true,
  debugEnabled: debugEnabled,
  defaultProviders: ['aws', 'gce', 'azure', 'cf', 'kubernetes', 'dcos', 'openstack', 'oraclebmcs', 'ecs'],
  feedbackUrl: feedbackUrl,
  gateUrl: gateHost,
  bakeryDetailUrl: bakeryDetailUrl,
  authEndpoint: authEndpoint,
  pollSchedule: 30000,
  defaultTimeZone: process.env.TIMEZONE || 'America/Los_Angeles', // see http://momentjs.com/timezone/docs/#/data-utilities/
  defaultCategory: 'serverGroup',
  defaultInstancePort: 80,
  providers: {
    azure: {
      defaults: {
        account: 'azure-test',
        region: 'westus',
      },
    },
    aws: {
      defaults: {
        account: 'test',
        region: 'us-east-1',
        iamRole: 'BaseIAMRole',
      },
      defaultSecurityGroups: [],
      loadBalancers: {
        // if true, VPC load balancers will be created as internal load balancers if the selected subnet has a purpose
        // tag that starts with "internal"
        inferInternalFlagFromSubnet: false,
      },
      useAmiBlockDeviceMappings: false,
    },
    ecs: {
      defaults: {
        account: 'test',
        region: 'us-east-1',
        iamRole: 'BaseIAMRole',
      },
      defaultSecurityGroups: [],
    },
    gce: {
      defaults: {
        account: 'my-google-account',
        instanceTypeStorage: {
          count: 1,
          defaultSettings: {
            disks: [
              {
                type: 'pd-ssd',
                sizeGb: 10,
              },
            ],
          },
          localSSDSupported: false,
          size: 10,
        },
        region: 'us-central1',
        zone: 'us-central1-f',
      },
      associatePublicIpAddress: true,
    },
    titus: {
      defaults: {
        account: 'titustestvpc',
        region: 'us-east-1',
        iamProfile: '{{application}}InstanceProfile',
      },
    },
    oraclebmcs: {
      defaults: {
        account: 'DEFAULT',
        region: 'us-phoenix-1',
        bakeryRegions: ['us-phoenix-1'],
      },
    },
    openstack: {
      defaults: {
        account: 'test',
        region: 'us-west-1',
      },
    },
    kubernetes: {
      defaults: {
        account: 'my-kubernetes-account',
        namespace: 'default',
        proxy: 'localhost:8001',
        internalDNSNameTemplate: '{{name}}.{{namespace}}.svc.cluster.local',
        instanceLinkTemplate: '{{host}}/api/v1/proxy/namespaces/{{namespace}}/pods/{{name}}',
        apiPrefix: 'api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#',
      },
    },
    dcos: {
      defaults: {
        account: 'my-dcos-account',
      },
    },
    appengine: {
      defaults: {
        account: 'my-appengine-account',
        containerImageUrlDeployments: false,
      },
    },
  },
  whatsNew: {
    gistId: '32526cd608db3d811b38',
    fileName: 'news.md',
  },
  notifications: {
    email: {
      enabled: true,
    },
    hipchat: {
      enabled: true,
      botName: 'Skynet T-800',
    },
    sms: {
      enabled: true,
    },
    slack: {
      enabled: true,
      botName: 'spinnakerbot',
    },
  },
  pagerDuty: {
    required: false,
  },
  authEnabled: authEnabled,
  authTtl: 600000,
  gitSources: ['stash', 'github', 'bitbucket', 'gitlab'],
  pubsubProviders: ['google'], // TODO(joonlim): Add amazon once it is confirmed that amazon pub/sub works.
  triggerTypes: ['git', 'pipeline', 'docker', 'cron', 'jenkins', 'travis', 'pubsub'],
  searchVersion: 1,
  useClassicFirewallLabels: useClassicFirewallLabels,
  canary: {
    reduxLogger: reduxLoggerEnabled,
    metricsAccountName: canaryAccount,
    storageAccountName: canaryAccount,
    defaultJudge: 'NetflixACAJudge-v1.0',
    metricStore: defaultMetricStore,
    stagesEnabled: canaryStagesEnabled,
    atlasWebComponentsUrl: atlasWebComponentsUrl,
    templatesEnabled: templatesEnabled,
    showAllConfigs: true,
    featureDisabled: canaryFeatureDisabled,
  },
  feature: {
    artifacts: artifactsEnabled,
    canary: canaryEnabled,
    chaosMonkey: chaosEnabled,
    clusterDiff: false,
    dryRunEnabled: dryRunEnabled,
    entityTags: entityTagsEnabled,
    fastProperty: true,
    fiatEnabled: fiatEnabled,
    // whether stages affecting infrastructure (like "Create Load Balancer") should be enabled or not
    infrastructureStages: infrastructureEnabled,
    jobs: false,
    netflixMode: netflixMode,
    notifications: false,
    pagerDuty: false,
    pipelineTemplates: false,
    pipelines: true,
    roscoMode: false,
    snapshots: false,
    travis: false,
    versionedProviders: true,
    vpcMigrator: true,
  },
};
<|endoftext|>


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

foam.CLASS({
  package: 'foam.dao',
  name: 'NullDAO',
  extends: 'foam.dao.AbstractDAO',

  documentation: 'A Null pattern (do-nothing) DAO implementation.',

  requires: [
    'foam.dao.ExternalException',
    'foam.dao.ObjectNotFoundException'
  ],

  methods: [
    function put(obj) {
      return Promise.reject(this.ExternalException.create({
        message: 'NullDAO: Cannot handle put()'
      }));
    },

    function remove(obj) {
      return Promise.resolve();
    },

    function find(id) {
      return Promise.resolve(null);
    },

    function select(sink) {
      sink = sink || foam.dao.ArraySink.create();
      sink.eof();
      return Promise.resolve(sink);
    },

    function removeAll() {
      return Promise.resolve();
    }
  ]
});
<commit_msg>Update NullDAO so it can be used as a pure proxy event system.<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.dao',
  name: 'NullDAO',
  extends: 'foam.dao.AbstractDAO',

  documentation: 'A Null pattern (do-nothing) DAO implementation.',

  requires: [
    'foam.dao.ExternalException',
    'foam.dao.ObjectNotFoundException'
  ],

  methods: [
    function put(obj) {
      this.pub('on', 'pub', obj);
      return Promise.resolve(obj);
    },

    function remove(obj) {
      this.pub('on', 'remove', obj);
      return Promise.resolve();
    },

    function find(id) {
      return Promise.resolve(null);
    },

    function select(sink) {
      sink = sink || foam.dao.ArraySink.create();
      sink.eof();
      return Promise.resolve(sink);
    },

    function removeAll() {
      return Promise.resolve();
    }
  ]
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import classnames from 'classnames';
import { deSig, uxToHex } from '/lib/util';
import { Route, Link } from "react-router-dom";

import { ChatTabBar } from '/components/lib/chat-tabbar';
import SidebarSwitcher from './lib/icons/icon-sidebar-switch';

export class SettingsScreen extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoading: false,
      title: "",
      description: "",
      color: ""
    };

    this.renderDelete = this.renderDelete.bind(this);
    this.changeTitle = this.changeTitle.bind(this);
    this.changeDescription = this.changeDescription.bind(this);
    this.changeColor = this.changeColor.bind(this);
  }

  componentDidMount() {
    if ((this.props.association) && (this.props.association.metadata)) {
      this.setState({
        title: this.props.association.metadata.title,
        description: this.props.association.metadata.description,
        color: uxToHex(this.props.association.metadata.color)
      });
    }
  }

  componentDidUpdate(prevProps, prevState) {
    const { props, state } = this;
    if (!!state.isLoading && !(props.station in props.inbox)) {
      this.setState({
        isLoading: false
      }, () => {
        props.api.setSpinner(false);
        props.history.push('/~chat');
      });
    }

    if ((this.state.title === "") && (prevProps !== this.props)) {
      if ((props.association) && (props.association.metadata))
      this.setState({
        title: props.association.metadata.title,
        description: props.association.metadata.description,
        color: uxToHex(props.association.metadata.color)});
    }
  }

  changeTitle() {
    this.setState({title: event.target.value})
  }

  changeDescription() {
    this.setState({description: event.target.value});
  }

  changeColor() {
    this.setState({color: event.target.value});
  }

  deleteChat() {
    const { props, state } = this;

    props.api.chatView.delete(props.station);
    props.api.setSpinner(true);

    this.setState({
      isLoading: true
    });
  }

  renderDelete() {
    const { props, state } = this;

    let chatOwner = (deSig(props.match.params.ship) === window.ship);

    let deleteButtonClasses = (chatOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--grey3 grey3 bg-gray0-d c-default';
    let leaveButtonClasses = (!chatOwner) ? "pointer" : "c-default";

    return (

Leave Chat

Remove this chat from your chat list. You will need to request for access again.

        Leave this chat

Delete Chat

Permenantly delete this chat. (All current members will no longer see this chat)

          Delete this chat

    );
  }

  renderMetadataSettings() {
    const { props, state } = this;

    let chatOwner = (deSig(props.match.params.ship) === window.ship);

    let association = ((props.association) && (props.association.metadata))
      ? props.association : {};

    return(

Rename

Change the name of this chat

          <input
            className="f8 ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 db w-100 flex-auto mr3"
            value={this.state.title}
            disabled={!chatOwner}
            onChange={this.changeTitle}
          />
           {
              if (chatOwner) {
                props.api.setSpinner(true);
                props.api.metadataAdd(
                  association['app-path'],
                  association['group-path'],
                  this.state.title,
                  association.metadata.description,
                  association.metadata['date-created'],
                  uxToHex(association.metadata.color)
                ).then(() => {
                  this.refs.rename.innerText = "Saved";
                  props.api.setSpinner(false);
                })
              }
            }}>
            Save

Change description

Change the description of this chat

            <input
              className="f8 ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 db w-100 flex-auto mr3"
              value={this.state.description}
              disabled={!chatOwner}
              onChange={this.changeDescription}
            />
             {
                if (chatOwner) {
                  props.api.setSpinner(true);
                  props.api.metadataAdd(
                    association['app-path'],
                    association['group-path'],
                    association.metadata.title,
                    this.state.description,
                    association.metadata['date-created'],
                    uxToHex(association.metadata.color)
                  ).then(() => {
                    this.refs.description.innerText = "Saved";
                    props.api.setSpinner(false);
                  })
                }
              }}>
              Save

Change color

Give this chat a color when viewing group channels

            <input
              className="f8 ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 db w-100 flex-auto mr3"
              value={this.state.color}
              disabled={!chatOwner}
              onChange={this.changeColor}
            />
             {
                if ((chatOwner) && (this.state.color.match(/[0-9A-F]{6}/i))) {
                  props.api.setSpinner(true);
                  props.api.metadataAdd(
                    association['app-path'],
                    association['group-path'],
                    association.metadata.title,
                    association.metadata.description,
                    association.metadata['date-created'],
                    this.state.color
                  ).then(() => {
                    this.refs.color.innerText = "Saved";
                    props.api.setSpinner(false);
                  })
                }
              }}>
              Save

    )
  }

  render() {
    const { props, state } = this;
    const isinPopout = this.props.popout ? "popout/" : "";

    let writeGroup = Array.from(props.group.values());

    if (!!state.isLoading) {
      let text = "Deleting...";
      if (deSig(props.match.params.ship) !== window.ship) {
        text = "Leaving...";
      }

      return (

            <Link to="/~chat/">{"⟵ All Chats"}</Link>

            <SidebarSwitcher
              sidebarShown={this.props.sidebarShown}
              popout={this.props.popout}
            />
            <Link to={`/~chat/` + isinPopout + `room` + props.station}
            className="pt2 white-d">

                {props.station.substr(1)}

            </Link>
            <ChatTabBar
              {...props}
              station={props.station}
              numPeers={writeGroup.length}
            />

{text}

      );
    }

    return (

          <Link to="/~chat/">{"⟵ All Chats"}</Link>

          <SidebarSwitcher
            sidebarShown={this.props.sidebarShown}
            popout={this.props.popout}
          />
          <Link to={`/~chat/` + isinPopout + `room` + props.station}
          className="pt2">

              {props.station.substr(1)}

          </Link>
          <ChatTabBar
            {...props}
            station={props.station}
            numPeers={writeGroup.length}
            isOwner={deSig(props.match.params.ship) === window.ship}
            popout={this.props.popout}
          />

Chat Settings

Share

Share a shortcode to join this chat

              <input
                className="f8 mono ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 db w-100 flex-auto mr3"
                disabled={true}
                value={props.station.substr(1)}
              />
               {
                  navigator.clipboard.writeText(props.station.substr(1));
                  this.refs.copy.innerText = "Copied";
                }}>
                Copy

          {this.renderDelete()}
          {this.renderMetadataSettings()}

    );
  }
}
<commit_msg>chat: settings inputs add borders on focus<commit_after>import React, { Component } from 'react';
import classnames from 'classnames';
import { deSig, uxToHex } from '/lib/util';
import { Route, Link } from "react-router-dom";

import { ChatTabBar } from '/components/lib/chat-tabbar';
import SidebarSwitcher from './lib/icons/icon-sidebar-switch';

export class SettingsScreen extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoading: false,
      title: "",
      description: "",
      color: ""
    };

    this.renderDelete = this.renderDelete.bind(this);
    this.changeTitle = this.changeTitle.bind(this);
    this.changeDescription = this.changeDescription.bind(this);
    this.changeColor = this.changeColor.bind(this);
  }

  componentDidMount() {
    if ((this.props.association) && (this.props.association.metadata)) {
      this.setState({
        title: this.props.association.metadata.title,
        description: this.props.association.metadata.description,
        color: uxToHex(this.props.association.metadata.color)
      });
    }
  }

  componentDidUpdate(prevProps, prevState) {
    const { props, state } = this;
    if (!!state.isLoading && !(props.station in props.inbox)) {
      this.setState({
        isLoading: false
      }, () => {
        props.api.setSpinner(false);
        props.history.push('/~chat');
      });
    }

    if ((this.state.title === "") && (prevProps !== this.props)) {
      if ((props.association) && (props.association.metadata))
      this.setState({
        title: props.association.metadata.title,
        description: props.association.metadata.description,
        color: uxToHex(props.association.metadata.color)});
    }
  }

  changeTitle() {
    this.setState({title: event.target.value})
  }

  changeDescription() {
    this.setState({description: event.target.value});
  }

  changeColor() {
    this.setState({color: event.target.value});
  }

  deleteChat() {
    const { props, state } = this;

    props.api.chatView.delete(props.station);
    props.api.setSpinner(true);

    this.setState({
      isLoading: true
    });
  }

  renderDelete() {
    const { props, state } = this;

    let chatOwner = (deSig(props.match.params.ship) === window.ship);

    let deleteButtonClasses = (chatOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--grey3 grey3 bg-gray0-d c-default';
    let leaveButtonClasses = (!chatOwner) ? "pointer" : "c-default";

    return (

Leave Chat

Remove this chat from your chat list. You will need to request for access again.

        Leave this chat

Delete Chat

Permenantly delete this chat. (All current members will no longer see this chat)

          Delete this chat

    );
  }

  renderMetadataSettings() {
    const { props, state } = this;

    let chatOwner = (deSig(props.match.params.ship) === window.ship);

    let association = ((props.association) && (props.association.metadata))
      ? props.association : {};

    return(

Rename

Change the name of this chat

          <input
            className={"f8 ba b--gray3 b--gray2-d bg-gray0-d white-d " +
            "focus-b--black focus-b--white-d pa3 db w-100 flex-auto mr3"}
            value={this.state.title}
            disabled={!chatOwner}
            onChange={this.changeTitle}
          />
           {
              if (chatOwner) {
                props.api.setSpinner(true);
                props.api.metadataAdd(
                  association['app-path'],
                  association['group-path'],
                  this.state.title,
                  association.metadata.description,
                  association.metadata['date-created'],
                  uxToHex(association.metadata.color)
                ).then(() => {
                  this.refs.rename.innerText = "Saved";
                  props.api.setSpinner(false);
                })
              }
            }}>
            Save

Change description

Change the description of this chat

            <input
              className={"f8 ba b--gray3 b--gray2-d bg-gray0-d white-d " +
                "focus-b--black focus-b--white-d pa3 db w-100 flex-auto mr3"}
              value={this.state.description}
              disabled={!chatOwner}
              onChange={this.changeDescription}
            />
             {
                if (chatOwner) {
                  props.api.setSpinner(true);
                  props.api.metadataAdd(
                    association['app-path'],
                    association['group-path'],
                    association.metadata.title,
                    this.state.description,
                    association.metadata['date-created'],
                    uxToHex(association.metadata.color)
                  ).then(() => {
                    this.refs.description.innerText = "Saved";
                    props.api.setSpinner(false);
                  })
                }
              }}>
              Save

Change color

Give this chat a color when viewing group channels

            <input
              className={"f8 ba b--gray3 b--gray2-d bg-gray0-d white-d " +
                "focus-b--black focus-b--white-d pa3 db w-100 flex-auto mr3"}
              value={this.state.color}
              disabled={!chatOwner}
              onChange={this.changeColor}
            />
             {
                if ((chatOwner) && (this.state.color.match(/[0-9A-F]{6}/i))) {
                  props.api.setSpinner(true);
                  props.api.metadataAdd(
                    association['app-path'],
                    association['group-path'],
                    association.metadata.title,
                    association.metadata.description,
                    association.metadata['date-created'],
                    this.state.color
                  ).then(() => {
                    this.refs.color.innerText = "Saved";
                    props.api.setSpinner(false);
                  })
                }
              }}>
              Save

    )
  }

  render() {
    const { props, state } = this;
    const isinPopout = this.props.popout ? "popout/" : "";

    let writeGroup = Array.from(props.group.values());

    if (!!state.isLoading) {
      let text = "Deleting...";
      if (deSig(props.match.params.ship) !== window.ship) {
        text = "Leaving...";
      }

      return (

            <Link to="/~chat/">{"⟵ All Chats"}</Link>

            <SidebarSwitcher
              sidebarShown={this.props.sidebarShown}
              popout={this.props.popout}
            />
            <Link to={`/~chat/` + isinPopout + `room` + props.station}
            className="pt2 white-d">

                {props.station.substr(1)}

            </Link>
            <ChatTabBar
              {...props}
              station={props.station}
              numPeers={writeGroup.length}
            />

{text}

      );
    }

    return (

          <Link to="/~chat/">{"⟵ All Chats"}</Link>

          <SidebarSwitcher
            sidebarShown={this.props.sidebarShown}
            popout={this.props.popout}
          />
          <Link to={`/~chat/` + isinPopout + `room` + props.station}
          className="pt2">

              {props.station.substr(1)}

          </Link>
          <ChatTabBar
            {...props}
            station={props.station}
            numPeers={writeGroup.length}
            isOwner={deSig(props.match.params.ship) === window.ship}
            popout={this.props.popout}
          />

Chat Settings

Share

Share a shortcode to join this chat

              <input
                className="f8 mono ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 db w-100 flex-auto mr3"
                disabled={true}
                value={props.station.substr(1)}
              />
               {
                  navigator.clipboard.writeText(props.station.substr(1));
                  this.refs.copy.innerText = "Copied";
                }}>
                Copy

          {this.renderDelete()}
          {this.renderMetadataSettings()}

    );
  }
}
<|endoftext|>


<commit_before>App = {
  web3Provider: null,
  contracts: {},

  init: function() {
    return App.initWeb3();
  },

  initWeb3: function() {
    // Initialize web3 and set the provider to the testRPC.
    if (typeof web3 !== 'undefined') {
      App.web3Provider = web3.currentProvider;
      web3 = new Web3(web3.currentProvider);
    } else {
      // set the provider you want from Web3.providers
      App.web3Provider = new web3.providers.HttpProvider('http://localhost:8545');
      web3 = new Web3(App.web3Provider);
    }

    return App.initContract();
  },

  initContract: function() {
    $.getJSON('GraivyApp.json', function(data) {
      // Get the necessary contract artifact file and instantiate it with truffle-contract.
      var GraivyAppArtifact = data;
      App.contracts.GraivyApp = TruffleContract(GraivyAppArtifact);

      // Set the provider for our contract.
      App.contracts.GraivyApp.setProvider(App.web3Provider);

      // Use our contract to retieve and mark the adopted pets.
      return App.getUserCount(), App.checkUser();
    });

    return App.bindEvents();
  },

  bindEvents: function() {
    $(document).on('click', '#isUser', App.handleUserCheck);
    $(document).on('click', '#insertUser', App.handleInsertUser);
    $(document).on('click', '#deleteUser', App.handleDeleteUser);
    $(document).on('click', '#getUserQualifications', App.handleGetUserQualifications);
    $(document).on('click', '#getUserPermissions', App.handleGetUserPermissions);
    $(document).on('click', '#updateUserQualifications', App.handleUpdateUserQualifications);
    $(document).on('click', '#updateUserPermissions', App.handleUpdateUserPermissions);
  },

  handleInsertUser: function() {
    event.preventDefault();

    console.log('Creating User');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.insertUser({from: account});
      }).then(function(result) {
        alert('User Created!');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleDeleteUser: function() {
    event.preventDefault();

    console.log('Deleting User... ');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.deleteUser(account, {from: account});
      }).then(function(result) {
        alert('User Deleted!');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleGetUserQualifications: function() {
    event.preventDefault();

    var userAddress = $('#GetUserQualificationsAddy').val();

    console.log('Getting qualifications for User ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.getUserQualifications(userAddress);
      }).then(function(result) {
        console.log(result);
        //qualifications = result.c;
        //rewardAvailable = result.c[1];
        //index = result.c[2];

        $('#ReturnUserQualifications').text(result);
        //$('#GetUserRewardAvailable').text(rewardAvailable);
        //$('#GetUserIndex').text(index);
        //$('#GetUserAddress').text(account);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleGetUserPermissions: function() {
    event.preventDefault();

    var userAddress = $('#GetUserPermissionsAddy').val();

    console.log('Getting permissions for User ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.getUserPermissions(userAddress);
      }).then(function(result) {
        console.log(result);
        //qualifications = result.c;
        //rewardAvailable = result.c[1];
        //index = result.c[2];

        $('#ReturnUserPermissions').text(result);
        //$('#GetUserRewardAvailable').text(rewardAvailable);
        //$('#GetUserIndex').text(index);
        //$('#GetUserAddress').text(account);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleUpdateUserQualifications: function() {
    event.preventDefault();

    var qualifications = parseInt($('#UpdateQualificationsValue').val());
    var userAddress = $('#UpdateQualificationsAddress').val();

    console.log('Updating Qualifications for ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.updateUserQualifications(userAddress, qualifications);
      }).then(function(result) {
        alert('User Qualifications updated');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleUpdateUserPermissions: function() {
    event.preventDefault();

    var permissions = parseInt($('#UpdatePermissionsValue').val());
    var userAddress = $('#UpdatePermissionsAddress').val();

    console.log('Updating Permissions');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.updateUserPermissions(userAddress, permissions);
      }).then(function(result) {
        alert('User Permissions updated');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleCheckUser: function() {
    event.preventDefault();

    var userAddress = $('#UpdatePermissionsAddress').val();

    console.log('Checking User Status for ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.isUser(userAddress);
      }).then(function(result) {
        alert(userAddress + ' is a registered User!');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  getUserCount: function(adopters) {
    console.log('Getting user count...');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.getUserCount();
      }).then(function(result) {
        count = result.c[0];

        $('#GVYUserCount').text(count);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  checkUser: function(adopters, account) {
    console.log('Checking if user...');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.isUser(account);
      }).then(function(result) {
        if (result == true) {
          $('#GVYUserCheck').text('Welcome back, you are logged in.');
        }
        else $('#GVYUserCheck').text('Please create a user account and login!');
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  }

};

$(function() {
  $(window).load(function() {
    App.init();
  });
});
<commit_msg>change isUser to authenticateUser<commit_after>App = {
  web3Provider: null,
  contracts: {},

  init: function() {
    return App.initWeb3();
  },

  initWeb3: function() {
    // Initialize web3 and set the provider to the testRPC.
    if (typeof web3 !== 'undefined') {
      App.web3Provider = web3.currentProvider;
      web3 = new Web3(web3.currentProvider);
    } else {
      // set the provider you want from Web3.providers
      App.web3Provider = new web3.providers.HttpProvider('http://localhost:8545');
      web3 = new Web3(App.web3Provider);
    }

    return App.initContract();
  },

  initContract: function() {
    $.getJSON('GraivyApp.json', function(data) {
      // Get the necessary contract artifact file and instantiate it with truffle-contract.
      var GraivyAppArtifact = data;
      App.contracts.GraivyApp = TruffleContract(GraivyAppArtifact);

      // Set the provider for our contract.
      App.contracts.GraivyApp.setProvider(App.web3Provider);

      // Use our contract to retieve and mark the adopted pets.
      return App.getUserCount(), App.checkUser();
    });

    return App.bindEvents();
  },

  bindEvents: function() {
    $(document).on('click', '#isUser', App.handleUserCheck);
    $(document).on('click', '#insertUser', App.handleInsertUser);
    $(document).on('click', '#deleteUser', App.handleDeleteUser);
    $(document).on('click', '#getUserQualifications', App.handleGetUserQualifications);
    $(document).on('click', '#getUserPermissions', App.handleGetUserPermissions);
    $(document).on('click', '#updateUserQualifications', App.handleUpdateUserQualifications);
    $(document).on('click', '#updateUserPermissions', App.handleUpdateUserPermissions);
  },

  handleInsertUser: function() {
    event.preventDefault();

    console.log('Creating User');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.insertUser({from: account});
      }).then(function(result) {
        alert('User Created!');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleDeleteUser: function() {
    event.preventDefault();

    console.log('Deleting User... ');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.deleteUser(account, {from: account});
      }).then(function(result) {
        alert('User Deleted!');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleGetUserQualifications: function() {
    event.preventDefault();

    var userAddress = $('#GetUserQualificationsAddy').val();

    console.log('Getting qualifications for User ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.getUserQualifications(userAddress);
      }).then(function(result) {
        console.log(result);
        //qualifications = result.c;
        //rewardAvailable = result.c[1];
        //index = result.c[2];

        $('#ReturnUserQualifications').text(result);
        //$('#GetUserRewardAvailable').text(rewardAvailable);
        //$('#GetUserIndex').text(index);
        //$('#GetUserAddress').text(account);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleGetUserPermissions: function() {
    event.preventDefault();

    var userAddress = $('#GetUserPermissionsAddy').val();

    console.log('Getting permissions for User ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.getUserPermissions(userAddress);
      }).then(function(result) {
        console.log(result);
        //qualifications = result.c;
        //rewardAvailable = result.c[1];
        //index = result.c[2];

        $('#ReturnUserPermissions').text(result);
        //$('#GetUserRewardAvailable').text(rewardAvailable);
        //$('#GetUserIndex').text(index);
        //$('#GetUserAddress').text(account);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleUpdateUserQualifications: function() {
    event.preventDefault();

    var qualifications = parseInt($('#UpdateQualificationsValue').val());
    var userAddress = $('#UpdateQualificationsAddress').val();

    console.log('Updating Qualifications for ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.updateUserQualifications(userAddress, qualifications);
      }).then(function(result) {
        alert('User Qualifications updated');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleUpdateUserPermissions: function() {
    event.preventDefault();

    var permissions = parseInt($('#UpdatePermissionsValue').val());
    var userAddress = $('#UpdatePermissionsAddress').val();

    console.log('Updating Permissions');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.updateUserPermissions(userAddress, permissions);
      }).then(function(result) {
        alert('User Permissions updated');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  handleCheckUser: function() {
    event.preventDefault();

    var userAddress = $('#UpdatePermissionsAddress').val();

    console.log('Checking User Status for ' + userAddress);

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.authenticateUser(userAddress);
      }).then(function(result) {
        alert(userAddress + ' is a registered User!');
        return App.getUserCount();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  getUserCount: function(adopters) {
    console.log('Getting user count...');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.getUserCount();
      }).then(function(result) {
        count = result.c[0];

        $('#GVYUserCount').text(count);
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  },

  checkUser: function(adopters, account) {
    console.log('Checking if user...');

    var graivyAppInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.GraivyApp.deployed().then(function(instance) {
        graivyAppInstance = instance;

        return graivyAppInstance.isUser(account);
      }).then(function(result) {
        if (result == true) {
          $('#GVYUserCheck').text('Welcome back, you are logged in.');
        }
        else $('#GVYUserCheck').text('Please create a user account and login!');
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  }

};

$(function() {
  $(window).load(function() {
    App.init();
  });
});
<|endoftext|>


<commit_before>window.addEvent('domready', function() {
    var buttons = $$('[data-mp3]'),
        remixmode = $('remixmode'),
        frenchKeyboard = 'azertyuiopqsdfghjklmwxcvbn'.split(''),
        mainEvent = (('ontouchend' in window)) ? 'touchend' : 'click';

    // Launch player
    buttons.each(function(el) {
        el.addEvent(mainEvent, function(e) {
            e.preventDefault();
            clickButton($(this), buttons);
        });
    });

    // Destroy all audio players on shut
    $('shut').addEvent(mainEvent, function(e) {
        e.preventDefault();
        stopSounds(buttons);
    });

    // Autoplay from hash
    autoplayFromHash(buttons);

    // Keyboard Events
    launchKeyboardEvents(buttons, frenchKeyboard);

    // Scroll top
    $(window).scrollTo(0, 0);
});

/* ----------------------------------------------------------
  Functions
---------------------------------------------------------- */

/* Autoplay from hash
-------------------------- */

var autoplayFromHash = function(buttons) {
    if (window.location.hash) {
        var hash = window.location.hash.replace('#', '');
        buttons.each(function(el) {
            var data_mp3 = el.getAttribute('data-mp3');
            if (data_mp3 == hash) {
                clickButton(el, buttons);
            }
        });
    }
};

/* Keyboard events
-------------------------- */

var launchKeyboardEvents = function(buttons, frenchKeyboard) {
    // Keyboards event
    window.addEvent('keydown', function(e) {
        if (!e.code) {
            return;
        }
        // Echap : stop sound
        if (e.code == 27) {
            stopSounds(buttons);
            return;
        }

        // Keyboard code
        if (e.shift || e.meta || e.control || e.alt) {
            return;
        }
        var kCode = String.fromCharCode(e.code).toLowerCase(),
            kId = frenchKeyboard.indexOf(kCode);
        if ((kId || kId === 0) && buttons[kId]) {
            clickButton(buttons[kId], buttons);
        }
    });
};

/* ----------------------------------------------------------
  Utilities
---------------------------------------------------------- */

/* Click Button
-------------------------- */

var clickButton = function(button, buttons) {
    if (!remixmode.checked) {
        stopSounds(buttons);
    }
    playMp3(button);
};

/* Stop all sounds
-------------------------- */

var stopSounds = function(buttons) {
    if ("pushState" in history) {
        history.pushState("", document.title, window.location.pathname + window.location.search);
    }
    else {
        window.location.hash = '';
    }
    buttons.removeClass('current');
    $$('.audio-player').destroy();
};

/* Play a mp3
-------------------------- */

var playMp3 = function(self) {
    self.addClass('current');
    var url = self.getAttribute('data-mp3'),
        audioElement = new Element('audio');
    audioElement.addEventListener('ended', function() {
        self.removeClass('current');
    });
    audioElement.addClass('audio-player');
    audioElement.set('src', url);
    audioElement.play();
    audioElement.inject($(document.body), 'after');
    window.location.hash = url;
};<commit_msg>Use tap event on a mobile view<commit_after>window.addEvent('domready', function() {
    var buttons = $$('[data-mp3]'),
        remixmode = $('remixmode'),
        frenchKeyboard = 'azertyuiopqsdfghjklmwxcvbn'.split(''),
        mainEvent = (('ontouchend' in window)) ? 'tap' : 'click';

    // Launch player
    buttons.each(function(el) {
        if (mainEvent == 'tap') {
            setTapEvent(el);
        }
        el.addEvent(mainEvent, function(e) {
            if (e) {
                e.preventDefault();
            }
            clickButton($(this), buttons);
        });
    });

    // Destroy all audio players on shut
    $('shut').addEvent(mainEvent, function(e) {
        e.preventDefault();
        stopSounds(buttons);
    });

    // Autoplay from hash
    autoplayFromHash(buttons);

    // Keyboard Events
    launchKeyboardEvents(buttons, frenchKeyboard);

    // Scroll top
    $(window).scrollTo(0, 0);
});

/* ----------------------------------------------------------
  Functions
---------------------------------------------------------- */

/* Tap event
-------------------------- */

var setTapEvent = function(el) {
    var duration = 300,
        timerStart, timerEnd;

    function startTimer() {
        timerStart = new Date().getTime();
    }

    function endTimer() {
        timerEnd = new Date().getTime();
        if (timerEnd - timerStart < duration) {
            el.fireEvent('tap');
        }
    }

    if (window.navigator.msPointerEnabled) {
        el.style.touchAction = "none";
        el.style.msTouchAction = "none";
        el.addEvent('MSPointerDown', startTimer);
        el.addEvent('MSPointerUp', endTimer);
    }
    else {
        el.addEvent('touchstart', startTimer);
        el.addEvent('touchend', endTimer);
    }
};

/* Autoplay from hash
-------------------------- */

var autoplayFromHash = function(buttons) {
    if (window.location.hash) {
        var hash = window.location.hash.replace('#', '');
        buttons.each(function(el) {
            var data_mp3 = el.getAttribute('data-mp3');
            if (data_mp3 == hash) {
                clickButton(el, buttons);
            }
        });
    }
};

/* Keyboard events
-------------------------- */

var launchKeyboardEvents = function(buttons, frenchKeyboard) {
    // Keyboards event
    window.addEvent('keydown', function(e) {
        if (!e.code) {
            return;
        }
        // Echap : stop sound
        if (e.code == 27) {
            stopSounds(buttons);
            return;
        }

        // Keyboard code
        if (e.shift || e.meta || e.control || e.alt) {
            return;
        }
        var kCode = String.fromCharCode(e.code).toLowerCase(),
            kId = frenchKeyboard.indexOf(kCode);
        if ((kId || kId === 0) && buttons[kId]) {
            clickButton(buttons[kId], buttons);
        }
    });
};

/* ----------------------------------------------------------
  Utilities
---------------------------------------------------------- */

/* Click Button
-------------------------- */

var clickButton = function(button, buttons) {
    if (!remixmode.checked) {
        stopSounds(buttons);
    }
    playMp3(button);
};

/* Stop all sounds
-------------------------- */

var stopSounds = function(buttons) {
    if ("pushState" in history) {
        history.pushState("", document.title, window.location.pathname + window.location.search);
    }
    else {
        window.location.hash = '';
    }
    buttons.removeClass('current');
    $$('.audio-player').destroy();
};

/* Play a mp3
-------------------------- */

var playMp3 = function(self) {
    self.addClass('current');
    var url = self.getAttribute('data-mp3'),
        audioElement = new Element('audio');
    audioElement.addEventListener('ended', function() {
        self.removeClass('current');
    });
    audioElement.addClass('audio-player');
    audioElement.set('src', url);
    audioElement.play();
    audioElement.inject($(document.body), 'after');
    window.location.hash = url;
};<|endoftext|>


<commit_before>module.exports = function (config) {
  config.set({
    basePath: '..',
    frameworks: ['jasmine'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-coverage')
    ],
    customLaunchers: {
      // chrome setup for travis CI using chromium
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },
    files: [
      { pattern: 'dist/vendor/es6-shim/es6-shim.js', included: true, watched: false },
      { pattern: 'dist/vendor/zone.js/dist/zone.js', included: true, watched: false },
      { pattern: 'dist/vendor/reflect-metadata/Reflect.js', included: true, watched: false },
      { pattern: 'dist/vendor/systemjs/dist/system-polyfills.js', included: true, watched: false },
      { pattern: 'dist/vendor/systemjs/dist/system.src.js', included: true, watched: false },
      { pattern: 'dist/vendor/zone.js/dist/async-test.js', included: true, watched: false },

      { pattern: 'config/karma-test-shim.js', included: true, watched: true },

      // Distribution folder.
      { pattern: 'dist/**/*', included: false, watched: true }
    ],
    exclude: [
      // Vendor packages might include spec files. We don't want to use those.
      'dist/vendor/**/*.spec.js'
    ],
    preprocessors: {},
    preprocessors: { 'dist/app/**/!(*spec).js': ['coverage'] },
    coverageReporter: {
      dir : 'coverage/',
      reporters: [
        { type: 'html' },
        { type: 'lcov' }
      ]
    },
    reporters: ['progress', 'coverage'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<commit_msg>change test coverage to components folder<commit_after>module.exports = function (config) {
  config.set({
    basePath: '..',
    frameworks: ['jasmine'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-coverage')
    ],
    customLaunchers: {
      // chrome setup for travis CI using chromium
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },
    files: [
      { pattern: 'dist/vendor/es6-shim/es6-shim.js', included: true, watched: false },
      { pattern: 'dist/vendor/zone.js/dist/zone.js', included: true, watched: false },
      { pattern: 'dist/vendor/reflect-metadata/Reflect.js', included: true, watched: false },
      { pattern: 'dist/vendor/systemjs/dist/system-polyfills.js', included: true, watched: false },
      { pattern: 'dist/vendor/systemjs/dist/system.src.js', included: true, watched: false },
      { pattern: 'dist/vendor/zone.js/dist/async-test.js', included: true, watched: false },

      { pattern: 'config/karma-test-shim.js', included: true, watched: true },

      // Distribution folder.
      { pattern: 'dist/**/*', included: false, watched: true }
    ],
    exclude: [
      // Vendor packages might include spec files. We don't want to use those.
      'dist/vendor/**/*.spec.js'
    ],
    preprocessors: {},
    preprocessors: {
      'dist/components/**/!(*spec).js': ['coverage']
    },
    coverageReporter: {
      dir : 'coverage/',
      reporters: [
        { type: 'html' },
        { type: 'lcov' }
      ]
    },
    reporters: ['progress', 'coverage'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<|endoftext|>


<commit_before>/**
 * Topic.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/documentation/concepts/models-and-orm/models
 */

var _ = require('lodash');
var Promise = require('bluebird');

module.exports = {

  attributes: {
    name: {
      type: Sequelize.STRING,
      allowNull: false
    },

    title: {
      type: Sequelize.TEXT,
      allowNull: false
    },

    description: {
      type: Sequelize.TEXT,
    },

    usage: {
      type: Sequelize.TEXT,
    },

    details: {
      type: Sequelize.TEXT,
    },

    value: {
      type: Sequelize.TEXT,
    },

    references: {
      type: Sequelize.TEXT,
    },

    note: {
      type: Sequelize.TEXT,
    },

    author: {
      type: Sequelize.TEXT,
    },

    seealso: {
      type: Sequelize.TEXT,
    },

    examples: {
      type: Sequelize.TEXT,
    },

  },
  associations: function() {

    Topic.belongsTo(PackageVersion,
      {
        as: 'package_version',
        foreignKey: {
          allowNull: false,
          required: true,
          name: 'package_version_id',
          as: 'package_version'
        }
      });

    Topic.hasMany(Argument, {as: 'arguments', foreignKey: 'topic_id'});

    Topic.hasMany(Section, {as: 'sections', foreignKey: 'topic_id'});

    Topic.hasMany(Alias, {as: 'aliases', foreignKey: 'topic_id'});

    Topic.belongsToMany(Tag, {as: 'keywords', through: 'TopicTags', foreignKey: 'topic_id', timestamps: false});
  },

  options: {
    underscored: true,

    indexes: [
      {
        type: 'UNIQUE',
        fields: ['name', 'package_version_id']
      }
    ],

    classMethods: {
      findOnePopulated: function(criteria, opts) {
        function customizer(objValue, srcValue) {
          if (_.isArray(objValue)) {
            return objValue.concat(srcValue);
          }
        }

        var options = _.mergeWith({
          where: criteria,
          include: [
            {model: Argument, as: 'arguments', attributes: ['name', 'description']},
            {model: Section, as: 'sections', attributes: ['name', 'description']},
            {model: Tag, as: 'keywords', attributes: ['name']},
            {model: Alias, as: 'aliases', attributes: ['name']}
          ]
        }, opts, customizer);

        return Topic.findOne(options);
      },

      createWithRdFile: function(opts) {
        var rdJSON = opts.input;
        return sequelize.transaction(function (t) {
          var attributes = [
            'name',
            'title',
            'description',
            'usage',
            'details',
            'value',
            'references',
            'note',
            'seealso',
            'examples'
          ];
          var topic = _.pick(rdJSON, attributes);
          if (topic.value instanceof Array) {{
            var valueArray = topic.value;
            topic.value = '';
            valueArray.forEach(function(item) {
              if ( typeof item === 'string') {
                topic.value += item;
              } else if ( typeof item === 'object') {
                for (var key in item) {
                  topic.value += '<' + key + '>' + item[key] + '</' + key + '>';
                }
              }

            });
          }}
          var customSections = _.omit(rdJSON, attributes.concat(['alias', 'arguments', 'keyword', 'author']));
          topic.author = rdJSON.author ? rdJSON.author.map(function(author){
            return author.name + ' ' +author.email;
          }).join(', ') : rdJSON.author;

          return PackageVersion.findOne({
            where: {package_name: opts.packageName, version: opts.packageVersion },
            transaction: t
          }).then(function(version) {
            if (version === null) throw {
              status: 404,
              message: 'Package ' + opts.packageName + ' Version ' + opts.packageVersion + ' cannot be found'
            };
            else topic.package_version_id = version.id;

            var keywords = rdJSON.keyword && !(rdJSON.keyword instanceof Array) ? [rdJSON.keyword] : rdJSON.keyword;
            var keywordsRecords =  _.isEmpty(keywords) ? [] :
              _.chain(keywords)
                .map(function(entry) { return entry.split(','); })
                .flatten()
                .map(function(keyword) {
                  return {name: keyword};
                })
                .value();

            return Promise.join(
              Topic.create(topic, {
                include: [ {model: Tag, as: 'keywords'} ]
              }),
              Tag.bulkCreate(keywordsRecords, {transaction:t, ignoreDuplicates: true})
              .then(function(instances) {
                var names = _.map(instances, function (inst) {
                  return inst.name;
                });
                return Tag.findAll({where: {name: {$in: names}}, transaction:t });
              }),
              function(topicInstance, keywordsInstances) {
                var topicArguments = _.isEmpty(rdJSON.arguments) ? [] : rdJSON.arguments.map(function(argument) {
                  return _.merge({}, argument, {topic_id: topicInstance.id});
                });

                var aliases = rdJSON.alias && !(rdJSON.alias instanceof Array) ? [rdJSON.alias] : rdJSON.alias;
                var aliasesRecords = _.isEmpty(aliases) ? [] : aliases.map(function(alias) {
                  return {name: alias, topic_id: topicInstance.id};
                });

                var sections = _.toPairs(customSections).map(function(pair) {
                  return { name: pair[0], description: pair[1], topic_id: topicInstance.id };
                });

                return Promise.all([
                  Argument.bulkCreate(topicArguments, {transaction: t}),
                  Alias.bulkCreate(aliasesRecords, {transaction: t}),
                  Section.bulkCreate(sections, {transaction: t}),
                  topicInstance.addKeywords(keywordsInstances, {transaction: t })
                ]).then(_.partial(Topic.findOnePopulated, {id: topicInstance.id}, {transaction: t}));
            });
          });

        });

      }
    }
  }

};

<commit_msg>handle custom section being an array<commit_after>/**
 * Topic.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/documentation/concepts/models-and-orm/models
 */

var _ = require('lodash');
var Promise = require('bluebird');

module.exports = {

  attributes: {
    name: {
      type: Sequelize.STRING,
      allowNull: false
    },

    title: {
      type: Sequelize.TEXT,
      allowNull: false
    },

    description: {
      type: Sequelize.TEXT,
    },

    usage: {
      type: Sequelize.TEXT,
    },

    details: {
      type: Sequelize.TEXT,
    },

    value: {
      type: Sequelize.TEXT,
    },

    references: {
      type: Sequelize.TEXT,
    },

    note: {
      type: Sequelize.TEXT,
    },

    author: {
      type: Sequelize.TEXT,
    },

    seealso: {
      type: Sequelize.TEXT,
    },

    examples: {
      type: Sequelize.TEXT,
    },

  },
  associations: function() {

    Topic.belongsTo(PackageVersion,
      {
        as: 'package_version',
        foreignKey: {
          allowNull: false,
          required: true,
          name: 'package_version_id',
          as: 'package_version'
        }
      });

    Topic.hasMany(Argument, {as: 'arguments', foreignKey: 'topic_id'});

    Topic.hasMany(Section, {as: 'sections', foreignKey: 'topic_id'});

    Topic.hasMany(Alias, {as: 'aliases', foreignKey: 'topic_id'});

    Topic.belongsToMany(Tag, {as: 'keywords', through: 'TopicTags', foreignKey: 'topic_id', timestamps: false});
  },

  options: {
    underscored: true,

    indexes: [
      {
        type: 'UNIQUE',
        fields: ['name', 'package_version_id']
      }
    ],

    classMethods: {
      findOnePopulated: function(criteria, opts) {
        function customizer(objValue, srcValue) {
          if (_.isArray(objValue)) {
            return objValue.concat(srcValue);
          }
        }

        var options = _.mergeWith({
          where: criteria,
          include: [
            {model: Argument, as: 'arguments', attributes: ['name', 'description']},
            {model: Section, as: 'sections', attributes: ['name', 'description']},
            {model: Tag, as: 'keywords', attributes: ['name']},
            {model: Alias, as: 'aliases', attributes: ['name']}
          ]
        }, opts, customizer);

        return Topic.findOne(options);
      },

      createWithRdFile: function(opts) {
        var rdJSON = opts.input;
        return sequelize.transaction(function (t) {
          var attributes = [
            'name',
            'title',
            'description',
            'usage',
            'details',
            'value',
            'references',
            'note',
            'seealso',
            'examples'
          ];

          var reduceArrayToString = function(array) {
            return array.reduce(function(acc, item) {
              if ( typeof item === 'string') {
                return acc + item;
              } else if ( typeof item === 'object') {
                for (var key in item) {
                  acc += '<' + key + '>' + item[key] + '</' + key + '>';
                }
                return acc;
              }

            }, '');
          };

          var topic = _.pick(rdJSON, attributes);
          if (topic.value instanceof Array) {
            var valueArray = topic.value;
            topic.value = reduceArrayToString(reduceArrayToString);
          }
          var customSections = _.omit(rdJSON, attributes.concat(['alias', 'arguments', 'keyword', 'author', 'docType', 'Rdversion']));
          topic.author = rdJSON.author ? rdJSON.author.map(function(author){
            return author.name + ' ' +author.email;
          }).join(', ') : rdJSON.author;

          customSections = customSections.map(function(section) {
            if (section instanceof Array) {
              return reduceArrayToString(section);
            } else return section;
          });

          return PackageVersion.findOne({
            where: {package_name: opts.packageName, version: opts.packageVersion },
            transaction: t
          }).then(function(version) {
            if (version === null) throw {
              status: 404,
              message: 'Package ' + opts.packageName + ' Version ' + opts.packageVersion + ' cannot be found'
            };
            else topic.package_version_id = version.id;

            var keywords = rdJSON.keyword && !(rdJSON.keyword instanceof Array) ? [rdJSON.keyword] : rdJSON.keyword;
            var keywordsRecords =  _.isEmpty(keywords) ? [] :
              _.chain(keywords)
                .map(function(entry) { return entry.split(','); })
                .flatten()
                .map(function(keyword) {
                  return {name: keyword};
                })
                .value();

            return Promise.join(
              Topic.create(topic, {
                include: [ {model: Tag, as: 'keywords'} ]
              }),
              Tag.bulkCreate(keywordsRecords, {transaction:t, ignoreDuplicates: true})
              .then(function(instances) {
                var names = _.map(instances, function (inst) {
                  return inst.name;
                });
                return Tag.findAll({where: {name: {$in: names}}, transaction:t });
              }),
              function(topicInstance, keywordsInstances) {
                var topicArguments = _.isEmpty(rdJSON.arguments) ? [] : rdJSON.arguments.map(function(argument) {
                  return _.merge({}, argument, {topic_id: topicInstance.id});
                });

                var aliases = rdJSON.alias && !(rdJSON.alias instanceof Array) ? [rdJSON.alias] : rdJSON.alias;
                var aliasesRecords = _.isEmpty(aliases) ? [] : aliases.map(function(alias) {
                  return {name: alias, topic_id: topicInstance.id};
                });

                var sections = _.toPairs(customSections).map(function(pair) {
                  return { name: pair[0], description: pair[1], topic_id: topicInstance.id };
                });

                return Promise.all([
                  Argument.bulkCreate(topicArguments, {transaction: t}),
                  Alias.bulkCreate(aliasesRecords, {transaction: t}),
                  Section.bulkCreate(sections, {transaction: t}),
                  topicInstance.addKeywords(keywordsInstances, {transaction: t })
                ]).then(_.partial(Topic.findOnePopulated, {id: topicInstance.id}, {transaction: t}));
            });
          });

        });

      }
    }
  }

};

<|endoftext|>