<commit_before>(function(){

function updateStatus(statusEl, result){
	statusEl.removeClass('success error loading-small');
	if (result && result.status == 'success' && result.data.message) {
		statusEl.addClass('success');
		return true;
	} else {
		statusEl.addClass('error');
		return false;
	}
}

OC.MountConfig={
	saveStorage:function(tr, callback) {
		var mountPoint = $(tr).find('.mountPoint input').val();
		if (mountPoint == '') {
			return false;
		}
		var statusSpan = $(tr).closest('tr').find('.status span');
		var backendClass = $(tr).find('.backend').data('class');
		var configuration = $(tr).find('.configuration input');
		var addMountPoint = true;
		if (configuration.length < 1) {
			return false;
		}
		var classOptions = {};
		$.each(configuration, function(index, input) {
			if ($(input).val() == '' && !$(input).hasClass('optional')) {
				addMountPoint = false;
				return false;
			}
			if ($(input).is(':checkbox')) {
				if ($(input).is(':checked')) {
					classOptions[$(input).data('parameter')] = true;
				} else {
					classOptions[$(input).data('parameter')] = false;
				}
			} else {
				classOptions[$(input).data('parameter')] = $(input).val();
			}
		});
		if ($('#externalStorage').data('admin') === true) {
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect == null) {
				return false;
			}
		}
		if (addMountPoint) {
			var status = false;
			if ($('#externalStorage').data('admin') === true) {
				var isPersonal = false;
				var oldGroups = $(tr).find('.applicable').data('applicable-groups');
				var oldUsers = $(tr).find('.applicable').data('applicable-users');
				var groups = [];
				var users = [];
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
						if ($.inArray(applicable, oldGroups) != -1) {
							oldGroups.splice($.inArray(applicable, oldGroups), 1);
						}
						groups.push(applicable);
					} else {
						var mountType = 'user';
						var applicable = value;
						if ($.inArray(applicable, oldUsers) != -1) {
							oldUsers.splice($.inArray(applicable, oldUsers), 1);
						}
						users.push(applicable);
					}
					statusSpan.addClass('loading-small').removeClass('error success');
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						},
						success: function(result) {
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						},
						error: function(result){
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						}
					});
				});
				$(tr).find('.applicable').data('applicable-groups', groups);
				$(tr).find('.applicable').data('applicable-users', users);
				var mountType = 'group';
				$.each(oldGroups, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
				var mountType = 'user';
				$.each(oldUsers, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
			} else {
				var isPersonal = true;
				var mountType = 'user';
				var applicable = OC.currentUser;
				statusSpan.addClass('loading-small').removeClass('error success');
				$.ajax({type: 'POST',
					url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
					data: {
						mountPoint: mountPoint,
						'class': backendClass,
						classOptions: classOptions,
						mountType: mountType,
						applicable: applicable,
						isPersonal: isPersonal
					},
					success: function(result) {
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					},
					error: function(result){
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					}
				});
			}
			return status;
		}
	}
};

$(document).ready(function() {
	$('.chzn-select').chosen();

	$('#externalStorage').on('change', '#selectBackend', function() {
		var tr = $(this).parent().parent();
		$('#externalStorage tbody').append($(tr).clone());
		$('#externalStorage tbody tr').last().find('.mountPoint input').val('');
		var selected = $(this).find('option:selected').text();
		var backendClass = $(this).val();
		$(this).parent().text(selected);
		if ($(tr).find('.mountPoint input').val() == '') {
			$(tr).find('.mountPoint input').val(suggestMountPoint(selected));
		}
		$(tr).addClass(backendClass);
		$(tr).find('.status').append('');
		$(tr).find('.backend').data('class', backendClass);
		var configurations = $(this).data('configurations');
		var td = $(tr).find('td.configuration');
		$.each(configurations, function(backend, parameters) {
			if (backend == backendClass) {
				$.each(parameters['configuration'], function(parameter, placeholder) {
					var is_optional = false;
					if (placeholder.indexOf('&') === 0) {
						is_optional = true;
						placeholder = placeholder.substring(1);
					}
					if (placeholder.indexOf('*') === 0) {
						var class_string = is_optional ? ' class="optional"' : '';
						td.append('<input type="password"' + class_string + ' data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
					} else if (placeholder.indexOf('!') === 0) {
						td.append('<input type="checkbox" data-parameter="'+parameter+'" />'+placeholder.substring(1)+'');
					} else if (placeholder.indexOf('#') === 0) {
						td.append('<input type="hidden" data-parameter="'+parameter+'" />');
					} else {
						var class_string = is_optional ? ' class="optional"' : '';
						td.append('<input type="text"' + class_string + ' data-parameter="'+parameter+'" placeholder="'+placeholder+'" />');
					}
				});
				if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass.replace(/\\/g, '\\\\')).length == 1) {
					OC.addScript('files_external', parameters['custom']);
				}
				return false;
			}
		});
		// Reset chosen
		var chosen = $(tr).find('.applicable select');
		chosen.parent().find('div').remove();
		chosen.removeAttr('id').removeClass('chzn-done').css({display:'inline-block'});
		chosen.chosen();
		$(tr).find('td').last().attr('class', 'remove');
		$(tr).find('td').last().removeAttr('style');
		$(tr).removeAttr('id');
		$(this).remove();
	});

	function suggestMountPoint(defaultMountPoint) {
		var pos = defaultMountPoint.indexOf('/');
		if (pos !== -1) {
			defaultMountPoint = defaultMountPoint.substring(0, pos);
		}
		defaultMountPoint = defaultMountPoint.replace(/\s+/g, '');
		var i = 1;
		var append = '';
		var match = true;
		while (match && i < 20) {
			match = false;
			$('#externalStorage tbody td.mountPoint input').each(function(index, mountPoint) {
				if ($(mountPoint).val() == defaultMountPoint+append) {
					match = true;
					return false;
				}
			});
			if (match) {
				append = i;
				i++;
			} else {
				break;
			}
		}
		return defaultMountPoint+append;
	}

	$('#externalStorage').on('paste', 'td', function() {
		var tr = $(this).parent();
		setTimeout(function() {
			OC.MountConfig.saveStorage(tr);
		}, 20);
	});

	var timer;

	$('#externalStorage').on('keyup', 'td input', function() {
		clearTimeout(timer);
		var tr = $(this).parent().parent();
		if ($(this).val) {
			timer = setTimeout(function() {
				OC.MountConfig.saveStorage(tr);
			}, 2000);
		}
	});

	$('#externalStorage').on('change', 'td input:checkbox', function() {
		OC.MountConfig.saveStorage($(this).parent().parent().parent());
	});

	$('#externalStorage').on('change', '.applicable .chzn-select', function() {
		OC.MountConfig.saveStorage($(this).parent().parent());
	});

	$('#sslCertificate').on('click', 'td.remove>img', function() {
		var $tr = $(this).parent().parent();
		var row = this.parentNode.parentNode;
		$.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id});
		$tr.remove();
		return true;
	});

	$('#externalStorage').on('click', 'td.remove>img', function() {
		var tr = $(this).parent().parent();
		var mountPoint = $(tr).find('.mountPoint input').val();

		if ($('#externalStorage').data('admin') === true) {
			var isPersonal = false;
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect != null) {
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
					} else {
						var mountType = 'user';
						var applicable = value;
					}
					$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
				});
			}
		} else {
			var mountType = 'user';
			var applicable = OC.currentUser;
			var isPersonal = true;
			$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
		}
		$(tr).remove();
	});

	$('#allowUserMounting').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		if (this.checked) {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes');
			$('input[name="allowUserMountingBackends\\[\\]"]').prop('checked', true);
			$('#userMountingBackends').removeClass('hidden');
			$($('input[name="allowUserMountingBackends\\[\\]"]')[0]).trigger('change');
		} else {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no');
			$('#userMountingBackends').addClass('hidden');
		}
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
	});

	$('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		var user_mounting_backends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get();
		OC.AppConfig.setValue('files_external', 'user_mounting_backends', user_mounting_backends.join());
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});

		// disable allowUserMounting
		if(user_mounting_backends.length === 0) {
			$('#allowUserMounting').prop('checked', false);
			$('#allowUserMounting').trigger('change');

		}
	});
});

})();
<commit_msg>fix camelCase and avoiud re-wrapping $()<commit_after>(function(){

function updateStatus(statusEl, result){
	statusEl.removeClass('success error loading-small');
	if (result && result.status == 'success' && result.data.message) {
		statusEl.addClass('success');
		return true;
	} else {
		statusEl.addClass('error');
		return false;
	}
}

OC.MountConfig={
	saveStorage:function(tr, callback) {
		var mountPoint = $(tr).find('.mountPoint input').val();
		if (mountPoint == '') {
			return false;
		}
		var statusSpan = $(tr).closest('tr').find('.status span');
		var backendClass = $(tr).find('.backend').data('class');
		var configuration = $(tr).find('.configuration input');
		var addMountPoint = true;
		if (configuration.length < 1) {
			return false;
		}
		var classOptions = {};
		$.each(configuration, function(index, input) {
			if ($(input).val() == '' && !$(input).hasClass('optional')) {
				addMountPoint = false;
				return false;
			}
			if ($(input).is(':checkbox')) {
				if ($(input).is(':checked')) {
					classOptions[$(input).data('parameter')] = true;
				} else {
					classOptions[$(input).data('parameter')] = false;
				}
			} else {
				classOptions[$(input).data('parameter')] = $(input).val();
			}
		});
		if ($('#externalStorage').data('admin') === true) {
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect == null) {
				return false;
			}
		}
		if (addMountPoint) {
			var status = false;
			if ($('#externalStorage').data('admin') === true) {
				var isPersonal = false;
				var oldGroups = $(tr).find('.applicable').data('applicable-groups');
				var oldUsers = $(tr).find('.applicable').data('applicable-users');
				var groups = [];
				var users = [];
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
						if ($.inArray(applicable, oldGroups) != -1) {
							oldGroups.splice($.inArray(applicable, oldGroups), 1);
						}
						groups.push(applicable);
					} else {
						var mountType = 'user';
						var applicable = value;
						if ($.inArray(applicable, oldUsers) != -1) {
							oldUsers.splice($.inArray(applicable, oldUsers), 1);
						}
						users.push(applicable);
					}
					statusSpan.addClass('loading-small').removeClass('error success');
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						},
						success: function(result) {
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						},
						error: function(result){
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						}
					});
				});
				$(tr).find('.applicable').data('applicable-groups', groups);
				$(tr).find('.applicable').data('applicable-users', users);
				var mountType = 'group';
				$.each(oldGroups, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
				var mountType = 'user';
				$.each(oldUsers, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
			} else {
				var isPersonal = true;
				var mountType = 'user';
				var applicable = OC.currentUser;
				statusSpan.addClass('loading-small').removeClass('error success');
				$.ajax({type: 'POST',
					url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
					data: {
						mountPoint: mountPoint,
						'class': backendClass,
						classOptions: classOptions,
						mountType: mountType,
						applicable: applicable,
						isPersonal: isPersonal
					},
					success: function(result) {
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					},
					error: function(result){
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					}
				});
			}
			return status;
		}
	}
};

$(document).ready(function() {
	$('.chzn-select').chosen();

	$('#externalStorage').on('change', '#selectBackend', function() {
		var tr = $(this).parent().parent();
		$('#externalStorage tbody').append($(tr).clone());
		$('#externalStorage tbody tr').last().find('.mountPoint input').val('');
		var selected = $(this).find('option:selected').text();
		var backendClass = $(this).val();
		$(this).parent().text(selected);
		if ($(tr).find('.mountPoint input').val() == '') {
			$(tr).find('.mountPoint input').val(suggestMountPoint(selected));
		}
		$(tr).addClass(backendClass);
		$(tr).find('.status').append('');
		$(tr).find('.backend').data('class', backendClass);
		var configurations = $(this).data('configurations');
		var td = $(tr).find('td.configuration');
		$.each(configurations, function(backend, parameters) {
			if (backend == backendClass) {
				$.each(parameters['configuration'], function(parameter, placeholder) {
					var is_optional = false;
					if (placeholder.indexOf('&') === 0) {
						is_optional = true;
						placeholder = placeholder.substring(1);
					}
					if (placeholder.indexOf('*') === 0) {
						var class_string = is_optional ? ' class="optional"' : '';
						td.append('<input type="password"' + class_string + ' data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
					} else if (placeholder.indexOf('!') === 0) {
						td.append('<input type="checkbox" data-parameter="'+parameter+'" />'+placeholder.substring(1)+'');
					} else if (placeholder.indexOf('#') === 0) {
						td.append('<input type="hidden" data-parameter="'+parameter+'" />');
					} else {
						var class_string = is_optional ? ' class="optional"' : '';
						td.append('<input type="text"' + class_string + ' data-parameter="'+parameter+'" placeholder="'+placeholder+'" />');
					}
				});
				if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass.replace(/\\/g, '\\\\')).length == 1) {
					OC.addScript('files_external', parameters['custom']);
				}
				return false;
			}
		});
		// Reset chosen
		var chosen = $(tr).find('.applicable select');
		chosen.parent().find('div').remove();
		chosen.removeAttr('id').removeClass('chzn-done').css({display:'inline-block'});
		chosen.chosen();
		$(tr).find('td').last().attr('class', 'remove');
		$(tr).find('td').last().removeAttr('style');
		$(tr).removeAttr('id');
		$(this).remove();
	});

	function suggestMountPoint(defaultMountPoint) {
		var pos = defaultMountPoint.indexOf('/');
		if (pos !== -1) {
			defaultMountPoint = defaultMountPoint.substring(0, pos);
		}
		defaultMountPoint = defaultMountPoint.replace(/\s+/g, '');
		var i = 1;
		var append = '';
		var match = true;
		while (match && i < 20) {
			match = false;
			$('#externalStorage tbody td.mountPoint input').each(function(index, mountPoint) {
				if ($(mountPoint).val() == defaultMountPoint+append) {
					match = true;
					return false;
				}
			});
			if (match) {
				append = i;
				i++;
			} else {
				break;
			}
		}
		return defaultMountPoint+append;
	}

	$('#externalStorage').on('paste', 'td', function() {
		var tr = $(this).parent();
		setTimeout(function() {
			OC.MountConfig.saveStorage(tr);
		}, 20);
	});

	var timer;

	$('#externalStorage').on('keyup', 'td input', function() {
		clearTimeout(timer);
		var tr = $(this).parent().parent();
		if ($(this).val) {
			timer = setTimeout(function() {
				OC.MountConfig.saveStorage(tr);
			}, 2000);
		}
	});

	$('#externalStorage').on('change', 'td input:checkbox', function() {
		OC.MountConfig.saveStorage($(this).parent().parent().parent());
	});

	$('#externalStorage').on('change', '.applicable .chzn-select', function() {
		OC.MountConfig.saveStorage($(this).parent().parent());
	});

	$('#sslCertificate').on('click', 'td.remove>img', function() {
		var $tr = $(this).parent().parent();
		var row = this.parentNode.parentNode;
		$.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id});
		$tr.remove();
		return true;
	});

	$('#externalStorage').on('click', 'td.remove>img', function() {
		var tr = $(this).parent().parent();
		var mountPoint = $(tr).find('.mountPoint input').val();

		if ($('#externalStorage').data('admin') === true) {
			var isPersonal = false;
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect != null) {
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
					} else {
						var mountType = 'user';
						var applicable = value;
					}
					$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
				});
			}
		} else {
			var mountType = 'user';
			var applicable = OC.currentUser;
			var isPersonal = true;
			$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
		}
		$(tr).remove();
	});

	$('#allowUserMounting').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		if (this.checked) {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes');
			$('input[name="allowUserMountingBackends\\[\\]"]').prop('checked', true);
			$('#userMountingBackends').removeClass('hidden');
			$('input[name="allowUserMountingBackends\\[\\]"]').eq(0).trigger('change');
		} else {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no');
			$('#userMountingBackends').addClass('hidden');
		}
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
	});

	$('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get();
		OC.AppConfig.setValue('files_external', 'user_mounting_backends', userMountingBackends.join());
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});

		// disable allowUserMounting
		if(userMountingBackends.length === 0) {
			$('#allowUserMounting').prop('checked', false);
			$('#allowUserMounting').trigger('change');

		}
	});
});

})();
<|endoftext|>


<commit_before>import { moduleFor, test } from 'ember-qunit';
import sinon from 'sinon';
import EmberObject from '@ember/object';

let sandbox, config, instanceStub, identity;

moduleFor('ember-metrics@metrics-adapter:amplitude', 'amplitude adapter', {
  beforeEach() {
    sandbox = sinon.createSandbox();
    config = {
      apiKey: 'AMPLITUDE_KEY'
    };
    instanceStub = EmberObject.create({
      identify: sinon.fake(),
      setUserId: sinon.fake(),
      logEvent: sinon.fake(),
      setOptOut: sinon.fake()
    });
    identity = EmberObject.create();
  },
  afterEach() {
    sandbox.restore();
  }
});

test('#identify sets the distinct user ID, and calls amplitude with any extra user properties', function(assert) {
  const adapter = this.subject({ config });

  sandbox.replace(window.amplitude, 'getInstance', () => instanceStub);
  sandbox.replace(window.amplitude, 'Identify', () => identity);

  adapter.identify({
    distinctId: '123',
    email: 'ben.simmons@sixers.net'
  });

  assert.ok(instanceStub.setUserId.calledWith('123'), 'it calls setUserId with distinctId');
  assert.ok(instanceStub.identify.calledWith(identity), 'it sends the correct user identity');
  assert.ok(instanceStub.logEvent.calledWith('Identify'), 'it calls a logEvent for "Identify"');

  assert.equal(identity.get('email'), 'ben.simmons@sixers.net', 'extra user properties are correctly assigned to the identity');
});

test('#trackEvent sends the correct request shape', function(assert) {
  const adapter = this.subject({ config });
  sandbox.replace(window.amplitude, 'getInstance', () => instanceStub);

  adapter.trackEvent({
    event: 'Registered User',
    email: 'joel.embiid@sixers.net'
  });
  const expectedEventProperties = {
    email: 'joel.embiid@sixers.net'
  };

  assert.ok(instanceStub.logEvent.calledWith('Registered User', expectedEventProperties), 'track called with proper arguments');
});

test('#trackPage returns the correct response shape', function(assert) {
  const adapter = this.subject({ config });
  sandbox.replace(window.amplitude, 'getInstance', () => instanceStub);

  const pageProperties = {
    url: '/shot-charts/missed-threes'
  };
  adapter.trackPage(pageProperties);

  assert.ok(instanceStub.logEvent.calledWith('Page View', pageProperties), 'track called with proper arguments');
});

test('#optOut calls amplitude optOut with false', function(assert) {
  const adapter = this.subject({ config });
  sandbox.replace(window.amplitude, 'getInstance', () => instanceStub);

  adapter.optOut();

  assert.ok(instanceStub.setOptOut.calledWith(true), 'optOut called with correct arguments');
});

test('#optIn calls amplitude optOut with false', function(assert) {
  const adapter = this.subject({ config });
  sandbox.replace(window.amplitude, 'getInstance', () => instanceStub);

  adapter.optIn();

  assert.ok(instanceStub.setOptOut.calledWith(false), 'optOut called with correct arguments');
});
<commit_msg>convert to module tests instead of moduleFor<commit_after>import { module, test } from 'ember-qunit';
import sinon from 'sinon';
import EmberObject from '@ember/object';

module('amplitude adapter', function(hooks) {
  hooks.beforeEach(function () {
    this.sandbox = sinon.createSandbox();
    this.config = {
      apiKey: 'AMPLITUDE_KEY'
    };
    this.instanceStub = EmberObject.create({
      identify: sinon.fake(),
      setUserId: sinon.fake(),
      logEvent: sinon.fake(),
      setOptOut: sinon.fake()
    });
    this.identity = EmberObject.create();

    this.subject = this.owner.factoryFor('ember-metrics@metrics-adapter:amplitude').create({ config: this.config });
  });

  hooks.afterEach(function () {
    this.sandbox.restore();
  });

  test('#identify sets the distinct user ID, and calls amplitude with any extra user properties', function(assert) {

    this.sandbox.replace(window.amplitude, 'getInstance', () => this.instanceStub);
    this.sandbox.replace(window.amplitude, 'Identify', () => this.identity);

    this.adapter.identify({
      distinctId: '123',
      email: 'ben.simmons@sixers.net'
    });

    assert.ok(this.instanceStub.setUserId.calledWith('123'), 'it calls setUserId with distinctId');
    assert.ok(this.instanceStub.identify.calledWith(this.identity), 'it sends the correct user identity');
    assert.ok(this.instanceStub.logEvent.calledWith('Identify'), 'it calls a logEvent for "Identify"');

    assert.equal(this.identity.get('email'), 'ben.simmons@sixers.net', 'extra user properties are correctly assigned to the identity');
  });

  test('#trackEvent sends the correct request shape', function(assert) {
    this.sandbox.replace(window.amplitude, 'getInstance', () => this.instanceStub);

    this.adapter.trackEvent({
      event: 'Registered User',
      email: 'joel.embiid@sixers.net'
    });
    const expectedEventProperties = {
      email: 'joel.embiid@sixers.net'
    };

    assert.ok(this.instanceStub.logEvent.calledWith('Registered User', expectedEventProperties), 'track called with proper arguments');
  });

  test('#trackPage returns the correct response shape', function(assert) {
    this.sandbox.replace(window.amplitude, 'getInstance', () => this.instanceStub);

    const pageProperties = {
      url: '/shot-charts/missed-threes'
    };
    this.adapter.trackPage(pageProperties);

    assert.ok(this.instanceStub.logEvent.calledWith('Page View', pageProperties), 'track called with proper arguments');
  });

  test('#optOut calls amplitude optOut with false', function(assert) {
    this.sandbox.replace(window.amplitude, 'getInstance', () => this.instanceStub);

    this.adapter.optOut();

    assert.ok(this.instanceStub.setOptOut.calledWith(true), 'optOut called with correct arguments');
  });

  test('#optIn calls amplitude optOut with false', function(assert) {
    this.sandbox.replace(window.amplitude, 'getInstance', () => this.instanceStub);

    this.adapter.optIn();

    assert.ok(this.instanceStub.setOptOut.calledWith(false), 'optOut called with correct arguments');
  });
});

<|endoftext|>


<commit_before>import {isUndefined, extend} from 'lodash'
import {DragDropMixin} from 'react-dnd'
import * as Promise from 'bluebird'
import * as React from 'react/addons'
import {Link} from 'react-router'
import * as humanize from 'humanize-plus'
import * as Immutable from 'immutable'

import add from 'app/helpers/add'
import countCredits from 'app/helpers/countCredits'
import semesterName from 'app/helpers/semesterName'
import {isCurrentSemester} from 'app/helpers/isCurrent'
import {Course, MissingCourse, EmptyCourseSlot} from 'app/elements/course'
import studentActions from 'app/flux/studentActions'
import itemTypes from 'app/models/itemTypes'

let cx = React.addons.classSet

let Semester = React.createClass({
	mixins: [DragDropMixin],

	propTypes: {
		student: React.PropTypes.object.isRequired,
		year: React.PropTypes.number.isRequired,
		semester: React.PropTypes.number.isRequired,
	},

	configureDragDrop(registerType) {
		registerType(itemTypes.COURSE, {
			dropTarget: {
				acceptDrop(courseIdentifier) {
					console.log('dropped courseIdentifier', courseIdentifier)
					studentActions.addCourse(this.props.student.id, this.state.schedule.id, courseIdentifier.clbid)
				}
			}
		})
	},

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},

	componentWillReceiveProps(nextProps) {
		let activeSchedules = nextProps.student.activeSchedules
		let schedule = activeSchedules.find((s) => s.year === this.props.year && s.semester === this.props.semester)

		Promise.all([schedule.courses, schedule.validate()]).then((results) => {
			let [courses, validation] = results
			this.setState({
				schedule,
				courses: Immutable.List(courses),
				validation,
			})
		})
	},

	getInitialState() {
		return {
			courses: Immutable.List(),
			schedule: null,
			validation: {},
		}
	},

	render() {
		// console.log('semester render', this.state.schedule)

		let infoIcons = []
		if (this.state.schedule && this.state.courses.size) {
			let courseCount = this.state.courses.size
			infoIcons.push(React.createElement('li',
				{className: 'semester-course-count', key: 'course-count'},
				`${courseCount} ${humanize.pluralize(courseCount, 'course')}`))

			if (this.state.validation.hasConflict) {
				let conflicts = JSON.stringify(this.state.validation.conflicts, null, 2)
				infoIcons.push(React.createElement('li',
					{
						className: 'semester-status',
						key: 'semester-status',
						title: conflicts,
					},
					React.createElement('i', {className: 'semester-alert'})))
			}

			let credits = this.state.courses
				.filterNot(isUndefined) // remove any undefined items
				.map(c => c.credits)
				.reduce(add)

			if (credits) {
				infoIcons.push(React.createElement('li',
					{className: 'semester-credit-count', key: 'credit-count'},
					`${credits} ${humanize.pluralize(credits, 'credit')}`))
			}
		}
		let infoBar = React.createElement('ul', {className: 'info-bar'}, infoIcons)

		let courseList = null
		if (this.state.schedule && this.state.courses) {
			let courseObjects = this.state.courses
				.filterNot(isUndefined)
				.map((course, i) =>
					React.createElement(Course, {
						key: `${course.clbid}-${i}`,
						info: course,
						student: this.props.student,
						schedule: this.state.schedule,
						index: i,
						conflicts: this.state.validation.conflicts,
					}))

			let couldntFindSlots = this.state.courses
				.filter(isUndefined) // only keep the undefined items
				.map((c, i) => React.createElement(MissingCourse, {key: i}))

			// maxCredits is 4 for fall/spring and 1 for everything else
			let maxCredits = ([1, 3].indexOf(this.props.semester) !== -1) ? 4 : 1
			let emptySlotList = Immutable.Range(Math.floor(countCredits(this.state.courses)), maxCredits)
			let emptySlots = emptySlotList
				.skip(couldntFindSlots.size)
				.map((i) => React.createElement(EmptyCourseSlot, {key: `empty-${i}`}))

			let courseBlocks = courseObjects
				.concat(couldntFindSlots)
				.concat(emptySlots)
				.toJS()

			courseList = React.createElement('div',
				{className: 'course-list'},
				courseBlocks)
		}
		else if (this.state.schedule) {
			courseList = React.createElement('div', {className: 'loading'}, 'Loading Courses')
		}

		let droppableIsMoving = this.getDropState(itemTypes.COURSE).isDragging
		let droppableIsOver = this.getDropState(itemTypes.COURSE).isHovering

		let semesterProps = {
			className: cx({
				semester: true,
				'can-drop': droppableIsMoving,
				'is-over': droppableIsOver,
			})
		}

		return React.createElement('div',
			extend(semesterProps, this.dropTargetFor(itemTypes.COURSE)),
			React.createElement('header', {className: 'semester-title'},
				React.createElement('h1', null, React.createElement(Link,
					{
						to: 'semester',
						params: {
							id: this.props.student.id,
							year: this.props.year,
							semester: this.props.semester,
						},
					},
					semesterName(this.props.semester))),
				infoBar,
				React.createElement('button', {
					className: 'remove-semester',
					title: `Remove ${this.props.year} ${semesterName(this.props.semester)}`,
					onClick: this.removeSemester,
				})),
			courseList)
	},

	removeSemester() {
		let {year, semester} = this.props
		let currentTermSchedules = this.props.student.schedules.filter(isCurrentSemester(year, semester))

		let scheduleIds = currentTermSchedules.map(s => s.id)

		studentActions.destroyMultipleSchedules(this.props.student.id, scheduleIds)
	},
})

export default Semester
<commit_msg>Pass a native array to countCredits<commit_after>import {isUndefined, extend} from 'lodash'
import {DragDropMixin} from 'react-dnd'
import * as Promise from 'bluebird'
import * as React from 'react/addons'
import {Link} from 'react-router'
import * as humanize from 'humanize-plus'
import * as Immutable from 'immutable'

import add from 'app/helpers/add'
import countCredits from 'app/helpers/countCredits'
import semesterName from 'app/helpers/semesterName'
import {isCurrentSemester} from 'app/helpers/isCurrent'
import {Course, MissingCourse, EmptyCourseSlot} from 'app/elements/course'
import studentActions from 'app/flux/studentActions'
import itemTypes from 'app/models/itemTypes'

let cx = React.addons.classSet

let Semester = React.createClass({
	mixins: [DragDropMixin],

	propTypes: {
		student: React.PropTypes.object.isRequired,
		year: React.PropTypes.number.isRequired,
		semester: React.PropTypes.number.isRequired,
	},

	configureDragDrop(registerType) {
		registerType(itemTypes.COURSE, {
			dropTarget: {
				acceptDrop(courseIdentifier) {
					console.log('dropped courseIdentifier', courseIdentifier)
					studentActions.addCourse(this.props.student.id, this.state.schedule.id, courseIdentifier.clbid)
				}
			}
		})
	},

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},

	componentWillReceiveProps(nextProps) {
		let activeSchedules = nextProps.student.activeSchedules
		let schedule = activeSchedules.find((s) => s.year === this.props.year && s.semester === this.props.semester)

		Promise.all([schedule.courses, schedule.validate()]).then((results) => {
			let [courses, validation] = results
			this.setState({
				schedule,
				courses: Immutable.List(courses),
				validation,
			})
		})
	},

	getInitialState() {
		return {
			courses: Immutable.List(),
			schedule: null,
			validation: {},
		}
	},

	render() {
		// console.log('semester render', this.state.schedule)

		let infoIcons = []
		if (this.state.schedule && this.state.courses.size) {
			let courseCount = this.state.courses.size
			infoIcons.push(React.createElement('li',
				{className: 'semester-course-count', key: 'course-count'},
				`${courseCount} ${humanize.pluralize(courseCount, 'course')}`))

			if (this.state.validation.hasConflict) {
				let conflicts = JSON.stringify(this.state.validation.conflicts, null, 2)
				infoIcons.push(React.createElement('li',
					{
						className: 'semester-status',
						key: 'semester-status',
						title: conflicts,
					},
					React.createElement('i', {className: 'semester-alert'})))
			}

			let credits = this.state.courses
				.filterNot(isUndefined) // remove any undefined items
				.map(c => c.credits)
				.reduce(add)

			if (credits) {
				infoIcons.push(React.createElement('li',
					{className: 'semester-credit-count', key: 'credit-count'},
					`${credits} ${humanize.pluralize(credits, 'credit')}`))
			}
		}
		let infoBar = React.createElement('ul', {className: 'info-bar'}, infoIcons)

		let courseList = null
		if (this.state.schedule && this.state.courses) {
			let courseObjects = this.state.courses
				.filterNot(isUndefined)
				.map((course, i) =>
					React.createElement(Course, {
						key: `${course.clbid}-${i}`,
						info: course,
						student: this.props.student,
						schedule: this.state.schedule,
						index: i,
						conflicts: this.state.validation.conflicts,
					}))

			let couldntFindSlots = this.state.courses
				.filter(isUndefined) // only keep the undefined items
				.map((c, i) => React.createElement(MissingCourse, {key: i}))

			// maxCredits is 4 for fall/spring and 1 for everything else
			let maxCredits = ([1, 3].indexOf(this.props.semester) !== -1) ? 4 : 1
			let emptySlotList = Immutable.Range(Math.floor(countCredits(this.state.courses.toArray())), maxCredits)
			let emptySlots = emptySlotList
				.skip(couldntFindSlots.size)
				.map((i) => React.createElement(EmptyCourseSlot, {key: `empty-${i}`}))

			let courseBlocks = courseObjects
				.concat(couldntFindSlots)
				.concat(emptySlots)
				.toJS()

			courseList = React.createElement('div',
				{className: 'course-list'},
				courseBlocks)
		}
		else if (this.state.schedule) {
			courseList = React.createElement('div', {className: 'loading'}, 'Loading Courses')
		}

		let droppableIsMoving = this.getDropState(itemTypes.COURSE).isDragging
		let droppableIsOver = this.getDropState(itemTypes.COURSE).isHovering

		let semesterProps = {
			className: cx({
				semester: true,
				'can-drop': droppableIsMoving,
				'is-over': droppableIsOver,
			})
		}

		return React.createElement('div',
			extend(semesterProps, this.dropTargetFor(itemTypes.COURSE)),
			React.createElement('header', {className: 'semester-title'},
				React.createElement('h1', null, React.createElement(Link,
					{
						to: 'semester',
						params: {
							id: this.props.student.id,
							year: this.props.year,
							semester: this.props.semester,
						},
					},
					semesterName(this.props.semester))),
				infoBar,
				React.createElement('button', {
					className: 'remove-semester',
					title: `Remove ${this.props.year} ${semesterName(this.props.semester)}`,
					onClick: this.removeSemester,
				})),
			courseList)
	},

	removeSemester() {
		let {year, semester} = this.props
		let currentTermSchedules = this.props.student.schedules.filter(isCurrentSemester(year, semester))

		let scheduleIds = currentTermSchedules.map(s => s.id)

		studentActions.destroyMultipleSchedules(this.props.student.id, scheduleIds)
	},
})

export default Semester
<|endoftext|>


<commit_before>angular.module('myApp.feedback', ['ngRoute'])

  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/feedback', {
      templateUrl: 'feedback/feedback.html',
      controller: 'FeedbackController'
    });
  }])

  /**
   * The feedback page allows users to leave feedback on a number of questions regarding
   * the application's different pages as well as general user information.
   */
  .controller('FeedbackController', ['$scope', 'ResourcesService', 'FeedbackSubmitService', 'FeedbackService',
    function ($scope, ResourcesService, FeedbackSubmitService, FeedbackService) {

      /**
       * Whenever a user answers a question by clicking a button with a rating
       * @param question The question being answered
       * @param rating The rating chosen
       */
      $scope.buttonClick = function (question, rating) {
        question.selected = rating;
        var feedback = {questionID: question.id, rating: rating};
        FeedbackService.saveFeedback(question.id, rating);
        FeedbackSubmitService.submitFeedback(feedback);
      };

      /**
       * Whenever the user answers a question by selecting an item in a selectlist
       * @param question The question being answered
       * @param option The option selected
       */
      $scope.selectedOption = function (question, option) {
        question.selected = option;
        var feedback = {questionID: question.id, comment: option.text};
        FeedbackService.saveFeedback(question.id, option);
        FeedbackSubmitService.submitFeedback(feedback);
      };

      /**
       * Whenever the user has finished writing a comment
       * @param sectionName The name of the section for the comment
       * @param text The comment
       */
      $scope.writtenComment = function (sectionName, text) {
        if (text.length > 1500) { // Disregard text after 1500 characters (very likely spam or garbage input)
          text = text.substring(0, 1500);
        }
        var feedback = {questionID: sectionName, comment: text};
        FeedbackService.saveFeedback(sectionName, text);
        FeedbackSubmitService.submitFeedback(feedback);
      };

      // Initialize values of buttons
      $scope.buttons = [{val: 1}, {val: 2}, {val: 3}, {val: 4}, {val: 5}, {val: 6}, {val: 7}, {val: 8}, {val: 9}];

      // Fetch and initialize the evaluation sections
      ResourcesService.Feedback.query().$promise.then(function (data) {
        // Load previously selected ratings for the questions
        var prevFeedback = FeedbackService.getFeedback();
        for (var i = 0; i < data.length; i++) {
          var comment = prevFeedback[data[i].sectionName]; // Exists if a user has input a comment for this section
          if (comment) {
            data[i].comment = comment;
          }

          for (var j = 0; j < data[i].questions.length; j++) {
            var answer = prevFeedback[data[i].questions[j].id]; // Exists if user previously answered question
            if (answer) {
              data[i].questions[j].selected = answer;
            }
          }
        }
        $scope.evaluations = data;
      }, function (err) {
        throw "No feedback was returned by query: " + err;
      });

    }]);<commit_msg>Now also submits data on how many times a user has requested songs in each section. Also fixed an issue with unselecting an answer.<commit_after>angular.module('myApp.feedback', ['ngRoute'])

  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/feedback', {
      templateUrl: 'feedback/feedback.html',
      controller: 'FeedbackController'
    });
  }])

  /**
   * The feedback page allows users to leave feedback on a number of questions regarding
   * the application's different pages as well as general user information.
   */
  .controller('FeedbackController', ['$scope', 'ResourcesService', 'FeedbackSubmitService', 'FeedbackService', 'EmotionsService','PlaneService','SlidersService',
    function ($scope, ResourcesService, FeedbackSubmitService, FeedbackService, EmotionsService, PlaneService, SlidersService) {

      /**
       * Whenever a user answers a question by clicking a button with a rating
       * @param question The question being answered
       * @param rating The rating chosen
       */
      $scope.buttonClick = function (question, rating) {
        question.selected = rating;
        var feedback = {questionID: question.id, rating: rating};
        FeedbackService.saveFeedback(question.id, rating);
        FeedbackSubmitService.submitFeedback(feedback);
      };

      /**
       * Whenever the user answers a question by selecting an item in a selectlist
       * @param question The question being answered
       * @param option The option selected
       */
      $scope.selectedOption = function (question, option) {
        console.log("test1");
        question.selected = option;
        console.log("test");
        var feedback;
        if(option !== null){
          feedback = {questionID: question.id, comment: option.text};
        }
        else{
          feedback = {questionID: question.id, comment: null};
        }

        FeedbackService.saveFeedback(question.id, option);
        FeedbackSubmitService.submitFeedback(feedback);
      };

      /**
       * Submits how many times the user has requested songs for each section
       */
      var submitPlayTimes = function(){
        // Get and submit the amount of times songs have been requested for emotion section
        var emotionsTimes = EmotionsService.getSavedValues().playTimes;
        var emotionsFeedback = {questionID: "emotionsTimes", rating:emotionsTimes};
        FeedbackSubmitService.submitFeedback(emotionsFeedback);

        // Get and submit the amount of times songs have been requested for plane section
        var planeTimes = PlaneService.getSavedValues().playTimes;
        var planeFeedback = {questionID: "planeTimes", rating:planeTimes};
        FeedbackSubmitService.submitFeedback(planeFeedback);

        // Get and submit the amount of times songs have been requested for sliders section
        var slidersTimes = SlidersService.getSavedValues().playTimes;
        var slidersFeedback = {questionID: "slidersTimes", rating:slidersTimes};
        FeedbackSubmitService.submitFeedback(slidersFeedback);

      };

      /**
       * Whenever the user has finished writing a comment
       * @param sectionName The name of the section for the comment
       * @param text The comment
       */
      $scope.writtenComment = function (sectionName, text) {
        if (text.length > 1500) { // Disregard text after 1500 characters (very likely spam or garbage input)
          text = text.substring(0, 1500);
        }
        var feedback = {questionID: sectionName, comment: text};
        FeedbackService.saveFeedback(sectionName, text);
        FeedbackSubmitService.submitFeedback(feedback);
      };

      // Initialize values of buttons
      $scope.buttons = [{val: 1}, {val: 2}, {val: 3}, {val: 4}, {val: 5}, {val: 6}, {val: 7}, {val: 8}, {val: 9}];

      // Fetch and initialize the evaluation sections
      ResourcesService.Feedback.query().$promise.then(function (data) {
        // Load previously selected ratings for the questions
        var prevFeedback = FeedbackService.getFeedback();
        for (var i = 0; i < data.length; i++) {
          var comment = prevFeedback[data[i].sectionName]; // Exists if a user has input a comment for this section
          if (comment) {
            data[i].comment = comment;
          }

          for (var j = 0; j < data[i].questions.length; j++) {
            var answer = prevFeedback[data[i].questions[j].id]; // Exists if user previously answered question
            if (answer) {
              data[i].questions[j].selected = answer;
            }
          }
        }
        $scope.evaluations = data;
        submitPlayTimes(); // Update how many times user has requested songs from sections
      }, function (err) {
        throw "No feedback was returned by query: " + err;
      });

    }]);<|endoftext|>


<commit_before>$(document).ready(function() {
        $('#versions').bind('change', function() {
                var checked = 1;
                if (!this.checked) {
                        checked = 0;
                }
                $.post(OC.filePath('files_versions','ajax','togglesettings.php'), 'versions='+checked);
        });
});

$(document).ready(function(){
	if (typeof FileActions !== 'undefined') {
		// Add history button to files/index.php
		FileActions.register('file','History',function(){return OC.imagePath('core','actions/history')},function(filename){

			if (scanFiles.scanning){return;}//workaround to prevent additional http request block scanning feedback

			var file = $('#dir').val()+'/'+filename;

			createVersionsDropdown(filename, file)

		});
	}
});

function createVersionsDropdown(filename, files) {

	var historyUrl = OC.linkTo('files_versions', 'history.php') + '?path='+encodeURIComponent( $( '#dir' ).val() ).replace( /%2F/g, '/' )+'/'+encodeURIComponent( filename );

	var html = '
';
	html += '
';
	html += '<select data-placeholder="Saved versions" id="found_versions" class="chzen-select">';
	html += '<option value=""></option>';
	html += '</select>';
	html += '
';
	//html += '<input type="button" value="Revert file" onclick="revertFile()" />';
	html += '<input type="button" value="All versions..." onclick="window.location=\''+historyUrl+'\'" name="makelink" id="makelink" />';
	html += '
';
	html += '<input id="link" style="display:none; width:90%;" />';

	if (filename) {
		$('tr').filterAttr('data-file',filename).addClass('mouseOver');
		$(html).appendTo($('tr').filterAttr('data-file',filename).find('td.filename'));
	} else {
		$(html).appendTo($('thead .share'));
	}

	$.ajax({
		type: 'GET',
		url: OC.filePath('files_versions', 'ajax', 'getVersions.php'),
		dataType: 'json',
		data: { source: files },
		async: false,
		success: function( versions ) {

			//alert("helo "+OC.linkTo('files_versions', 'ajax/getVersions.php'));

			if (versions) {

				$.each( versions, function(index, row ) {
					addVersion( row );
				});

			}
			$('#found_versions').change(function(){
				var revision=parseInt($(this).val());
				revertFile(files,revision);
			})
		}
	});

	function revertFile(file, revision) {

		$.ajax({
			type: 'GET',
			url: OC.linkTo('files_versions', 'ajax/rollbackVersion.php'),
			dataType: 'json',
			data: {file: file, revision: revision},
			async: false,
			success: function(response) {
				if (response.status=='error') {
					OC.dialogs.alert('Failed to revert '+file+' to revision '+formatDate(revision*1000)+'.','Failed to revert');
				} else {
					$('#dropdown').hide('blind', function() {
						$('#dropdown').remove();
						$('tr').removeClass('mouseOver');
						// TODO also update the modified time in the web ui
					});
				}
			}
		});

	}

	function addVersion(revision ) {
		name=formatDate(revision*1000);
		var version=$('<option/>');
		version.attr('value',revision);
		version.text(name);

// 		} else {
// 			var checked = ((permissions > 0) ? 'checked="checked"' : 'style="display:none;"');
// 			var style = ((permissions == 0) ? 'style="display:none;"' : '');
// 			var user = '
';
// 			user += '';
// 			user += uid_shared_with;
// 			user += '<input type="checkbox" name="permissions" id="'+uid_shared_with+'" class="permissions" '+checked+' />';
// 			user += 'can edit';
// 			user += '
';
// 		}

		version.appendTo('#found_versions');
	}

	$('#dropdown').show('blind');
	$('#found_versions').chosen();

}
<commit_msg>Don't show the select form in the history dropdown if a file has no other versions<commit_after>$(document).ready(function() {
        $('#versions').bind('change', function() {
                var checked = 1;
                if (!this.checked) {
                        checked = 0;
                }
                $.post(OC.filePath('files_versions','ajax','togglesettings.php'), 'versions='+checked);
        });
});

$(document).ready(function(){
	if (typeof FileActions !== 'undefined') {
		// Add history button to files/index.php
		FileActions.register('file','History',function(){return OC.imagePath('core','actions/history')},function(filename){

			if (scanFiles.scanning){return;}//workaround to prevent additional http request block scanning feedback

			var file = $('#dir').val()+'/'+filename;

			createVersionsDropdown(filename, file)

		});
	}
});

function createVersionsDropdown(filename, files) {

	var historyUrl = OC.linkTo('files_versions', 'history.php') + '?path='+encodeURIComponent( $( '#dir' ).val() ).replace( /%2F/g, '/' )+'/'+encodeURIComponent( filename );

	var html = '
';
	html += '
';
	html += '<select data-placeholder="Saved versions" id="found_versions" class="chzen-select" style="width:16em;">';
	html += '<option value=""></option>';
	html += '</select>';
	html += '
';
	//html += '<input type="button" value="Revert file" onclick="revertFile()" />';
	html += '<input type="button" value="All versions..." onclick="window.location=\''+historyUrl+'\'" name="makelink" id="makelink" />';
	html += '<input id="link" style="display:none; width:90%;" />';

	if (filename) {
		$('tr').filterAttr('data-file',filename).addClass('mouseOver');
		$(html).appendTo($('tr').filterAttr('data-file',filename).find('td.filename'));
	} else {
		$(html).appendTo($('thead .share'));
	}

	$.ajax({
		type: 'GET',
		url: OC.filePath('files_versions', 'ajax', 'getVersions.php'),
		dataType: 'json',
		data: { source: files },
		async: false,
		success: function( versions ) {

			//alert("helo "+OC.linkTo('files_versions', 'ajax/getVersions.php'));

			if (versions) {
				$.each( versions, function(index, row ) {
					addVersion( row );
				});
				$('#found_versions').chosen();
			} else {
				$('#found_versions').hide();
				$('#makelink').hide();
				$('
No other versions available
').appendTo('#dropdown');
			}
			$('#found_versions').change(function(){
				var revision=parseInt($(this).val());
				revertFile(files,revision);
			})
		}
	});

	function revertFile(file, revision) {

		$.ajax({
			type: 'GET',
			url: OC.linkTo('files_versions', 'ajax/rollbackVersion.php'),
			dataType: 'json',
			data: {file: file, revision: revision},
			async: false,
			success: function(response) {
				if (response.status=='error') {
					OC.dialogs.alert('Failed to revert '+file+' to revision '+formatDate(revision*1000)+'.','Failed to revert');
				} else {
					$('#dropdown').hide('blind', function() {
						$('#dropdown').remove();
						$('tr').removeClass('mouseOver');
						// TODO also update the modified time in the web ui
					});
				}
			}
		});

	}

	function addVersion(revision ) {
		name=formatDate(revision*1000);
		var version=$('<option/>');
		version.attr('value',revision);
		version.text(name);

// 		} else {
// 			var checked = ((permissions > 0) ? 'checked="checked"' : 'style="display:none;"');
// 			var style = ((permissions == 0) ? 'style="display:none;"' : '');
// 			var user = '
';
// 			user += '';
// 			user += uid_shared_with;
// 			user += '<input type="checkbox" name="permissions" id="'+uid_shared_with+'" class="permissions" '+checked+' />';
// 			user += 'can edit';
// 			user += '
';
// 		}

		version.appendTo('#found_versions');
	}

	$('#dropdown').show('blind');

}
<|endoftext|>


<commit_before>// :doc:
// This module exports the query string in browser.
//
// Example::
//
//    import query from 'bemuse/utils/query'
//    alert(query.mode)

import querystring from 'querystring'
export default querystring.parse(location.search.replace(/^\?/, ''))
<commit_msg>Replace with URLSearchParams<commit_after>// :doc:
// This module exports the query string in browser.
//
// Example::
//
//    import query from 'bemuse/utils/query'
//    alert(query.mode)

export default Object.fromEntries(
  new URLSearchParams(location.search).entries()
)
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2011 OpenMFG LLC, d/b/a xTuple
// ==========================================================================
/*globals global Postbooks XM XT sc_assert */

Postbooks.SUBMODULE = SC.State.design({

  className: null,
  title: null,

  didCommit: false,

  enterState: function() {
    sc_assert(Postbooks.store.isNested, "Postbooks.store should be nested before entering a submodule.");
    sc_assert(Postbooks.submoduleController, "Postbooks.submoduleController should be set before entering a submodule.");

    var className = this.get('className'),
        title = this.get('title');

    sc_assert(className !== null, "You must set a className property in your Postbooks.SUBMODULE subclass.");
    sc_assert(typeof className === 'string', "className must be a string in your Postbooks.SUBMODULE subclass.");
    sc_assert(title !== null, "You must set a title property in your Postbooks.SUBMODULE subclass.");
    sc_assert(typeof title === 'string', "title must be a string in your Postbooks.SUBMODULE subclass.");
    sc_assert(title[0] === '_', "title must be an unlocalized string (beginning with an underscore) in your Postbooks.SUBMODULE subclass.");

    this.didCommit = false;
    Postbooks.LoadSubmodule(className, title.loc());
  },

  exitState: function() {
    sc_assert(!Postbooks.store.isNested, "Postbooks.store should NOT be nested when exiting a submodule.");

    Postbooks.submoduleController = null;
    SC.app.get('ui').popSurface();
  },

  // ACTIONS

  showDashboard: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.DASHBOARD)) return;
    else this.back('DASHBOARD');
  },

  showCRM: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.CRM)) return;
    else this.back('CRM');
  },

  showBilling: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.BILLING)) return;
    else this.back('BILLING');
  },

  showPayments: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.PAYMENTS)) return;
    else this.back('PAYMENTS');
  },

  showLedger: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.LEDGER)) return;
    else this.back('LEDGER');
  },

  back: function(stateName) {
    SC.EndEditingTextLayer();
    if (Postbooks.getPath('store.hasChanges')) {
      var save;
      if (Postbooks.submoduleController.get('status') === SC.Record.READY_NEW) {
        save = window.confirm("_unsavedRecord".loc());
      } else {
        save = window.confirm("_unsavedChanges".loc());
      }
      if (!save) {
        // Subtle: We may need to re-establish our module's route.
        SC.routes.set('location', this.parentState.get('route'));
        return;
      } else {
        Postbooks.get('store').commitChanges(true); // force
      }
    }

    Postbooks.get('store').destroy();
    Postbooks.set('store', XT.store); // Required before we exit.

    // Push our changes to the server.
    if (this.didCommit) {
      console.log('Committing changes to the server.');
      XT.store.commitRecords();
    }

    if (typeof stateName === 'string') {
      this.gotoState(stateName);
    } else {
      // HACK: SC.Statechart will exit/enter our parent state!
      this.parentState.__movingUp__ = true;

      this.gotoState(this.parentState);
    }
  },

  apply: function() {
    SC.EndEditingTextLayer();
    Postbooks.get('store').commitChanges(true); // force
    this.didCommit = true;
  },

  cancel: function() {
    SC.EndEditingTextLayer();

    // If we're working on a new record, just clean up and exit.
    if (Postbooks.submoduleController.get('status') === SC.Record.READY_NEW) {
      Postbooks.get('store').destroy();
      Postbooks.set('store', XT.store); // Required before we exit.

      // HACK: SC.Statechart will exit/enter our parent state!
      this.parentState.__movingUp__ = true;

      this.gotoState(this.parentState);
    } else {
      Postbooks.get('store').discardChanges();
    }
  },

  newRecord: function(sender) {
    var listController = sender.listController,
        firstObject = listController.get('selection').firstObject(),
        klass = firstObject? firstObject.klass : null;

    if (klass) {
      var instance = Postbooks.get('store').createRecord(klass, {});
      Postbooks.submoduleController.get(firstObject.attribute).pushObject(instance);
      Postbooks.LoadModal(klass.prototype.className.slice(3), "_back".loc(), instance);
    }
  },

  deleteRecord: function() {
    SC.EndEditingTextLayer();

    if (window.confirm("_deleteRecord".loc())) {

      // If we're working on a new record, just clean up and exit.
      if (Postbooks.submoduleController.get('status') === SC.Record.READY_NEW) {
        Postbooks.get('store').destroy();
        Postbooks.set('store', XT.store); // Required before we exit.

      } else {
        Postbooks.submoduleController.get('content').destroy();
        Postbooks.get('store').commitChanges(true); // force
        this.didCommit = true;

        Postbooks.get('store').destroy();
        Postbooks.set('store', XT.store); // Required before we exit.
      }

      // Push our changes to the server.
      if (this.didCommit) {
        console.log('Committing changes to the server.');
        XT.store.commitRecords();
      }

      // HACK: SC.Statechart will exit/enter our parent state!
      this.parentState.__movingUp__ = true;
      this.gotoState(this.parentState);
    }
  }

  // SUBSTATES

});
<commit_msg>Commit applied changes to server immediately. Also make sure to commit changes to server confirmed on exit of window.<commit_after>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2011 OpenMFG LLC, d/b/a xTuple
// ==========================================================================
/*globals global Postbooks XM XT sc_assert */

Postbooks.SUBMODULE = SC.State.design({

  className: null,
  title: null,

  didCommit: false,

  enterState: function() {
    sc_assert(Postbooks.store.isNested, "Postbooks.store should be nested before entering a submodule.");
    sc_assert(Postbooks.submoduleController, "Postbooks.submoduleController should be set before entering a submodule.");

    var className = this.get('className'),
        title = this.get('title');

    sc_assert(className !== null, "You must set a className property in your Postbooks.SUBMODULE subclass.");
    sc_assert(typeof className === 'string', "className must be a string in your Postbooks.SUBMODULE subclass.");
    sc_assert(title !== null, "You must set a title property in your Postbooks.SUBMODULE subclass.");
    sc_assert(typeof title === 'string', "title must be a string in your Postbooks.SUBMODULE subclass.");
    sc_assert(title[0] === '_', "title must be an unlocalized string (beginning with an underscore) in your Postbooks.SUBMODULE subclass.");

    this.didCommit = false;
    Postbooks.LoadSubmodule(className, title.loc());
  },

  exitState: function() {
    sc_assert(!Postbooks.store.isNested, "Postbooks.store should NOT be nested when exiting a submodule.");

    Postbooks.submoduleController = null;
    SC.app.get('ui').popSurface();
  },

  // ACTIONS

  showDashboard: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.DASHBOARD)) return;
    else this.back('DASHBOARD');
  },

  showCRM: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.CRM)) return;
    else this.back('CRM');
  },

  showBilling: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.BILLING)) return;
    else this.back('BILLING');
  },

  showPayments: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.PAYMENTS)) return;
    else this.back('PAYMENTS');
  },

  showLedger: function() {
    if (Postbooks.statechart.stateIsEntered(Postbooks.statechart.rootState.APPLICATION.LEDGER)) return;
    else this.back('LEDGER');
  },

  back: function(stateName) {
    SC.EndEditingTextLayer();
    if (Postbooks.getPath('store.hasChanges')) {
      var save;
      if (Postbooks.submoduleController.get('status') === SC.Record.READY_NEW) {
        save = window.confirm("_unsavedRecord".loc());
      } else {
        save = window.confirm("_unsavedChanges".loc());
      }
      if (!save) {
        // Subtle: We may need to re-establish our module's route.
        SC.routes.set('location', this.parentState.get('route'));
        return;
      } else {
        Postbooks.get('store').commitChanges(true); // force
        this.didCommit = true;
      }
    }

    Postbooks.get('store').destroy();
    Postbooks.set('store', XT.store); // Required before we exit.

    // Push our changes to the server.
    if (this.didCommit) {
      console.log('Committing changes to the server.');
      XT.store.commitRecords();
    }

    if (typeof stateName === 'string') {
      this.gotoState(stateName);
    } else {
      // HACK: SC.Statechart will exit/enter our parent state!
      this.parentState.__movingUp__ = true;

      this.gotoState(this.parentState);
    }
  },

  apply: function() {
    SC.EndEditingTextLayer();
    Postbooks.get('store').commitChanges(true); // force
    XT.store.commitRecords();
  },

  cancel: function() {
    SC.EndEditingTextLayer();

    // If we're working on a new record, just clean up and exit.
    if (Postbooks.submoduleController.get('status') === SC.Record.READY_NEW) {
      Postbooks.get('store').destroy();
      Postbooks.set('store', XT.store); // Required before we exit.

      // HACK: SC.Statechart will exit/enter our parent state!
      this.parentState.__movingUp__ = true;

      this.gotoState(this.parentState);
    } else {
      Postbooks.get('store').discardChanges();
    }
  },

  newRecord: function(sender) {
    var listController = sender.listController,
        firstObject = listController.get('selection').firstObject(),
        klass = firstObject? firstObject.klass : null;

    if (klass) {
      var instance = Postbooks.get('store').createRecord(klass, {});
      Postbooks.submoduleController.get(firstObject.attribute).pushObject(instance);
      Postbooks.LoadModal(klass.prototype.className.slice(3), "_back".loc(), instance);
    }
  },

  deleteRecord: function() {
    SC.EndEditingTextLayer();

    if (window.confirm("_deleteRecord".loc())) {

      // If we're working on a new record, just clean up and exit.
      if (Postbooks.submoduleController.get('status') === SC.Record.READY_NEW) {
        Postbooks.get('store').destroy();
        Postbooks.set('store', XT.store); // Required before we exit.

      } else {
        Postbooks.submoduleController.get('content').destroy();
        Postbooks.get('store').commitChanges(true); // force
        this.didCommit = true;

        Postbooks.get('store').destroy();
        Postbooks.set('store', XT.store); // Required before we exit.
      }

      // Push our changes to the server.
      if (this.didCommit) {
        console.log('Committing changes to the server.');
        XT.store.commitRecords();
      }

      // HACK: SC.Statechart will exit/enter our parent state!
      this.parentState.__movingUp__ = true;
      this.gotoState(this.parentState);
    }
  }

  // SUBSTATES

});
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var parseArgs = require('minimist');
var argv = parseArgs(process.argv.slice(2), {
    alias: {
        m: multiplicity,
        c: numClients,
        r: numRequests
    }
});
var multiplicity = parseInt(argv.multiplicity, 10) || 2;
var numClients = parseInt(argv.numClients, 10) || 5;
var numRequests = parseInt(argv.numRequests, 10) || 20000;

var TChannel = require("../index"),
    metrics = require("metrics"),
    tests = [],
    client_options = {
        return_buffers: false
    },
    small_str, large_str, small_buf, large_buf;

function Test(args) {
    this.args = args;

    this.arg1 = new Buffer(args.command);
    this.arg2 = args.args ? new Buffer(args.args) : null;
    this.arg3 = null;

    this.callback = null;
    this.clients = [];
    this.clients_ready = 0;
    this.commands_sent = 0;
    this.commands_completed = 0;
    this.max_pipeline = this.args.pipeline || numRequests;
    this.client_options = args.client_options || client_options;

    this.connect_latency = new metrics.Histogram();
    this.ready_latency = new metrics.Histogram();
    this.command_latency = new metrics.Histogram();
}

Test.prototype.copy = function () {
    return new Test(this.args);
};

Test.prototype.run = function (callback) {
    var i;

    this.callback = callback;

    for (i = 0; i < numClients ; i++) {
        this.new_client(i);
    }
};

Test.prototype.new_client = function (id) {
    var self = this, new_client;

    var port = 4041 + id;
    new_client = new TChannel();
    new_client.create_time = Date.now();
    new_client.listen(port, "127.0.0.1", function (err) {
        // sending a ping to pre-connect the socket
        new_client
            .request({host: '127.0.0.1:4040'}, noop)
            .send('ping', null, null);

        new_client.on("identified", function (peer) {
            self.connect_latency.update(Date.now() - new_client.create_time);
            self.ready_latency.update(Date.now() - new_client.create_time);
            self.clients_ready++;
            if (self.clients_ready === self.clients.length) {
                self.on_clients_ready();
            }
        });

        self.clients[id] = new_client;
    });
};

Test.prototype.on_clients_ready = function () {
    this.test_start = Date.now();
    this.fill_pipeline();
};

Test.prototype.fill_pipeline = function () {
    var pipeline = this.commands_sent - this.commands_completed;

    while (this.commands_sent < numRequests && pipeline < this.max_pipeline) {
        this.commands_sent++;
        pipeline++;
        this.send_next();
    }

    if (this.commands_completed === numRequests) {
        this.print_stats();
        this.stop_clients();
    }
};

Test.prototype.stop_clients = function () {
    var self = this;

    this.clients.forEach(function (client, pos) {
        if (pos === self.clients.length - 1) {
            client.quit(function (err, res) {
                self.callback();
            });
        } else {
            client.quit();
        }
    });
};

Test.prototype.send_next = function () {
    var self = this,
        cur_client = this.commands_sent % this.clients.length,
        start = Date.now();

    this.clients[cur_client]
        .request({
            host: '127.0.0.1:4040',
            timeout: 10000,
            service: 'benchmark',
            headers: {
                benchHeader1: 'bench value one',
                benchHeader2: 'bench value two',
                benchHeader3: 'bench value three'
            }
        }, done)
        .send(this.arg1, this.arg2, this.arg3);

    function done(err, res1, res2) {
        if (err) {
            throw err;
        }
        self.commands_completed++;
        self.command_latency.update(Date.now() - start);
        self.fill_pipeline();
    }
};

Test.prototype.get_stats = function () {
    var obj = this.command_latency.printObj();
    obj.descr = this.args.descr;
    obj.pipeline = this.args.pipeline;
    obj.numClients = this.clients_ready;
    obj.elapsed = Date.now() - this.test_start;
    obj.rate = numRequests / (obj.elapsed / 1000);
    return obj;
};

Test.prototype.print_stats = function () {
    var obj = this.get_stats();
    process.stdout.write(JSON.stringify(obj) + "\n");
};

small_str = "1234";
small_buf = new Buffer(small_str);
large_str = (new Array(4097).join("-"));
large_buf = new Buffer(large_str);
var small_str_set = JSON.stringify(['foo_rand000000000000', small_str]);
var small_buf_set = new Buffer(small_str_set);
var large_str_set = JSON.stringify(['foo_rand000000000001', large_str]);
var large_buf_set = new Buffer(large_str_set);

tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 1}));
tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 50}));
tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 200}));
tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 20000}));

tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 1}));
tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 50}));
tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 200}));
tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 20000}));

tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 1}));
tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 50}));
tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 200}));
tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 20000}));

tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 1}));
tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 50}));
tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 200}));
tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 20000}));

tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 1}));
tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 50}));
tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 200}));
tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 20000}));

tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 1}));
tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 50}));
tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 200}));
tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 20000}));

tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 1}));
tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 50}));
tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 200}));
tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 20000}));

function next(i, j, done) {
    if (i >= tests.length) return done();
    if (j >= multiplicity) return next(i+1, 0, done);
    var test = tests[i].copy();
    test.run(function () {
        next(i, j+1, done);
    });
}

next(0, 0, function() {
    process.exit(0);
});

function noop() {
}
<commit_msg>Udpate benchmark for new send api<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var parseArgs = require('minimist');
var argv = parseArgs(process.argv.slice(2), {
    alias: {
        m: multiplicity,
        c: numClients,
        r: numRequests
    }
});
var multiplicity = parseInt(argv.multiplicity, 10) || 2;
var numClients = parseInt(argv.numClients, 10) || 5;
var numRequests = parseInt(argv.numRequests, 10) || 20000;

var TChannel = require("../index"),
    metrics = require("metrics"),
    tests = [],
    client_options = {
        return_buffers: false
    },
    small_str, large_str, small_buf, large_buf;

function Test(args) {
    this.args = args;

    this.arg1 = new Buffer(args.command);
    this.arg2 = args.args ? new Buffer(args.args) : null;
    this.arg3 = null;

    this.callback = null;
    this.clients = [];
    this.clients_ready = 0;
    this.commands_sent = 0;
    this.commands_completed = 0;
    this.max_pipeline = this.args.pipeline || numRequests;
    this.client_options = args.client_options || client_options;

    this.connect_latency = new metrics.Histogram();
    this.ready_latency = new metrics.Histogram();
    this.command_latency = new metrics.Histogram();
}

Test.prototype.copy = function () {
    return new Test(this.args);
};

Test.prototype.run = function (callback) {
    var i;

    this.callback = callback;

    for (i = 0; i < numClients ; i++) {
        this.new_client(i);
    }
};

Test.prototype.new_client = function (id) {
    var self = this, new_client;

    var port = 4041 + id;
    new_client = new TChannel();
    new_client.create_time = Date.now();
    new_client.listen(port, "127.0.0.1", function (err) {
        // sending a ping to pre-connect the socket
        new_client
            .request({host: '127.0.0.1:4040'})
            .send('ping', null, null);

        new_client.on("identified", function (peer) {
            self.connect_latency.update(Date.now() - new_client.create_time);
            self.ready_latency.update(Date.now() - new_client.create_time);
            self.clients_ready++;
            if (self.clients_ready === self.clients.length) {
                self.on_clients_ready();
            }
        });

        self.clients[id] = new_client;
    });
};

Test.prototype.on_clients_ready = function () {
    this.test_start = Date.now();
    this.fill_pipeline();
};

Test.prototype.fill_pipeline = function () {
    var pipeline = this.commands_sent - this.commands_completed;

    while (this.commands_sent < numRequests && pipeline < this.max_pipeline) {
        this.commands_sent++;
        pipeline++;
        this.send_next();
    }

    if (this.commands_completed === numRequests) {
        this.print_stats();
        this.stop_clients();
    }
};

Test.prototype.stop_clients = function () {
    var self = this;

    this.clients.forEach(function (client, pos) {
        if (pos === self.clients.length - 1) {
            client.quit(function (err, res) {
                self.callback();
            });
        } else {
            client.quit();
        }
    });
};

Test.prototype.send_next = function () {
    var self = this,
        cur_client = this.commands_sent % this.clients.length,
        start = Date.now();

    this.clients[cur_client]
        .request({
            host: '127.0.0.1:4040',
            timeout: 10000,
            service: 'benchmark',
            headers: {
                benchHeader1: 'bench value one',
                benchHeader2: 'bench value two',
                benchHeader3: 'bench value three'
            }
        })
        .send(this.arg1, this.arg2, this.arg3, done);

    function done(err, res) {
        if (err) {
            throw err;
        }
        self.commands_completed++;
        self.command_latency.update(Date.now() - start);
        self.fill_pipeline();
    }
};

Test.prototype.get_stats = function () {
    var obj = this.command_latency.printObj();
    obj.descr = this.args.descr;
    obj.pipeline = this.args.pipeline;
    obj.numClients = this.clients_ready;
    obj.elapsed = Date.now() - this.test_start;
    obj.rate = numRequests / (obj.elapsed / 1000);
    return obj;
};

Test.prototype.print_stats = function () {
    var obj = this.get_stats();
    process.stdout.write(JSON.stringify(obj) + "\n");
};

small_str = "1234";
small_buf = new Buffer(small_str);
large_str = (new Array(4097).join("-"));
large_buf = new Buffer(large_str);
var small_str_set = JSON.stringify(['foo_rand000000000000', small_str]);
var small_buf_set = new Buffer(small_str_set);
var large_str_set = JSON.stringify(['foo_rand000000000001', large_str]);
var large_buf_set = new Buffer(large_str_set);

tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 1}));
tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 50}));
tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 200}));
tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: 20000}));

tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 1}));
tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 50}));
tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 200}));
tests.push(new Test({descr: "SET small str", command: "set", args: small_str_set, pipeline: 20000}));

tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 1}));
tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 50}));
tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 200}));
tests.push(new Test({descr: "SET small buf", command: "set", args: small_buf_set, pipeline: 20000}));

tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 1}));
tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 50}));
tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 200}));
tests.push(new Test({descr: "GET small str", command: "get", args: "foo_rand000000000000", pipeline: 20000}));

tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 1}));
tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 50}));
tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 200}));
tests.push(new Test({descr: "SET large str", command: "set", args: large_str_set, pipeline: 20000}));

tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 1}));
tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 50}));
tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 200}));
tests.push(new Test({descr: "SET large buf", command: "set", args: large_buf_set, pipeline: 20000}));

tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 1}));
tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 50}));
tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 200}));
tests.push(new Test({descr: "GET large str", command: "get", args: 'foo_rand000000000001', pipeline: 20000}));

function next(i, j, done) {
    if (i >= tests.length) return done();
    if (j >= multiplicity) return next(i+1, 0, done);
    var test = tests[i].copy();
    test.run(function () {
        next(i, j+1, done);
    });
}

next(0, 0, function() {
    process.exit(0);
});
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Code.org
 * http://code.org/
 *
 * 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.
 */

/**
 * @fileoverview Generator and controller for message log.
 */

/* jshint
 funcscope: true,
 newcap: true,
 nonew: true,
 shadow: false,
 unused: true,

 maxlen: 90,
 maxparams: 3,
 maxstatements: 200
 */
/* global $ */
'use strict';

var markup = require('./NetSimLogWidget.html');
var dom = require('../dom');

/**
 * @constructor
 */
var NetSimLogWidget = function () {
};
module.exports = NetSimLogWidget;

/**
 * Static counter used to generate/uniquely identify different instances
 * of this log widget on the page.
 * @type {number}
 */
NetSimLogWidget.uniqueIDCounter = 0;

/**
 * Generate a new NetSimLogWidget, puttig it on the page and hooking
 * it up to the given connection where it will update to reflect the
 * state of the connected router, if there is one.
 * @param element
 * @param {!string} title - The log widget header text
 */
NetSimLogWidget.createWithin = function (element, title) {
  var controller = new NetSimLogWidget();

  var instanceID = NetSimLogWidget.uniqueIDCounter;
  NetSimLogWidget.uniqueIDCounter++;

  element.innerHTML = markup({
    logInstanceID: instanceID,
    logTitle: title
  });
  controller.bindElements_(instanceID);
  return controller;
};

/**
 * Get relevant elements from the page and bind them to local variables.
 * @private
 */
NetSimLogWidget.prototype.bindElements_ = function (instanceID) {
  this.rootDiv_ = $('#netsim_log_widget_' + instanceID);
  this.scrollArea_ = this.rootDiv_.find('#scroll_area');
  this.clearButton_ = this.rootDiv_.find('#clear_button');

  dom.addClickTouchEvent(this.clearButton_[0], this.onClearButtonPress_.bind(this));
};

NetSimLogWidget.prototype.onClearButtonPress_ = function () {
  this.scrollArea_.empty();
};

/**
 * Put a message into the log.
 */
NetSimLogWidget.prototype.log = function (message) {
  var scrollArea = this.scrollArea_;
  var wasScrolledToEnd =
      scrollArea[0].scrollHeight - scrollArea[0].scrollTop <=
      scrollArea.outerHeight();

  $('<div>').html(message).appendTo(this.scrollArea_);

  // Auto-scroll
  if (wasScrolledToEnd) {
    var scrollTimeMs = 250;
    scrollArea.animate({ scrollTop: scrollArea[0].scrollHeight},
        scrollTimeMs);
  }
};
<commit_msg>Correct bad comment.<commit_after>/**
 * Copyright 2015 Code.org
 * http://code.org/
 *
 * 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.
 */

/**
 * @fileoverview Generator and controller for message log.
 */

/* jshint
 funcscope: true,
 newcap: true,
 nonew: true,
 shadow: false,
 unused: true,

 maxlen: 90,
 maxparams: 3,
 maxstatements: 200
 */
/* global $ */
'use strict';

var markup = require('./NetSimLogWidget.html');
var dom = require('../dom');

/**
 * @constructor
 */
var NetSimLogWidget = function () {
};
module.exports = NetSimLogWidget;

/**
 * Static counter used to generate/uniquely identify different instances
 * of this log widget on the page.
 * @type {number}
 */
NetSimLogWidget.uniqueIDCounter = 0;

/**
 * Generate a new NetSimLogWidget, putting it on the page.
 * @param element
 * @param {!string} title - The log widget header text
 */
NetSimLogWidget.createWithin = function (element, title) {
  var controller = new NetSimLogWidget();

  var instanceID = NetSimLogWidget.uniqueIDCounter;
  NetSimLogWidget.uniqueIDCounter++;

  element.innerHTML = markup({
    logInstanceID: instanceID,
    logTitle: title
  });
  controller.bindElements_(instanceID);
  return controller;
};

/**
 * Get relevant elements from the page and bind them to local variables.
 * @private
 */
NetSimLogWidget.prototype.bindElements_ = function (instanceID) {
  this.rootDiv_ = $('#netsim_log_widget_' + instanceID);
  this.scrollArea_ = this.rootDiv_.find('#scroll_area');
  this.clearButton_ = this.rootDiv_.find('#clear_button');

  dom.addClickTouchEvent(this.clearButton_[0], this.onClearButtonPress_.bind(this));
};

NetSimLogWidget.prototype.onClearButtonPress_ = function () {
  this.scrollArea_.empty();
};

/**
 * Put a message into the log.
 */
NetSimLogWidget.prototype.log = function (message) {
  var scrollArea = this.scrollArea_;
  var wasScrolledToEnd =
      scrollArea[0].scrollHeight - scrollArea[0].scrollTop <=
      scrollArea.outerHeight();

  $('<div>').html(message).appendTo(this.scrollArea_);

  // Auto-scroll
  if (wasScrolledToEnd) {
    var scrollTimeMs = 250;
    scrollArea.animate({ scrollTop: scrollArea[0].scrollHeight},
        scrollTimeMs);
  }
};
<|endoftext|>


<commit_before>import invariant from 'invariant';
import merge from 'lodash.merge';

import Plurality from './constants/Plurality';
import normalise from './normalise';
import { REQUEST, INVALIDATE } from './constants/ActionTypes';

export const baseState = {
  entities: {},
  config: {}
};

export default function makeReducer (config, plugins) {
  const { contentTypes, entityKeyPropName } = config;

  const initialState = merge({},
    baseState,
    { config }
  );

  const pluginReducers = plugins
    .reduce((obj, plugin) => merge(obj, plugin.reducer), {});

  const reducer = merge({}, pluginReducers, {
    [REQUEST.COMPLETE]: (state, action) => {
      const normalisedData = normalise(action.contentType, action.data, entityKeyPropName);
      return merge({}, state, { entities: normalisedData.entities });
    },
    [INVALIDATE]: (state, action) => {
      const namePlural = contentTypes[action.contentType].name[Plurality.PLURAL];
      delete state.entities[namePlural][action.id];
      return merge({}, state);
    }
  });

  return {
    wordpress: function pepperoniReducer (state = initialState, action) {
      const [actionNamespace] = action.type.split('/');

      if (actionNamespace !== 'pepperoni') {
        return state;
      }

      console.log(reducer)

      if (action.type in reducer) {
        return reducer[action.type](state, action);
      }

      return state;
    }
  };
};
<commit_msg>Remove unused invariant import;<commit_after>import merge from 'lodash.merge';

import Plurality from './constants/Plurality';
import normalise from './normalise';
import { REQUEST, INVALIDATE } from './constants/ActionTypes';

export const baseState = {
  entities: {},
  config: {}
};

export default function makeReducer (config, plugins) {
  const { contentTypes, entityKeyPropName } = config;

  const initialState = merge({},
    baseState,
    { config }
  );

  const pluginReducers = plugins
    .reduce((obj, plugin) => merge(obj, plugin.reducer), {});

  const reducer = merge({}, pluginReducers, {
    [REQUEST.COMPLETE]: (state, action) => {
      const normalisedData = normalise(action.contentType, action.data, entityKeyPropName);
      return merge({}, state, { entities: normalisedData.entities });
    },
    [INVALIDATE]: (state, action) => {
      const namePlural = contentTypes[action.contentType].name[Plurality.PLURAL];
      delete state.entities[namePlural][action.id];
      return merge({}, state);
    }
  });

  return {
    wordpress: function pepperoniReducer (state = initialState, action) {
      const [actionNamespace] = action.type.split('/');

      if (actionNamespace !== 'pepperoni') {
        return state;
      }

      console.log(reducer)

      if (action.type in reducer) {
        return reducer[action.type](state, action);
      }

      return state;
    }
  };
};
<|endoftext|>


<commit_before>var audio = document.getElementById('AudioElement') || new Audio();
var playing = null;

function textToAlexa(text){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "/text?text="+text, true);
  xhr.responseType = "blob";
  xhr.onload = function(evt){
    if(xhr.status = 200){
      var blob = new Blob([xhr.response], {type: 'audio/wav'});
      var objectUrl = URL.createObjectURL(blob);
      audio.addEventListener("ended", function(){
        if(playing == 'response'){
          draw("white");
        }
        playing = null;
      });
      audio.src = objectUrl;
      audio.onload = function(evt){
        URL.revokeObjectUrl(objectUrl);
      };
      draw('#00ff00');
      audio.play();
      playing = "response";
    }
  }
  xhr.send();
}
<commit_msg>add trigger support on frontend<commit_after>var audio = document.getElementById('AudioElement') || new Audio();
var playing = null;

function textToAlexa(text){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "/text?text="+text, true);
  xhr.responseType = "blob";
  xhr.onload = function(evt){
    if(xhr.status = 200){
      var blob = new Blob([xhr.response], {type: 'audio/wav'});
      var objectUrl = URL.createObjectURL(blob);
      audio.addEventListener("ended", function(){
        if(playing == 'response'){
          draw("white");
        }
        playing = null;
      });
      audio.src = objectUrl;
      audio.onload = function(evt){
        URL.revokeObjectUrl(objectUrl);
      };
      draw('#00ff00');
      audio.play();
      playing = "response";
    }
  }
  xhr.send();
}

window.setInterval(function(){
  $.getJSON( "/trigger", function( data ) {
    if(data["trigger"] == true){
      textToAlexa("hello alexa");
    }
  }
}, 500)<|endoftext|>


<commit_before>// ==UserScript==
// @name           Amazon personal filter
// @namespace      curipha
// @description    Obscure annoying contents from search result and best sellers
// @include        http://www.amazon.co.jp/*
// @include        https://www.amazon.co.jp/*
// @version        0.1.0
// @grant          none
// @noframes
// ==/UserScript==

(function() {
  'use strict';

  if (document.contentType !== 'text/html') return;

  var opacity = 0.2;
  var pattern = /(無料|期間限定|(試|立ち?)読|(試|ため)し|スターター|STARTER|ダイジェスト|分冊|単話|1話売り|雑誌|Web版|未分類|プチ(キス|デザ)|ハーレクイン|([^0-9０-９][0０]|創刊)号|[Vv]ol[\s．\.]*[0０]([^0-9０-９]|$))/;

  var opaque = function(list_selector, item_selector, title_func) {
    var gettitle = title_func || (function(elem) { return elem.getAttribute('title') || elem.textContent });

    return function() {
      var result = document.body.querySelectorAll(list_selector);
      for (var item of result) {
        var title = item.querySelector(item_selector);
        if (title) {
          if (pattern.test(gettitle(title).trim())) {
            item.style.opacity = opacity;
          }
          else {
            if (item.style.opacity == opacity) item.style.opacity = 1;
          }
        }
      }
    };
  };

  // Search result
  if (document.getElementById('searchTemplate')) {
    var mo_sr = new MutationObserver(opaque('#searchTemplate .s-result-item', 'h2'));
    mo_sr.observe(document.body, { childList: true, subtree: true });
  }
  if (document.getElementById('mainResults')) {
    var mo_sr2 = new MutationObserver(opaque('#mainResults [id^="result_"]', 'h3 .lrg'));
    mo_sr2.observe(document.body, { childList: true });
  }

  // Best sellers
  if (document.getElementById('zg_col1')) {
    var mo_bs = new MutationObserver(opaque('#zg_col1 .zg_item_compact', '.zg_title'));
    mo_bs.observe(document.body, { childList: true });
  }

  // Personalized item list
  var mo_il = new MutationObserver(opaque('.s9hl', 'a.title[title]'));
  mo_il.observe(document.body, { childList: true });
  var mo_il2 = new MutationObserver(opaque('#buttonWrapper .shoveler-cell', '.p13n-link div[class^="p13n-sc-"]'));
  mo_il2.observe(document.body, { childList: true, subtree: true });
})();
<commit_msg>Update blocking pattern<commit_after>// ==UserScript==
// @name           Amazon personal filter
// @namespace      curipha
// @description    Obscure annoying contents from search result and best sellers
// @include        http://www.amazon.co.jp/*
// @include        https://www.amazon.co.jp/*
// @version        0.1.0
// @grant          none
// @noframes
// ==/UserScript==

(function() {
  'use strict';

  if (document.contentType !== 'text/html') return;

  var opacity = 0.2;
  var pattern = /(無料|期間限定|(試|立ち?)読|(試|ため)し|スターター|STARTER|ダイジェスト|分冊|単話|1話売り|雑誌|Web版|未分類|プチ(キス|デザ|ララ)|ハーレクイン|([^0-9０-９][0０]|創刊)号|[Vv]ol[\s．\.]*[0０]([^0-9０-９]|$))/;

  var opaque = function(list_selector, item_selector, title_func) {
    var gettitle = title_func || (function(elem) { return elem.getAttribute('title') || elem.textContent });

    return function() {
      var result = document.body.querySelectorAll(list_selector);
      for (var item of result) {
        var title = item.querySelector(item_selector);
        if (title) {
          if (pattern.test(gettitle(title).trim())) {
            item.style.opacity = opacity;
          }
          else {
            if (item.style.opacity == opacity) item.style.opacity = 1;
          }
        }
      }
    };
  };

  // Search result
  if (document.getElementById('searchTemplate')) {
    var mo_sr = new MutationObserver(opaque('#searchTemplate .s-result-item', 'h2'));
    mo_sr.observe(document.body, { childList: true, subtree: true });
  }
  if (document.getElementById('mainResults')) {
    var mo_sr2 = new MutationObserver(opaque('#mainResults [id^="result_"]', 'h3 .lrg'));
    mo_sr2.observe(document.body, { childList: true });
  }

  // Best sellers
  if (document.getElementById('zg_col1')) {
    var mo_bs = new MutationObserver(opaque('#zg_col1 .zg_item_compact', '.zg_title'));
    mo_bs.observe(document.body, { childList: true });
  }

  // Personalized item list
  var mo_il = new MutationObserver(opaque('.s9hl', 'a.title[title]'));
  mo_il.observe(document.body, { childList: true });
  var mo_il2 = new MutationObserver(opaque('#buttonWrapper .shoveler-cell', '.p13n-link div[class^="p13n-sc-"]'));
  mo_il2.observe(document.body, { childList: true, subtree: true });
})();
<|endoftext|>