<commit_before>'use strict'
const reload = require('require-reload')(require);
const ErisUtils = reload('./../util/eris_utils.js');
const PublicError = reload('./../public_error.js');
const strings = reload('./../string_factory.js').help;

function validateCommand(command) {
  let commandName = command.aliases[0];
  if (command.shortDescription && typeof command.shortDescription !== typeof '') {
    throw new Error('The shortDescription must be a string. It is not for ' + commandName);
  } else if (command.usageExample && typeof command.usageExample !== typeof '') {
    throw new Error('The usageExample must be a string. It is not for ' + commandName);
  } else if (command.longDescription && typeof command.longDescription !== typeof '') {
    throw new Error('The longDescription must be a string. It is not for ' + commandName);
  } else if (command.aliasesForHelp && (!Array.isArray(command.aliasesForHelp) || command.aliasesForHelp.length < 1)) {
    throw new Error('The aliasesForHelp must be an array. It is not for ' + commandName);
  }
}

function createTopLevelHelpTextForCommands(commands, helpCommandAlias) {
  if (commands.length === 0) {
    return;
  }
  let helpText = '```glsl\n';
  for (let command of commands) {
    helpText += createTopLevelHelpTextForCommand(command) + '\n';
  }
  helpText += `\nSay ${helpCommandAlias} [command name] to see more help for a command. Example: ${helpCommandAlias} ${commands[0].aliases[0]}\n\`\`\``;
  return helpText;
}

function createTopLevelHelpTextForCommand(command) {
  validateCommand(command);
  let aliases = command.aliasesForHelp || command.aliases;
  let firstAlias = aliases[0];
  let otherAliases = aliases.slice(1);
  let helpText = firstAlias;
  if (otherAliases.length > 0) {
    helpText += ` (aliases: ${otherAliases.join(', ')})`;
  }
  if (command.shortDescription || command.usageExample) {
    helpText += '\n    # ';
  }
  if (command.shortDescription) {
    helpText += command.shortDescription + ' ';
  }
  if (command.usageExample) {
    helpText += 'Example: ' + command.usageExample;
  }

  return helpText;
}

function findCommandWithAlias(commands, alias) {
  return commands.find(command => command.aliases.indexOf(alias) !== -1);
}

function findCloseMatchCommandForAlias(commands, alias) {
  let currentCandidate;
  let currentCandidateAlias;
  for (let command of commands) {
    for (let candidateAlias of command.aliases) {
      if (candidateAlias.indexOf(alias) !== -1) {
        if (!currentCandidateAlias || currentCandidateAlias.length > candidateAlias.length) {
          currentCandidateAlias = candidateAlias;
          currentCandidate = command;
        }
      }
    }
  }
  return currentCandidate;
}

function indexOfAliasInList(command, list) {
  for (let alias of command.aliases) {
    let index = list.indexOf(alias);
    if (index !== -1) {
      return index;
    }
  }
  return -1;
}

function compareCommandOrder(commandA, commandB, orderList) {
  return indexOfAliasInList(commandA, orderList) - indexOfAliasInList(commandB, orderList);
}

/**
* A command for reloading the command and message managers. This is a special command that the command manager has direct knowledge of.
*/
class Help {
  /**
  * @param {Array<Command>} otherCommands - The commands that should be considered to be included in the help.
  * @param {Array<String>} enabledSettingsForOtherCommands - An array of the enable setting name for each command.
  *   Must be parallel to the otherCommands array.
  * @param {Object} config - The monochrome config.
  */
  constructor(otherCommands, config) {
    this.commandAliases = config.autoGeneratedHelpCommandAliases;
    this.embedColor_ = config.colorForAutoGeneratedHelpEmbeds;
    this.uniqueId = 'autoGeneratedHelp425654';
    this.commandsToGenerateHelpFor_ = otherCommands
      .filter(command => indexOfAliasInList(command, config.commandsToGenerateHelpFor) !== -1)
      .sort((a, b) => compareCommandOrder(a, b, config.commandsToGenerateHelpFor));
    this.requiredSettings = this.commandsToGenerateHelpFor_
      .map(command => command.getEnabledSettingFullyQualifiedUserFacingName())
      .filter(settingName => !!settingName);
    for (let command of this.commandsToGenerateHelpFor_) {
      validateCommand(command);
    }
    this.action = (bot, msg, suffix, settings) => this.execute_(bot, msg, suffix, settings);
  }

  execute_(bot, msg, suffix, settings) {
    if (suffix) {
      return this.showAdvancedHelp_(msg, suffix, settings);
    } else {
      return this.showGeneralHelp_(msg, settings);
    }
  }

  showAdvancedHelp_(msg, targetAlias, settings) {
    let command = findCommandWithAlias(this.commandsToGenerateHelpFor_, targetAlias);
    if (!command) {
      command = findCloseMatchCommandForAlias(this.commandsToGenerateHelpFor_, targetAlias);
    }
    if (!command) {
      return this.showGeneralHelp_(msg, settings);
    }

    let fields = [];
    if (command.getCooldown() !== undefined) {
      fields.push({name: 'Cooldown', value: command.getCooldown().toString() + ' seconds', inline: true});
    }
    let permissionsString = '';

    if (command.getIsForServerAdminOnly()) {
      permissionsString += 'Server admin\n';
    }
    if (command.getIsForBotAdminOnly()) {
      permissionsString += 'Bot admin\n';
    }
    if (!permissionsString) {
      permissionsString += 'None';
    }
    fields.push({name: 'Required permissions', value: permissionsString, inline: true});
    if (command.usageExample) {
      fields.push({name: 'Usage example', value: command.usageExample});
    }

    let botContent = {
      embed: {
        title: command.aliases[0],
        description: command.longDescription || command.shortDescription,
        color: this.embedColor_,
        fields: fields,
      }
    };

    return msg.channel.createMessage(botContent);
  }

  showGeneralHelp_(msg, settings) {
    let commandsToDisplayHelpFor = [];
    for (let command of this.commandsToGenerateHelpFor_) {
      let enabledSettingName = command.getEnabledSettingFullyQualifiedUserFacingName();
      if (enabledSettingName && !settings[enabledSettingName]) {
        continue;
      }
      commandsToDisplayHelpFor.push(command);
    }

    let helpText = createTopLevelHelpTextForCommands(commandsToDisplayHelpFor, this.commandAliases[0]);
    if (helpText) {
      return msg.channel.createMessage(helpText);
    } else {
      throw PublicError.createWithCustomPublicMessage('There are no commands to show help for. Perhaps the server admins disabled all my commands in this channel.', true, strings.noCommandsForHelpLog);
    }
  }
}

module.exports = Help;
<commit_msg>make the help deletable too<commit_after>'use strict'
const reload = require('require-reload')(require);
const ErisUtils = reload('./../util/eris_utils.js');
const PublicError = reload('./../public_error.js');
const strings = reload('./../string_factory.js').help;

function validateCommand(command) {
  let commandName = command.aliases[0];
  if (command.shortDescription && typeof command.shortDescription !== typeof '') {
    throw new Error('The shortDescription must be a string. It is not for ' + commandName);
  } else if (command.usageExample && typeof command.usageExample !== typeof '') {
    throw new Error('The usageExample must be a string. It is not for ' + commandName);
  } else if (command.longDescription && typeof command.longDescription !== typeof '') {
    throw new Error('The longDescription must be a string. It is not for ' + commandName);
  } else if (command.aliasesForHelp && (!Array.isArray(command.aliasesForHelp) || command.aliasesForHelp.length < 1)) {
    throw new Error('The aliasesForHelp must be an array. It is not for ' + commandName);
  }
}

function createTopLevelHelpTextForCommands(commands, helpCommandAlias) {
  if (commands.length === 0) {
    return;
  }
  let helpText = '```glsl\n';
  for (let command of commands) {
    helpText += createTopLevelHelpTextForCommand(command) + '\n';
  }
  helpText += `\nSay ${helpCommandAlias} [command name] to see more help for a command. Example: ${helpCommandAlias} ${commands[0].aliases[0]}\n\`\`\``;
  return helpText;
}

function createTopLevelHelpTextForCommand(command) {
  validateCommand(command);
  let aliases = command.aliasesForHelp || command.aliases;
  let firstAlias = aliases[0];
  let otherAliases = aliases.slice(1);
  let helpText = firstAlias;
  if (otherAliases.length > 0) {
    helpText += ` (aliases: ${otherAliases.join(', ')})`;
  }
  if (command.shortDescription || command.usageExample) {
    helpText += '\n    # ';
  }
  if (command.shortDescription) {
    helpText += command.shortDescription + ' ';
  }
  if (command.usageExample) {
    helpText += 'Example: ' + command.usageExample;
  }

  return helpText;
}

function findCommandWithAlias(commands, alias) {
  return commands.find(command => command.aliases.indexOf(alias) !== -1);
}

function findCloseMatchCommandForAlias(commands, alias) {
  let currentCandidate;
  let currentCandidateAlias;
  for (let command of commands) {
    for (let candidateAlias of command.aliases) {
      if (candidateAlias.indexOf(alias) !== -1) {
        if (!currentCandidateAlias || currentCandidateAlias.length > candidateAlias.length) {
          currentCandidateAlias = candidateAlias;
          currentCandidate = command;
        }
      }
    }
  }
  return currentCandidate;
}

function indexOfAliasInList(command, list) {
  for (let alias of command.aliases) {
    let index = list.indexOf(alias);
    if (index !== -1) {
      return index;
    }
  }
  return -1;
}

function compareCommandOrder(commandA, commandB, orderList) {
  return indexOfAliasInList(commandA, orderList) - indexOfAliasInList(commandB, orderList);
}

/**
* A command for reloading the command and message managers. This is a special command that the command manager has direct knowledge of.
*/
class Help {
  /**
  * @param {Array<Command>} otherCommands - The commands that should be considered to be included in the help.
  * @param {Array<String>} enabledSettingsForOtherCommands - An array of the enable setting name for each command.
  *   Must be parallel to the otherCommands array.
  * @param {Object} config - The monochrome config.
  */
  constructor(otherCommands, config) {
    this.commandAliases = config.autoGeneratedHelpCommandAliases;
    this.embedColor_ = config.colorForAutoGeneratedHelpEmbeds;
    this.uniqueId = 'autoGeneratedHelp425654';
    this.commandsToGenerateHelpFor_ = otherCommands
      .filter(command => indexOfAliasInList(command, config.commandsToGenerateHelpFor) !== -1)
      .sort((a, b) => compareCommandOrder(a, b, config.commandsToGenerateHelpFor));
    this.requiredSettings = this.commandsToGenerateHelpFor_
      .map(command => command.getEnabledSettingFullyQualifiedUserFacingName())
      .filter(settingName => !!settingName);
    for (let command of this.commandsToGenerateHelpFor_) {
      validateCommand(command);
    }
    this.action = (bot, msg, suffix, settings) => this.execute_(bot, msg, suffix, settings);
  }

  execute_(bot, msg, suffix, settings) {
    if (suffix) {
      return this.showAdvancedHelp_(msg, suffix, settings);
    } else {
      return this.showGeneralHelp_(msg, settings);
    }
  }

  showAdvancedHelp_(msg, targetAlias, settings) {
    let command = findCommandWithAlias(this.commandsToGenerateHelpFor_, targetAlias);
    if (!command) {
      command = findCloseMatchCommandForAlias(this.commandsToGenerateHelpFor_, targetAlias);
    }
    if (!command) {
      return this.showGeneralHelp_(msg, settings);
    }

    let fields = [];
    if (command.getCooldown() !== undefined) {
      fields.push({name: 'Cooldown', value: command.getCooldown().toString() + ' seconds', inline: true});
    }
    let permissionsString = '';

    if (command.getIsForServerAdminOnly()) {
      permissionsString += 'Server admin\n';
    }
    if (command.getIsForBotAdminOnly()) {
      permissionsString += 'Bot admin\n';
    }
    if (!permissionsString) {
      permissionsString += 'None';
    }
    fields.push({name: 'Required permissions', value: permissionsString, inline: true});
    if (command.usageExample) {
      fields.push({name: 'Usage example', value: command.usageExample});
    }

    let botContent = {
      embed: {
        title: command.aliases[0],
        description: command.longDescription || command.shortDescription,
        color: this.embedColor_,
        fields: fields,
      }
    };

    return msg.channel.createMessage(botContent, null, msg);
  }

  showGeneralHelp_(msg, settings) {
    let commandsToDisplayHelpFor = [];
    for (let command of this.commandsToGenerateHelpFor_) {
      let enabledSettingName = command.getEnabledSettingFullyQualifiedUserFacingName();
      if (enabledSettingName && !settings[enabledSettingName]) {
        continue;
      }
      commandsToDisplayHelpFor.push(command);
    }

    let helpText = createTopLevelHelpTextForCommands(commandsToDisplayHelpFor, this.commandAliases[0]);
    if (helpText) {
      return msg.channel.createMessage(helpText, null, msg);
    } else {
      throw PublicError.createWithCustomPublicMessage('There are no commands to show help for. Perhaps the server admins disabled all my commands in this channel.', true, strings.noCommandsForHelpLog);
    }
  }
}

module.exports = Help;
<|endoftext|>


<commit_before>import './index.css';
import '../foundation.css';

import React, { Component } from 'react';
import { render } from 'react-dom';
import alertify from 'alertify.js';
import {
  form,
  DisabledFormSubmit,
  FeedbackFormSubmit,
  ResetFormButton,
} from 'react-inform';

alertify.logPosition('top right');

function LabeledInput({ text, error, ...rest }) {
  let htmlFor = undefined;
  if (rest.id) {
    htmlFor = rest.id;
  }
  return (

      {text}
      <input placeholder={text} type="text" {...rest} />
      {error}

  );
}

@form()
class MyForm extends Component {
  handleSubmit(e) {
    e.preventDefault();
    alertify.success('Awesome, it submitted!');
  }

  render() {
    const { fields: fieldMap } = this.props;
    const fields = Object.keys(fieldMap);
    return (
      <form onSubmit={e => this.handleSubmit(e)}>
        {fields.map(fieldName =>
          <LabeledInput
            text={fieldName}
            id={fieldName}
            key={fieldName}
            {...fieldMap[fieldName]}
          />
        )}
        <DisabledFormSubmit className="button" value="I am enabled when valid!" />
        <FeedbackFormSubmit
          className="button"
          value="I will reveal errors!"
          onInvalid={() => alertify.error('Please fix errors!')}
        />
        <ResetFormButton className="alert button" />
      </form>
    );
  }
}

class App extends Component {
  state= {
    descriptors: [{
      fieldName: 'Email',
      validate: "x => !!x && !!x.match(/[^@]+@[^@]+\\.[^@]+/) || 'Must be a valid email'",
    }, {
      fieldName: 'Password',
      validate: "x => !!x || 'Password is required'",
    }, {
      fieldName: 'Confirm Password',
      validate: "(x, values) => x === values.Password || 'Passwords must match'",
    }],
  };

  handleChange = e => {
    const { descriptors } = this.state;
    const index = parseInt(e.target.getAttribute('data-index'), 10);
    const type = e.target.getAttribute('data-type');
    this.setState({
      descriptors: descriptors.map((des, i) => {
        if (i !== index) return des;
        return {
          ...des,
          [type]: e.target.value,
        };
      }),
    });
  }

  handleAdd = () => {
    const { descriptors } = this.state;
    this.setState({
      descriptors: descriptors.concat({
        fieldName: '',
        validate: 'x => undefined',
      }),
    });
  }

  handleRemove = i => {
    const { descriptors } = this.state;
    this.setState({
      descriptors: descriptors.filter((d, idx) => idx !== i),
    });
  }

  tryEval(code) {
    try {
      return eval(code);
    } catch (e) {
      return undefined;
    }
  }

  convertDescriptor = ({ fieldName, validate }) => {
    const result = this.tryEval(validate);
    if (result instanceof Function) {
      return {
        fieldName,
        validate: result,
      };
    }
    return {
      fieldName,
      validate: () => undefined,
    };
  }

  makeValidate = () => {
    const descriptors = this.state.descriptors.map(this.convertDescriptor);

    return values => {
      const errors = {};
      descriptors.forEach(({ fieldName, validate }) => {
        if (!fieldName) return;
        try {
          const result = validate(values[fieldName], values);
          if (result === true) return;
          if (result) errors[fieldName] = result;
        } catch (e) {
          errors[fieldName] = e.toString();
        }
      });
      return errors;
    };
  }

  render() {
    const { descriptors } = this.state;
    const fields = descriptors.filter(({ fieldName }) => !!fieldName).map(d => d.fieldName);
    const value = fields.reduce((acc, field) => ({ ...acc, [field]: (this.state.value || {})[field] }), {});

    return (

          <MyForm onChange={value => this.setState({ value })} fields={fields} validate={this.makeValidate()} />

{JSON.stringify(value || {}, 2, 2)}

        <form className="fields">
          {descriptors.map((d, i) =>

              <input
                type="text"
                placeholder="Name"
                data-index={i}
                data-type="fieldName"
                value={d.fieldName}
                onChange={this.handleChange}
              />
              <input
                type="text"
                placeholder="Validation"
                data-index={i}
                data-type="validate"
                value={d.validate}
                onChange={this.handleChange}
              />
              <button className="button" type="button" onClick={() => this.handleRemove(i)}>x</button>

          )}
        </form>
        <button className="button" onClick={this.handleAdd}>+</button>

    );
  }
}

render(<App />, document.getElementById('container'));
<commit_msg>Sync form state when removing fields in dynamic example<commit_after>import './index.css';
import '../foundation.css';

import React, { Component } from 'react';
import { render } from 'react-dom';
import alertify from 'alertify.js';
import {
  form,
  DisabledFormSubmit,
  FeedbackFormSubmit,
  ResetFormButton,
} from 'react-inform';

alertify.logPosition('top right');

function LabeledInput({ text, error, ...rest }) {
  let htmlFor = undefined;
  if (rest.id) {
    htmlFor = rest.id;
  }
  return (

      {text}
      <input placeholder={text} type="text" {...rest} />
      {error}

  );
}

@form()
class MyForm extends Component {
  handleSubmit(e) {
    e.preventDefault();
    alertify.success('Awesome, it submitted!');
  }

  render() {
    const { fields: fieldMap } = this.props;
    const fields = Object.keys(fieldMap);
    return (
      <form onSubmit={e => this.handleSubmit(e)}>
        {fields.map(fieldName =>
          <LabeledInput
            text={fieldName}
            id={fieldName}
            key={fieldName}
            {...fieldMap[fieldName]}
          />
        )}
        <DisabledFormSubmit className="button" value="I am enabled when valid!" />
        <FeedbackFormSubmit
          className="button"
          value="I will reveal errors!"
          onInvalid={() => alertify.error('Please fix errors!')}
        />
        <ResetFormButton className="alert button" />
      </form>
    );
  }
}

class App extends Component {
  state= {
    descriptors: [{
      fieldName: 'Email',
      validate: "x => !!x && !!x.match(/[^@]+@[^@]+\\.[^@]+/) || 'Must be a valid email'",
    }, {
      fieldName: 'Password',
      validate: "x => !!x || 'Password is required'",
    }, {
      fieldName: 'Confirm Password',
      validate: "(x, values) => x === values.Password || 'Passwords must match'",
    }],
  };

  setPruned(value) {
    this.setState({ value: this.pruned(value) });
  }

  pruned = (value = this.state.value) =>
    this.fields().reduce((acc, field) => (
      value.hasOwnProperty(field) ? { ...acc, [field]: value[field] } : acc
    ), {});

  convertDescriptor = ({ fieldName, validate }) => {
    const result = this.tryEval(validate);
    if (result instanceof Function) {
      return {
        fieldName,
        validate: result,
      };
    }
    return {
      fieldName,
      validate: () => undefined,
    };
  }

  makeValidate = () => {
    const descriptors = this.state.descriptors.map(this.convertDescriptor);

    return values => {
      const errors = {};
      descriptors.forEach(({ fieldName, validate }) => {
        if (!fieldName) return;
        try {
          const result = validate(values[fieldName], values);
          if (result === true) return;
          if (result) errors[fieldName] = result;
        } catch (e) {
          errors[fieldName] = e.toString();
        }
      });
      return errors;
    };
  }

  fields() {
    const { descriptors } = this.state;
    return descriptors.filter(({ fieldName }) => !!fieldName).map(d => d.fieldName);
  }

  tryEval(code) {
    try {
      return eval(code);
    } catch (e) {
      return undefined;
    }
  }

  handleRemove = i => {
    const { descriptors } = this.state;
    this.setState({
      descriptors: descriptors.filter((d, idx) => idx !== i),
    }, () => this.setPruned());
  }

  handleAdd = () => {
    const { descriptors } = this.state;
    this.setState({
      descriptors: descriptors.concat({
        fieldName: '',
        validate: 'x => undefined',
      }),
    });
  }

  handleChange = e => {
    const { descriptors } = this.state;
    const index = parseInt(e.target.getAttribute('data-index'), 10);
    const type = e.target.getAttribute('data-type');
    this.setState({
      descriptors: descriptors.map((des, i) => {
        if (i !== index) return des;
        return {
          ...des,
          [type]: e.target.value,
        };
      }),
    });
  }

  render() {
    const { descriptors } = this.state;

    return (

          <MyForm
            onChange={value => this.setPruned(value)}
            value={this.state.value}
            fields={this.fields()}
            validate={this.makeValidate()}
          />

{JSON.stringify(this.state.value || {}, 2, 2)}

        <form className="fields">
          {descriptors.map((d, i) =>

              <input
                type="text"
                placeholder="Name"
                data-index={i}
                data-type="fieldName"
                value={d.fieldName}
                onChange={this.handleChange}
              />
              <input
                type="text"
                placeholder="Validation"
                data-index={i}
                data-type="validate"
                value={d.validate}
                onChange={this.handleChange}
              />
              <button
                className="button"
                type="button"
                onClick={() => this.handleRemove(i)}
              >
                x
              </button>

          )}
        </form>
        <button className="button" onClick={this.handleAdd}>+</button>

    );
  }
}

render(<App />, document.getElementById('container'));
<|endoftext|>


<commit_before>'use strict';

var ProjectListPage = require('../pages/projectlist.page.js');
var ProjectPage = require('../pages/project.page.js');
var SearchPage = require('../pages/search.page.js');

describe('project page', function () {

	  var projectListPage;
	  var projectPage;

	  beforeEach(function () {
			projectListPage = new ProjectListPage();
	    projectListPage.addProject();
	    projectListPage.openLastProject();
	    projectPage = new ProjectPage();
	});

	it('should show the title of the selected project', function () {
	  expect(projectPage.title.getAttribute('value')).toBe('new Project');
	});

	it('should redirect if a project with a valid id is called', function () {
	  expect(browser.getCurrentUrl()).toContain("/project/");
	});

	it('should save the new title of the selected project after save button is pressed', function () {
	  var expectedText = 'newProjectTitle';
	  var title = projectPage.title;
	  title.click();
	  title.clear();
	  title.sendKeys(expectedText);
	  projectPage.save();
	  expect(title.getAttribute('value')).toBe(expectedText);
	});

	 it('should reset the new title of the selected project after cancel button is pressed', function () {
		    var newText = 'newProjectTitle';
		    var title = projectPage.title;
		    var oldText = title.getAttribute('value');
			title.click();
			title.clear();
		    title.sendKeys(newText);
		    projectPage.cancel();
		    expect(title.getAttribute('value')).toBe(oldText);
	  });

	  it('should set a date correctly and persist date to project', function() {
		    var inputDate = '01.03.01';
		    var inputStart = projectPage.start;
		    inputStart.click();
		    inputStart.clear();
		    inputStart.sendKeys(inputDate);
		    projectPage.save();
		    expect(inputStart.getAttribute('value')).toBe(inputDate);
	  });

	  it('should be able to create a new tag', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test");
		    locations.sendKeys(protractor.Key.ENTER);
		    expect(projectPage.locationsTagCount).toBe(1);
		  });

	  it('should be able to create a new tag with length one', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("T");
		    locations.sendKeys(protractor.Key.ENTER);
		    expect(projectPage.locationsTagCount).toBe(1);
		  });

	  fit('should be able to create a new tag without replace spaces with dashes', function () {
		    var locations = projectPage.locations;
		    var inputLocation = 'Test without dashes';
		    locations.click();
		    locations.sendKeys(inputLocation);
		    locations.sendKeys(protractor.Key.ENTER);
		    expect(projectPage.getLastLocationText).toBe(inputLocation);
		    expect(projectPage.locationsTagCount).toBe(1);
		  });

	  it('should set an invalid date and persist it after correcting it', function() {
		    var incorrectInputDate = '01.0x.01';
		    var inputStart = projectPage.start;
		    inputStart.click();
		    inputStart.clear();
		    inputStart.sendKeys(incorrectInputDate);
		    inputStart.sendKeys(protractor.Key.DOWN);
		    inputStart.sendKeys(protractor.Key.ENTER);
		    inputStart.click();
		    var newValue = inputStart.getAttribute('value');
		    projectPage.save();
		    expect(inputStart.getAttribute('value')).toBe(newValue);
		  });

	  it('should be able to remove an existing tag', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test");
		    locations.sendKeys(protractor.Key.ENTER);

		    locations.click();
		    locations.sendKeys("Test2");
		    locations.sendKeys(protractor.Key.ENTER);

		    locations.click();
		    locations.sendKeys("Test3");
		    locations.sendKeys(protractor.Key.ENTER);

		    locations.sendKeys(protractor.Key.BACK_SPACE);
		    locations.sendKeys(protractor.Key.BACK_SPACE);
		    projectPage.save();
		    expect(projectPage.locationsTagCount).toBe(2);
		  });

	  it('should provide suggestions for tag fields from other profiles', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test123");
		    locations.sendKeys("Test124");
		    locations.sendKeys(protractor.Key.ENTER);

		    projectPage.save();

			var newProjectListPage = new ProjectListPage();
			newProjectListPage.addProject();
			newProjectListPage.openLastProject();

		    locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test");

		    var suggestionsCount = element.all(by.css('.suggestion-item')).count();
		    expect(suggestionsCount).toBe(3);
		  });

});	  <commit_msg>HIRE-171: test<commit_after>'use strict';

var ProjectListPage = require('../pages/projectlist.page.js');
var ProjectPage = require('../pages/project.page.js');
var SearchPage = require('../pages/search.page.js');

describe('project page', function () {

	  var projectListPage;
	  var projectPage;

	  beforeEach(function () {
			projectListPage = new ProjectListPage();
	    projectListPage.addProject();
	    projectListPage.openLastProject();
	    projectPage = new ProjectPage();
	});

	it('should show the title of the selected project', function () {
	  expect(projectPage.title.getAttribute('value')).toBe('new Project');
	});

	it('should redirect if a project with a valid id is called', function () {
	  expect(browser.getCurrentUrl()).toContain("/project/");
	});

	it('should save the new title of the selected project after save button is pressed', function () {
	  var expectedText = 'newProjectTitle';
	  var title = projectPage.title;
	  title.click();
	  title.clear();
	  title.sendKeys(expectedText);
	  projectPage.save();
	  expect(title.getAttribute('value')).toBe(expectedText);
	});

	 it('should reset the new title of the selected project after cancel button is pressed', function () {
		    var newText = 'newProjectTitle';
		    var title = projectPage.title;
		    var oldText = title.getAttribute('value');
			title.click();
			title.clear();
		    title.sendKeys(newText);
		    projectPage.cancel();
		    expect(title.getAttribute('value')).toBe(oldText);
	  });

	  it('should set a date correctly and persist date to project', function() {
		    var inputDate = '01.03.01';
		    var inputStart = projectPage.start;
		    inputStart.click();
		    inputStart.clear();
		    inputStart.sendKeys(inputDate);
		    projectPage.save();
		    expect(inputStart.getAttribute('value')).toBe(inputDate);
	  });

	  it('should be able to create a new tag', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test");
		    locations.sendKeys(protractor.Key.ENTER);
		    expect(projectPage.locationsTagCount).toBe(1);
		  });

	  it('should be able to create a new tag with length one', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("T");
		    locations.sendKeys(protractor.Key.ENTER);
		    expect(projectPage.locationsTagCount).toBe(1);
		  });

	  it('should be able to create a new tag without replace spaces with dashes', function () {
		    var locations = projectPage.locations;
		    var inputLocation = 'Test without dashes';
		    locations.click();
		    locations.sendKeys(inputLocation);
		    locations.sendKeys(protractor.Key.ENTER);
		    expect(projectPage.getLastLocationText).toBe(inputLocation);
		    expect(projectPage.locationsTagCount).toBe(1);
		  });

	  it('should set an invalid date and persist it after correcting it', function() {
		    var incorrectInputDate = '01.0x.01';
		    var inputStart = projectPage.start;
		    inputStart.click();
		    inputStart.clear();
		    inputStart.sendKeys(incorrectInputDate);
		    inputStart.sendKeys(protractor.Key.DOWN);
		    inputStart.sendKeys(protractor.Key.ENTER);
		    inputStart.click();
		    var newValue = inputStart.getAttribute('value');
		    projectPage.save();
		    expect(inputStart.getAttribute('value')).toBe(newValue);
		  });

	  it('should be able to remove an existing tag', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test");
		    locations.sendKeys(protractor.Key.ENTER);

		    locations.click();
		    locations.sendKeys("Test2");
		    locations.sendKeys(protractor.Key.ENTER);

		    locations.click();
		    locations.sendKeys("Test3");
		    locations.sendKeys(protractor.Key.ENTER);

		    locations.sendKeys(protractor.Key.BACK_SPACE);
		    locations.sendKeys(protractor.Key.BACK_SPACE);
		    projectPage.save();
		    expect(projectPage.locationsTagCount).toBe(2);
		  });

	  it('should provide suggestions for tag fields from other profiles', function () {
		    var locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test123");
		    locations.sendKeys("Test124");
		    locations.sendKeys(protractor.Key.ENTER);

		    projectPage.save();

			var newProjectListPage = new ProjectListPage();
			newProjectListPage.addProject();
			newProjectListPage.openLastProject();

		    locations = projectPage.locations;
		    locations.click();
		    locations.sendKeys("Test");

		    var suggestionsCount = element.all(by.css('.suggestion-item')).count();
		    expect(suggestionsCount).toBe(3);
		  });

});	  <|endoftext|>


<commit_before>var students = [];

// View model for the courses page
function pageViewModel(gvm) {
    gvm.userId = -1;
    gvm.studentlistName = ko.observable('Name');
    gvm.listId = -1
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("AccountTitle");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("EditListTitle");}, gvm);

    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.myLists = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("myLists");}, gvm);
    gvm.addStudListBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("addStudListBtn");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    gvm.firstname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Firstname");}, gvm);
    gvm.lastname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Lastname");}, gvm);
    gvm.email = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Email");}, gvm);
    gvm.memberSince = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("MemberSince");}, gvm);
    gvm.myProjects = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("MyProjects");}, gvm);

    gvm.tabledata = ko.observableArray([]);

    gvm.addTableData = function(id, firstname, lastname, username) {
        // Push data
        var tblOject = {tid: id, tfirstname: firstname, tlastname: lastname, tusername: username};
        gvm.tabledata.push(tblOject);

        $('#editbtn-' + id).bind('click', function(event, data) {
            showEditStudentModal(tblOject);
            event.stopPropagation();
        });

        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

}

function showEditStudentModal(tblObject) {
    resetGeneralModal();
    setGeneralModalTitle("Edit Student");
    setGeneralModalBody('<form id="updateStudent"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + tblObject.tfirstname + '" " name="firstname" value="' + tblObject.tfirstname + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + tblObject.tlastname + '" name="lastname" value="' + tblObject.tlastname + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + tblObject.tusername + '" name="username" value="' + tblObject.tusername + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateStudent(tblObject.tid, $('#updateStudent').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function addNewStudent(studentname, listid, callback) {
    console.log(studentname);
    console.log(listid);
    $.ajax({
        url: "/api/newstudent/" + studentname + "/" + listid,
        type: "POST",
        data: {'name': studentname, 'list': listid},
        success: function(data) {
            //console.log(data);
            callback(true);
        },
        error: function(data) {
            console.log('Failed to add new student');
            callback(false);
        }
    });
}

function updateStudent(id, object, callback) {
    $.ajax({
        url: "/api/studentrapport/" + id,
        type: "PUT",
        data: object,
        success: function(data) {
            loadStudentTable();
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function deleteTableItem(id, tblObject){
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen?", function(val){
        if(val){
            $.ajax({
                url: '/api/studentlistrapport/' + $("#page-header").data('value') + '/delete/student/' + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblObject);
                }
            });
        }
    });
}

function getAllStudents() {
    $.getJSON('/api/allstudents', function(data) {
        $.each(data, function(i, item) {
            students.push(item.firstname + " " + item.lastname);
        });
    });
    return students;
}

function loadStudentTable() {
    $.getJSON('/api/studentlistrapporten/students/' + $("#page-header").data('value'), function(data) {
        viewModel.clearTable();
        // Load table data
        $.each(data, function(i, item) {
            viewModel.addTableData(item.id, item.firstname, item.lastname, item.username);
        });
    });
}

function initPage() {
    $.getJSON('/api/studentlistrapport/info/' + $("#page-header").data('value'), function(data) {
        console.log(data[0].id);
        viewModel.studentlistName(data[0].name);
        viewModel.listId = (data[0].id);
    });

    $('#addStudentForm').hide();

    $('#addStudent').click(function(){
        $("#addStudentForm").show();
    });

    $('#addStudentBtn').click(function() {
        var listid = $('#page-header').attr('data-value');
        addNewStudent($('#studentsComplete').val(), listid, function() {
            $('#addStudentForm').hide();
        });
    });

    $('#studentsComplete').autocomplete({ source: getAllStudents() });

    loadStudentTable();
}<commit_msg>add button enablen/disablen<commit_after>var students = [];

// View model for the courses page
function pageViewModel(gvm) {
    gvm.userId = -1;
    gvm.studentlistName = ko.observable('Name');
    gvm.listId = -1
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("AccountTitle");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("EditListTitle");}, gvm);

    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.myLists = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("myLists");}, gvm);
    gvm.addStudListBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("addStudListBtn");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    gvm.firstname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Firstname");}, gvm);
    gvm.lastname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Lastname");}, gvm);
    gvm.email = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Email");}, gvm);
    gvm.memberSince = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("MemberSince");}, gvm);
    gvm.myProjects = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("MyProjects");}, gvm);

    gvm.tabledata = ko.observableArray([]);

    gvm.addTableData = function(id, firstname, lastname, username) {
        // Push data
        var tblOject = {tid: id, tfirstname: firstname, tlastname: lastname, tusername: username};
        gvm.tabledata.push(tblOject);

        $('#editbtn-' + id).bind('click', function(event, data) {
            showEditStudentModal(tblOject);
            event.stopPropagation();
        });

        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

}

function showEditStudentModal(tblObject) {
    resetGeneralModal();
    setGeneralModalTitle("Edit Student");
    setGeneralModalBody('<form id="updateStudent"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + tblObject.tfirstname + '" " name="firstname" value="' + tblObject.tfirstname + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + tblObject.tlastname + '" name="lastname" value="' + tblObject.tlastname + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + tblObject.tusername + '" name="username" value="' + tblObject.tusername + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateStudent(tblObject.tid, $('#updateStudent').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function addNewStudent(studentname, listid, callback) {
    console.log(studentname);
    console.log(listid);
    $.ajax({
        url: "/api/newstudent/" + studentname + "/" + listid,
        type: "POST",
        data: {'name': studentname, 'list': listid},
        success: function(data) {
            //console.log(data);
            callback(true);
        },
        error: function(data) {
            console.log('Failed to add new student');
            callback(false);
        }
    });
}

function updateStudent(id, object, callback) {
    $.ajax({
        url: "/api/studentrapport/" + id,
        type: "PUT",
        data: object,
        success: function(data) {
            loadStudentTable();
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function deleteTableItem(id, tblObject){
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen?", function(val){
        if(val){
            $.ajax({
                url: '/api/studentlistrapport/' + $("#page-header").data('value') + '/delete/student/' + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblObject);
                }
            });
        }
    });
}

function getAllStudents() {
    $.getJSON('/api/allstudents', function(data) {
        $.each(data, function(i, item) {
            students.push(item.firstname + " " + item.lastname);
        });
    });
    return students;
}

function loadStudentTable() {
    $.getJSON('/api/studentlistrapporten/students/' + $("#page-header").data('value'), function(data) {
        viewModel.clearTable();
        // Load table data
        $.each(data, function(i, item) {
            viewModel.addTableData(item.id, item.firstname, item.lastname, item.username);
        });
    });
}

function initPage() {
    $.getJSON('/api/studentlistrapport/info/' + $("#page-header").data('value'), function(data) {
        console.log(data[0].id);
        viewModel.studentlistName(data[0].name);
        viewModel.listId = (data[0].id);
    });

    $('#addStudentForm').hide();
    $('#addStudentBtn').prop('disabled', true);

    $('#addStudent').click(function(){
        $("#addStudentForm").show();
    });

    $('#addStudentBtn').click(function() {
        var listid = $('#page-header').attr('data-value');
        addNewStudent($('#studentsComplete').val(), listid, function() {
            $('#addStudentForm').hide();
        });
    });

    $('#studentsComplete').autocomplete({
        source: getAllStudents(),
        change: function(event, ui) {
            if (ui.item) {
                $('#addStudentBtn').prop('disabled', false);
            }
        }
    });

    loadStudentTable();
}<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-2016 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint node: true */

'use strict';

var assert = require('assert');
var config = require('../config');
var utils = require('./utils');
var environment = config.environment || 'production';
var labels = {
        debug: '[DEBUG]',
        info: '[INFO] ',
        warn: '[WARN] ',
        error: '[ERROR]',
        critical: '[CRIT] '
    };
var level = config.get('level') || 0;
var levels = {
        debug: 1,
        info: 2,
        warn: 4,
        error: 5,
        critical: 6
    };
var eq;
var qt;
var prefix;
var separator;

if (config.production) {
    eq = '=';
    qt = '"';
    prefix = '\t';
    separator = '\t';
} else {
    eq = ': ';
    qt = '';
    prefix = ' ';
    separator = '; ';
}

/* This function has too many statements. */
/* jshint -W071 */

/* This function's cyclomatic complexity is too high. */
/* jshint -W074 */

/**
 * Capture entry.request if existing
 * @param entry
 * @returns {*}
 */
function capture(entry) {
    assert.ok(typeof entry === 'object', '`entry` is expected to be an object');
    if (entry instanceof Error) {
        // JSON.stringify(new Error('Oops)) === {}
        // So we need to capture the properties we want
        entry = {
            error: entry,
            message: entry.message
        };
        if (entry.error.originalError) {
            // entry.error.originalError is not necessarily an instance of Error because we use deepExtend
            // if (entry.error.originalError instanceof Error) {
            entry.originalError = entry.error.originalError;
            delete entry.error.originalError;
            entry.originalMessage = entry.originalError.message;
            entry.stack = entry.originalError.stack;
        } else {
            entry.stack = entry.error.stack.split('\n').join(',')
        }
    }
    var application = config.get('application:name');
    if (application) {
        entry.application = application;
    }
    if (process.env.HOSTNAME) {
        entry.host = process.env.HOSTNAME;
    }
    if (entry.request) {
        var request = entry.request;
        // utils.deepExtends adds undefined values and we do not want to clutter our logs with undefined
        if (request.header && request.headers['user-agent']) {
            entry.agent = request.headers['user-agent'];
        }
        if (request.ip) {
            entry.ip = request.ip;
        }
        if (request.query) {
            entry.query = request.query;
        }
        if (request.trace) {
            entry.trace = request.trace;
        }
        if (request.url) {
            entry.url = request.url;
        }
        delete entry.request;
    }
    // entry.date = (new Date()).toISOString();
    // Note: such an entry is not only ready to print to console but also to be sent as JSON
    return entry;
}

/**
* Print a log entry to the console
* Note: we have discarded pretty solutions because they do not print well in Webstorm console
* @param entry
* @param label
*/
function print(entry, label) {
    /* jshint maxstatements: 44 */
    /* jshint maxcomplexity: 30 */
    var message = (isNaN(Date.parse(entry.date)) ? new Date() : new Date(entry.date)).toISOString();
    message += prefix + label;
    var first = true;
    if (entry.application) {
        message += (first ? prefix : separator) + 'application' + eq + qt + entry.application + qt;
        first = false;
    }
    if (entry.host) {
        message += (first ? prefix : separator) + 'host' + eq + qt + entry.host + qt;
        first = false;
    }
    if (entry.message) {
        message += (first ? prefix : separator) + 'message' + eq + qt + entry.message + qt;
        first = false;
    }
    if (entry.originalMessage) {
        message += (first ? prefix : separator) + 'originalMessage' + eq + qt + entry.originalMessage + qt;
        first = false;
    }
    if (entry.module) {
        message += (first ? prefix : separator) + 'module' + eq + qt + entry.module + qt;
        first = false;
    }
    if (entry.method) {
        message += (first ? prefix : separator) + 'method' + eq + qt + entry.method + qt;
        first = false;
    }
    if (entry.data) {
        try {
            message += (first ? prefix : separator) + 'data' + eq + qt + JSON.stringify(entry.data) + qt;
        } catch (ex) {
            if (typeof entry.data.toString === 'function') {
                message += (first ? prefix : separator) + 'data' + eq + qt + entry.data.toString() + qt;
            }
        }
        first = false;
    }
    if (entry.url) {
        message += (first ? prefix : separator) + 'url' + eq + qt + entry.url + qt;
        first = false;
    }
    if (entry.query) {
        try {
            message += (first ? prefix : separator) + 'query' + eq + qt + JSON.stringify(entry.query) + qt;
        } catch (ex) {
            if (typeof entry.data.toString === 'function') {
                message += (first ? prefix : separator) + 'query' + eq + qt + entry.query.toString() + qt;
            }
        }
        first = false;
    }
    if (entry.trace) {
        message += (first ? prefix : separator) + 'trace' + eq + qt + entry.trace + qt;
        first = false;
    }
    if (entry.ip) {
        message += (first ? prefix : separator) + 'ip' + eq + qt + entry.ip + qt;
        first = false;
    }
    if (entry.agent) {
        message += (first ? prefix : separator) + 'agent' + eq + qt + entry.agent + qt;
        first = false;
    }
    if (entry.stack) {
        message += (first ? prefix : separator) + 'stack' + eq + qt + entry.stack.split('\n').join(', ').replace(/\s+/g, ' ') + qt;
    }
    console.log(message);
    /*
    if (entry.error) {
        console.error(entry.error);
    }
    if (entry.originalError) {
        console.error(entry.originalError);
    }
    */
}

/* jshint +W074 */
/* jshint +W071 */

module.exports = exports = {

    /**
     * Export level for tests
     */
    level: level,

    /**
     * Log a debug entry
     * Only output if debug===true
     * @param entry
     */
    debug: function (entry) {
        if (exports.level > levels.debug) {
            return false;
        }
        print(capture(entry), labels.debug);
        return true;
    },

    /**
     * Log an info entry
     * @param entry
     */
    info: function (entry) {
        if (exports.level > levels.info) {
            return false;
        }
        print(capture(entry), labels.info);
        return true;
    },

    /**
     * Log a warning entry
     * @param entry
     */
    warn: function (entry) {
        if (exports.level > levels.warn) {
            return false;
        }
        print(capture(entry), labels.warn);
        return true;
    },

    /**
     * Log an error entry
     * @param entry
     */
    error: function (entry) {
        if (exports.level > levels.error) {
            return false;
        }
        print(capture(entry), labels.error);
        return true;
    },

    /**
     * Log a critical entry
     * @param entry
     */
    critical: function (entry) {
        if (exports.level > levels.critical) {
            return false;
        }
        print(capture(entry), labels.critical);
        return true;
    },

    /**
     * Shortcut for critical
     */
    crit: function(entry) {
        exports.critical(entry);
    }

};
<commit_msg>Copied from Kidoju-WebApp<commit_after>/**
 * Copyright (c) 2013-2016 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint node: true */

'use strict';

var assert = require('assert');
var config = require('../config');
var utils = require('./utils');
var environment = config.environment || 'production';
var labels = {
        debug: '[DEBUG]',
        info: '[INFO] ',
        warn: '[WARN] ',
        error: '[ERROR]',
        critical: '[CRIT] '
    };
var level = config.get('level') || 0;
var levels = {
        debug: 1,
        info: 2,
        warn: 4,
        error: 5,
        critical: 6
    };
var eq;
var qt;
var prefix;
var separator;

if (config.production) {
    eq = '=';
    qt = '"';
    prefix = '\t';
    separator = '\t';
} else {
    eq = ': ';
    qt = '';
    prefix = ' ';
    separator = '; ';
}

/* This function has too many statements. */
/* jshint -W071 */

/* This function's cyclomatic complexity is too high. */
/* jshint -W074 */

/**
 * Capture entry.request if existing
 * @param entry
 * @returns {*}
 */
function capture(entry) {
    assert.ok(typeof entry === 'object', '`entry` is expected to be an object');
    if (entry instanceof Error) {
        entry = { error: entry };
    }
    // JSON.stringify(new Error('Oops)) === {}
    // So we need to capture the properties we want
    if (entry.error instanceof Error) {
        entry.message = entry.message || entry.error.message;
        if (entry.error.originalError) {
            // entry.error.originalError is not necessarily an instance of Error because we use deepExtend
            // if (entry.error.originalError instanceof Error) {
            entry.originalError = entry.error.originalError;
            delete entry.error.originalError;
            entry.originalMessage = entry.originalError.message;
            entry.stack = entry.originalError.stack;
        } else {
            entry.stack = entry.error.stack;
        }
    }
    var application = config.get('application:name');
    if (application) {
        entry.application = application;
    }
    if (process.env.HOSTNAME) {
        entry.host = process.env.HOSTNAME;
    }
    if (entry.request) {
        var request = entry.request;
        // utils.deepExtends adds undefined values and we do not want to clutter our logs with undefined
        if (request.header && request.headers['user-agent']) {
            entry.agent = request.headers['user-agent'];
        }
        if (request.ip) {
            entry.ip = request.ip;
        }
        if (request.query) {
            entry.query = request.query;
        }
        if (request.trace) {
            entry.trace = request.trace;
        }
        if (request.url) {
            entry.url = request.url;
        }
        delete entry.request;
    }
    // entry.date = (new Date()).toISOString();
    // Note: such an entry is not only ready to print to console but also to be sent as JSON
    return entry;
}

/**
* Print a log entry to the console
* Note: we have discarded pretty solutions because they do not print well in Webstorm console
* @param entry
* @param label
*/
function print(entry, label) {
    /* jshint maxstatements: 48 */
    /* jshint maxcomplexity: 34 */
    var message = (isNaN(Date.parse(entry.date)) ? new Date() : new Date(entry.date)).toISOString();
    message += prefix + label;
    var first = true;
    if (entry.application) {
        message += (first ? prefix : separator) + 'application' + eq + qt + entry.application + qt;
        first = false;
    }
    if (entry.host) {
        message += (first ? prefix : separator) + 'host' + eq + qt + entry.host + qt;
        first = false;
    }
    if (entry.message) {
        message += (first ? prefix : separator) + 'message' + eq + qt + entry.message + qt;
        first = false;
    }
    if (entry.originalMessage) {
        message += (first ? prefix : separator) + 'originalMessage' + eq + qt + entry.originalMessage + qt;
        first = false;
    }
    if (entry.module) {
        message += (first ? prefix : separator) + 'module' + eq + qt + entry.module + qt;
        first = false;
    }
    if (entry.method) {
        message += (first ? prefix : separator) + 'method' + eq + qt + entry.method + qt;
        first = false;
    }
    if (entry.data) {
        try {
            message += (first ? prefix : separator) + 'data' + eq + qt + JSON.stringify(entry.data) + qt;
        } catch (ex) {
            if (typeof entry.data.toString === 'function') {
                message += (first ? prefix : separator) + 'data' + eq + qt + entry.data.toString() + qt;
            }
        }
        first = false;
    }
    if (entry.url) {
        message += (first ? prefix : separator) + 'url' + eq + qt + entry.url + qt;
        first = false;
    }
    if (entry.query) {
        try {
            message += (first ? prefix : separator) + 'query' + eq + qt + JSON.stringify(entry.query) + qt;
        } catch (ex) {
            if (typeof entry.data.toString === 'function') {
                message += (first ? prefix : separator) + 'query' + eq + qt + entry.query.toString() + qt;
            }
        }
        first = false;
    }
    if (entry.trace) {
        message += (first ? prefix : separator) + 'trace' + eq + qt + entry.trace + qt;
        first = false;
    }
    if (entry.ip) {
        message += (first ? prefix : separator) + 'ip' + eq + qt + entry.ip + qt;
        first = false;
    }
    if (entry.agent) {
        message += (first ? prefix : separator) + 'agent' + eq + qt + entry.agent + qt;
        first = false;
    }
    if (entry.stack) {
        message += (first ? prefix : separator) + 'stack' + eq + qt + entry.stack.split('\n').join(', ').replace(/\s+/g, ' ') + qt;
    }
    console.log(message);
    /*
    if (entry.error) {
        console.error(entry.error);
    }
    if (entry.originalError) {
        console.error(entry.originalError);
    }
    */
}

/* jshint +W074 */
/* jshint +W071 */

module.exports = exports = {

    /**
     * Export level for tests
     */
    level: level,

    /**
     * Log a debug entry
     * Only output if debug===true
     * @param entry
     */
    debug: function (entry) {
        if (exports.level > levels.debug) {
            return false;
        }
        print(capture(entry), labels.debug);
        return true;
    },

    /**
     * Log an info entry
     * @param entry
     */
    info: function (entry) {
        if (exports.level > levels.info) {
            return false;
        }
        print(capture(entry), labels.info);
        return true;
    },

    /**
     * Log a warning entry
     * @param entry
     */
    warn: function (entry) {
        if (exports.level > levels.warn) {
            return false;
        }
        print(capture(entry), labels.warn);
        return true;
    },

    /**
     * Log an error entry
     * @param entry
     */
    error: function (entry) {
        if (exports.level > levels.error) {
            return false;
        }
        print(capture(entry), labels.error);
        return true;
    },

    /**
     * Log a critical entry
     * @param entry
     */
    critical: function (entry) {
        if (exports.level > levels.critical) {
            return false;
        }
        print(capture(entry), labels.critical);
        return true;
    },

    /**
     * Shortcut for critical
     */
    crit: function(entry) {
        exports.critical(entry);
    }

};
<|endoftext|>


<commit_before>/**
*
* s.Comm ---
* allows us to compartmentalize all interactions
* with the server to this class (s.Comm) --this class
* is the only place that holds the logic that allows
* the client to communicate with the server.
*
**/

s.Comm = new Class( {

    extend: s.EventEmitter,

    toString: "Comm",

    // makeTrigger is responsible for broadcasting all events

    // receieved from the server to the rest of the game.

    makeTrigger: function ( evt ) {
        var that = this;

        return function ( message ) {

            that.trigger.call( that, evt, message );

        };

    },

    destruct: function ( ) {

        // TODO: Send server some kind of destruct message?

    },

    construct: function ( options ) {

        //binding the game's context

        this.game = options.game;

        // Prepend http. Doing this so that you can customize the server before finalizing the string.

        options.server = 'http://' + options.server;

        this.player = options.player;

        this.ship = options.ship;

        this.pilot = options.pilot;

        this.room = options.room;

        var that = this;

        this.lastMessageTime = new Date( ).getTime( );

        // Create socket connection

        this.socket = io.connect( options.server );

        this.socket.on( 'join', this.makeTrigger( 'join' ) );

        this.socket.on( 'failed', function ( message ) {
            // try to reconnect
            that.connected( );
        } );

        this.socket.on( 'player list', this.makeTrigger( 'player list' ) );

        this.socket.on( 'leave', this.makeTrigger( 'leave' ) );

        this.socket.on( 'move', this.makeTrigger( 'move' ) );

        this.socket.on(' killed', this.makeTrigger( 'killed' ));

        this.socket.on( 'fire', this.makeTrigger( 'fire' ));

        this.socket.on( 'hit', this.makeTrigger( 'hit' ));

        this.socket.on( 'sync', this.makeTrigger( 'sync'));

        this.game.hook( this.position );

        this.clockTick = this.clockTick.bind(this);

        this.timer = setInterval(this.clockTick,1000);

        this.time = 0;

    },

    connected: function ( ) {

        var time = new Date( ).getTime( );

        var shipPosition = this.game.player.getPositionPacket( );
        var packet = {
            room: this.room,

            evt: 'joined',

            name: this.pilot.name,

            time: time,

            pos: shipPosition.pos,

            rot: shipPosition.rot,

            aVeloc: shipPosition.aVeloc,

            lVeloc: shipPosition.lVeloc,

        };

        // Broadcast position

        this.socket.emit('join', packet );

    },

    position: function ( ) {

        var time = new Date( ).getTime( );

        // Never send faster than server can handle

        if ( time - s.game.comm.lastMessageTime >= 700 ) {

            var shipPosition = s.game.player.getPositionPacket( );

            // TODO: Figure out if ship or turret actually moved

            // If ship moved, send packet

            if ( this.lastPosition !== shipPosition.pos ) {

                // Build packet

                this.time = 0;

                var packet = {

                    time: time,

                    pos: shipPosition.pos,

                    rot: shipPosition.rot,

                    aVeloc: shipPosition.aVeloc,

                    lVeloc: shipPosition.lVeloc

                };

                // Broadcast position

                s.game.comm.socket.emit( 'combat','move', packet );

                s.game.comm.lastMessageTime = time;

                this.lastPosition = shipPosition.pos;

            }
        }
    },

    fire: function( pos, rot, velocity ) {

        this.time = 0;

        this.socket.emit( 'combat','fire', {

            position: pos,

            rotation: rot,

            initialVelocity: velocity

        });
    },

    died: function( you, killer ) {

        this.socket.emit( 'player','killed',{

            you: you,

            killer: killer

             });

    },

    hit: function( otherPlayerName, yourName ) {

        this.time = 0;

        this.socket.emit( 'combat','hit', {

            otherPlayerName: otherPlayerName,

            yourName: yourName

        });
    },

    clockTick: function( ){
        this.time += 1;
        // if ( this.time >= 60 ){
        //     window.location.href = "http://satellite-game.com";
        // }
    }
} );
<commit_msg>s.Comm altered to support sending keys<commit_after>/**
*
* s.Comm ---
* allows us to compartmentalize all interactions
* with the server to this class (s.Comm) --this class
* is the only place that holds the logic that allows
* the client to communicate with the server.
*
**/

s.Comm = new Class( {

    extend: s.EventEmitter,

    toString: "Comm",

    // makeTrigger is responsible for broadcasting all events

    // receieved from the server to the rest of the game.

    makeTrigger: function ( evt ) {
        var that = this;

        return function ( message ) {

            that.trigger.call( that, evt, message );

        };

    },

    destruct: function ( ) {

        // TODO: Send server some kind of destruct message?

    },

    construct: function ( options ) {

        //binding the game's context

        this.game = options.game;

        // Prepend http. Doing this so that you can customize the server before finalizing the string.

        options.server = 'http://' + options.server;

        this.player = options.player;

        this.ship = options.ship;

        this.pilot = options.pilot;

        this.room = options.room;

        var that = this;

        this.lastMessageTime = new Date( ).getTime( );

        // Create socket connection

        this.socket = io.connect( options.server );

        this.socket.on( 'join', this.makeTrigger( 'join' ) );

        this.socket.on( 'failed', function ( message ) {
            // try to reconnect
            that.connected( );
        } );

        this.socket.on( 'player list', this.makeTrigger( 'player list' ) );

        this.socket.on( 'leave', this.makeTrigger( 'leave' ) );

        this.socket.on( 'move', this.makeTrigger( 'move' ) );

        this.socket.on(' killed', this.makeTrigger( 'killed' ));

        this.socket.on( 'fire', this.makeTrigger( 'fire' ));

        this.socket.on( 'hit', this.makeTrigger( 'hit' ));

        this.socket.on( 'sync', this.makeTrigger( 'sync'));

        this.game.hook( this.position );

        this.clockTick = this.clockTick.bind(this);

        this.timer = setInterval(this.clockTick,1000);

        this.time = 0;

    },

    connected: function ( ) {

        var time = new Date( ).getTime( );

        var shipPosition = this.game.player.getPositionPacket( );
        var packet = {
            room: this.room,

            evt: 'joined',

            name: this.pilot.name,

            time: time,

            pos: shipPosition.pos,

            rot: shipPosition.rot,

            aVeloc: shipPosition.aVeloc,

            lVeloc: shipPosition.lVeloc,

        };

        // Broadcast position

        this.socket.emit('join', packet );

    },

    position: function ( ) {

        var time = new Date( ).getTime( );

        // Never send faster than server can handle

        if ( time - s.game.comm.lastMessageTime >= 700 ) {

            var shipPosition = s.game.player.getPositionPacket( );

            // TODO: Figure out if ship or turret actually moved

            // If ship moved, send packet

            if ( this.lastPosition !== shipPosition.pos ) {

                // Build packet

                this.time = 0;

                var packet = {

                    time: time,

                    pos: shipPosition.pos,

                    rot: shipPosition.rot,

                    aVeloc: shipPosition.aVeloc,

                    lVeloc: shipPosition.lVeloc

                };

                // Broadcast position

                s.game.comm.socket.emit( 'combat','move', packet );

                s.game.comm.lastMessageTime = time;

                this.lastPosition = shipPosition.pos;

            }
        }
    },

    fire: function( pos, rot, velocity ) {

        this.time = 0;

        this.socket.emit( 'combat','fire', {

            position: pos,

            rotation: rot,

            initialVelocity: velocity

        });
    },

    died: function( you, killer ) {

        this.socket.emit( 'player','killed',{

            you: you,

            killer: killer

             });

    },

    hit: function( otherPlayerName, yourName ) {

        this.time = 0;

        this.socket.emit( 'combat','hit', {

            otherPlayerName: otherPlayerName,

            yourName: yourName

        });
    },

    clockTick: function( ){
        this.time += 1;
        // if ( this.time >= 60 ){
        //     window.location.href = "http://satellite-game.com";
        // }
    },

    sendKey: function(direction, key){
        var time = new Date().getTime();
        // Never send faster than server can handle
        if ( time - s.game.comm.lastMessageTime >= 15 ) {
            var shipPosition = s.game.player.getPositionPacket();
            // TODO: Figure out if ship or turret actually moved
            // If ship moved, send packet
            if ( this.lastPosition !== shipPosition.pos ) {
                // Build packet
                this.time = 0;

                var packet = {
                    time: time,
                    room: this.room,
                    name: this.pilot.name,
                    pos: shipPosition.pos,
                    rot: shipPosition.rot,
                    aVeloc: shipPosition.aVeloc,
                    lVeloc: shipPosition.lVeloc
                };
                // Broadcast position
                this.socket.emit( 'keypress', direction, $.extend(packet, { direction: direction, key: key }) );
                s.game.comm.lastMessageTime = time;
                this.lastPosition = shipPosition.pos;
            }
        }
    }
} );
<|endoftext|>


<commit_before>const { ParamsDef } = Msa.require("params")
const { SheetPerm } = require("./perm")

const sheetParamsDef = new ParamsDef()
sheetParamsDef.add("perm", SheetPerm.newPermParamDef(SheetPerm.READ))

module.exports = { sheetParamsDef }
<commit_msg>user Perm redesign<commit_after>const { ParamsDef } = Msa.require("params")
const { SheetPerm } = require("./perm")

const sheetParamsDef = new ParamsDef()
sheetParamsDef.add("perm", SheetPerm.newPermParamDef({ group:"all", value:SheetPerm.READ }))

module.exports = { sheetParamsDef }
<|endoftext|>


<commit_before>/***
|''Requires''|TiddlySpaceConfig|
***/
//{{{
(function($) {

var cmd = config.commands;
var ns = config.extensions.tiddlyspace;
var fieldStash = {}; // XXX: should not be private!?

cmd.cloneTiddler = {
	text: cmd.editTiddler.text,
	tooltip: "Create a copy of this tiddler in the current space",
	errorMsg: "Error publishing %0: %1",

	isEnabled: function(tiddler) {
		var bag = tiddler.fields["server.bag"];
		if(readOnly) {
			return false;
		} else if(ns.coreBags.contains(bag)) {
			return true;
		} else {
			var space = ns.determineSpace(tiddler, false);
			return space && space.name != ns.currentSpace.name;
		}
	},
	handler: function(ev, src, title) {
		var tiddler = store.getTiddler(title);
		fieldStash[title] = $.extend({}, tiddler.fields);
		tiddler.fields["server.workspace"] = "bags/%0_private".
			format([ns.currentSpace.name]);
		$.each(["bag", "permissions", "page.revision"], function(i, item) {
			delete tiddler.fields["server." + item];
		});
		cmd.editTiddler.handler.apply(this, arguments);
		return false;
	}
};

cmd.editTiddler.isEnabled = function(tiddler) {
	return !cmd.cloneTiddler.isEnabled.apply(this, arguments);
};

// hijack cancelTiddler to restore original fields
var _cancelHandler = cmd.cancelTiddler.handler;
cmd.cancelTiddler.handler = function(ev, src, title) {
	var tiddler = store.getTiddler(title);
	tiddler.fields = fieldStash[title] || tiddler.fields;
	delete fieldStash[title];
	return _cancelHandler.apply(this, arguments);
};

// hijack saveTiddler to clear unused fields stash
cmd.saveTiddler.handler =  function(ev, src, title) {
	var tiddler = store.getTiddler(title);
	delete fieldStash[title];
	return _saveHandler.apply(this, arguments);
};

})(jQuery);
//}}}
<commit_msg>fixed saveTiddler hijack in TiddlySpaceCloneCommand<commit_after>/***
|''Requires''|TiddlySpaceConfig|
***/
//{{{
(function($) {

var cmd = config.commands;
var ns = config.extensions.tiddlyspace;
var fieldStash = {}; // XXX: should not be private!?

cmd.cloneTiddler = {
	text: cmd.editTiddler.text,
	tooltip: "Create a copy of this tiddler in the current space",
	errorMsg: "Error publishing %0: %1",

	isEnabled: function(tiddler) {
		var bag = tiddler.fields["server.bag"];
		if(readOnly) {
			return false;
		} else if(ns.coreBags.contains(bag)) {
			return true;
		} else {
			var space = ns.determineSpace(tiddler, false);
			return space && space.name != ns.currentSpace.name;
		}
	},
	handler: function(ev, src, title) {
		var tiddler = store.getTiddler(title);
		fieldStash[title] = $.extend({}, tiddler.fields);
		tiddler.fields["server.workspace"] = "bags/%0_private".
			format([ns.currentSpace.name]);
		$.each(["bag", "permissions", "page.revision"], function(i, item) {
			delete tiddler.fields["server." + item];
		});
		cmd.editTiddler.handler.apply(this, arguments);
		return false;
	}
};

cmd.editTiddler.isEnabled = function(tiddler) {
	return !cmd.cloneTiddler.isEnabled.apply(this, arguments);
};

// hijack cancelTiddler to restore original fields
var _cancelHandler = cmd.cancelTiddler.handler;
cmd.cancelTiddler.handler = function(ev, src, title) {
	var tiddler = store.getTiddler(title);
	tiddler.fields = fieldStash[title] || tiddler.fields;
	delete fieldStash[title];
	return _cancelHandler.apply(this, arguments);
};

// hijack saveTiddler to clear unused fields stash
var _saveHandler = cmd.saveTiddler.handler;
cmd.saveTiddler.handler =  function(ev, src, title) {
	var tiddler = store.getTiddler(title);
	delete fieldStash[title];
	return _saveHandler.apply(this, arguments);
};

})(jQuery);
//}}}
<|endoftext|>


<commit_before>import Mixin from '@ember/object/mixin';
import { get, getWithDefault, computed } from '@ember/object';
import { inject } from '@ember/service';
import { getOwner } from '@ember/application';
import { scheduleOnce } from '@ember/runloop';
import { setupRouter, reset, whenRouteIdle, whenRoutePainted } from 'ember-app-scheduler';
import { gte } from 'ember-compatibility-helpers';
import { getScrollBarWidth } from './utils/scrollbar-width';

let ATTEMPTS = 0;
const MAX_ATTEMPTS = 100; // rAF runs every 16ms ideally, so 60x a second
let requestId;
let scrollBarWidth = 0;

/**
 * By default, we start checking to see if the document height is >= the last known `y` position
 * we want to scroll to.  This is important for content heavy pages that might try to scrollTo
 * before the content has painted
 *
 * @method tryScrollRecursively
 * @param {Function} fn
 * @param {Object} scrollHash
 * @void
 */
function tryScrollRecursively(fn, scrollHash) {
  const body = document.body;
  const html = document.documentElement;
  // read DOM outside of rAF
  const documentWidth = Math.max(body.scrollWidth, body.offsetWidth,
    html.clientWidth, html.scrollWidth, html.offsetWidth);
  const documentHeight = Math.max(body.scrollHeight, body.offsetHeight,
    html.clientHeight, html.scrollHeight, html.offsetHeight);
  const { innerHeight, innerWidth } = window;

  requestId = window.requestAnimationFrame(() => {
    // write DOM (scrollTo causes reflow)
    if (documentWidth + scrollBarWidth - innerWidth >= scrollHash.x
        && documentHeight + scrollBarWidth - innerHeight >= scrollHash.y
        || ATTEMPTS >= MAX_ATTEMPTS) {
      ATTEMPTS = 0;
      fn.call(null, scrollHash.x, scrollHash.y);
    } else {
        ATTEMPTS++;
        tryScrollRecursively(fn, scrollHash)
    }
  })
}

let RouterScrollMixin = Mixin.create({
  service: inject('router-scroll'),

  isFastBoot: computed(function() {
    const fastboot = getOwner(this).lookup('service:fastboot');
    return fastboot ? fastboot.get('isFastBoot') : false;
  }),

  init() {
    this._super(...arguments);

    setupRouter(this);

    if (gte('3.6.0-beta.1')) {
      this.on('routeWillChange', () => {
        this._routeWillChange();
      });

      this.on('routeDidChange', (transition) => {
        this._routeDidChange(transition);
      });
    }
    if (!get(this, 'isFastBoot')) {
      scrollBarWidth = getScrollBarWidth();
    }
  },

  destroy() {
    reset();

    if (requestId) {
      window.cancelAnimationFrame(requestId);
    }

    this._super(...arguments);
  },

  /**
   * Updates the scroll position
   * it will be a single transition
   * @method updateScrollPosition
   * @param {transition|transition[]} transition If before Ember 3.6, this will be an array of transitions, otherwise
   * @param {Boolean} recursiveCheck -  if "true", check until document height is >= y. `y` is the last coordinate the target page was on
   */
  updateScrollPosition(transition, recursiveCheck) {
    const url = get(this, 'currentURL');
    const hashElement = url ? document.getElementById(url.split('#').pop()) : null;

    if (get(this, 'service.isFirstLoad')) {
      get(this, 'service').unsetFirstLoad();
      return;
    }

    let scrollPosition;

    if (url && url.indexOf('#') > -1 && hashElement) {
      scrollPosition = { x: hashElement.offsetLeft, y: hashElement.offsetTop };
    } else {
      scrollPosition = get(this, 'service.position');
    }

    let preserveScrollPosition;
    if (gte('3.6.0-beta.1')) {
      preserveScrollPosition = getWithDefault(transition, 'router.currentRouteInfos', []).some((routeInfo) => get(routeInfo, 'route.controller.preserveScrollPosition'));
    } else {
      preserveScrollPosition = transition.some((t) => get(t, 'handler.controller.preserveScrollPosition'));
    }

    // If `preserveScrollPosition` was not set on the controller, attempt fallback to `preserveScrollPosition` which was set on the router service.
    if(!preserveScrollPosition) {
      preserveScrollPosition = get(this, 'service.preserveScrollPosition')
    }

    if (!preserveScrollPosition) {
      const scrollElement = get(this, 'service.scrollElement');
      const targetElement = get(this, 'service.targetElement');

      if (targetElement || 'window' === scrollElement) {
        if (recursiveCheck) {
          // our own implementation
          tryScrollRecursively(window.scrollTo, scrollPosition);
        } else {
          // using ember-app-scheduler
          window.scrollTo(scrollPosition.x, scrollPosition.y);
        }
      } else if ('#' === scrollElement.charAt(0)) {
        const element = document.getElementById(scrollElement.substring(1));

        if (element) {
          element.scrollLeft = scrollPosition.x;
          element.scrollTop = scrollPosition.y;
        }
      }
    }
  },

  _routeWillChange() {
    if (get(this, 'isFastBoot')) {
      return;
    }

    get(this, 'service').update();
  },

  _routeDidChange(transition) {
    if (get(this, 'isFastBoot')) {
      return;
    }

    const delayScrollTop = get(this, 'service.delayScrollTop');
    const scrollWhenPainted = get(this, 'service.scrollWhenPainted');
    const scrollWhenIdle = get(this, 'service.scrollWhenIdle');

    if (!delayScrollTop && !scrollWhenPainted && !scrollWhenIdle) {
      // out of the 3 options, this happens on the tightest schedule
      scheduleOnce('render', this, () => this.updateScrollPosition(transition, true));
    } else if (scrollWhenPainted) {
      // as described in ember-app-scheduler, this addon can be used to delay rendering until after First Meaningful Paint.
      // If you loading your routes progressively, this may be a good option to delay scrollTop until the remaining DOM elements are painted.
      whenRoutePainted().then(() => {
        this.updateScrollPosition(transition);
      });
    } else {
      // as described in ember-app-scheduler, this addon can be used to delay rendering until after the route is idle
      whenRouteIdle().then(() => {
        this.updateScrollPosition(transition);
      });
    }
  }
});

if (!gte('3.6.0-beta.1')) {
  RouterScrollMixin = Mixin.create(RouterScrollMixin, {
    willTransition(...args) {
      this._super(...args);

      this._routeWillChange();
    },

    didTransition(transitions, ...args) {
      this._super(transitions, ...args);

      this._routeDidChange(transitions);
    }
  });
}

export default RouterScrollMixin;
<commit_msg>Allow recording position with users first page visit (#225)<commit_after>import Mixin from '@ember/object/mixin';
import { get, getWithDefault, computed } from '@ember/object';
import { inject } from '@ember/service';
import { getOwner } from '@ember/application';
import { scheduleOnce } from '@ember/runloop';
import { setupRouter, reset, whenRouteIdle, whenRoutePainted } from 'ember-app-scheduler';
import { gte } from 'ember-compatibility-helpers';
import { getScrollBarWidth } from './utils/scrollbar-width';

let ATTEMPTS = 0;
const MAX_ATTEMPTS = 100; // rAF runs every 16ms ideally, so 60x a second
let requestId;
let scrollBarWidth = 0;

/**
 * By default, we start checking to see if the document height is >= the last known `y` position
 * we want to scroll to.  This is important for content heavy pages that might try to scrollTo
 * before the content has painted
 *
 * @method tryScrollRecursively
 * @param {Function} fn
 * @param {Object} scrollHash
 * @void
 */
function tryScrollRecursively(fn, scrollHash) {
  const body = document.body;
  const html = document.documentElement;
  // read DOM outside of rAF
  const documentWidth = Math.max(body.scrollWidth, body.offsetWidth,
    html.clientWidth, html.scrollWidth, html.offsetWidth);
  const documentHeight = Math.max(body.scrollHeight, body.offsetHeight,
    html.clientHeight, html.scrollHeight, html.offsetHeight);
  const { innerHeight, innerWidth } = window;

  requestId = window.requestAnimationFrame(() => {
    // write DOM (scrollTo causes reflow)
    if (documentWidth + scrollBarWidth - innerWidth >= scrollHash.x
        && documentHeight + scrollBarWidth - innerHeight >= scrollHash.y
        || ATTEMPTS >= MAX_ATTEMPTS) {
      ATTEMPTS = 0;
      fn.call(null, scrollHash.x, scrollHash.y);
    } else {
        ATTEMPTS++;
        tryScrollRecursively(fn, scrollHash)
    }
  })
}

let RouterScrollMixin = Mixin.create({
  service: inject('router-scroll'),

  isFastBoot: computed(function() {
    const fastboot = getOwner(this).lookup('service:fastboot');
    return fastboot ? fastboot.get('isFastBoot') : false;
  }),

  init() {
    this._super(...arguments);

    setupRouter(this);

    if (gte('3.6.0-beta.1')) {
      this.on('routeWillChange', () => {
        this._routeWillChange();
      });

      this.on('routeDidChange', (transition) => {
        this._routeDidChange(transition);
      });
    }
    if (!get(this, 'isFastBoot')) {
      scrollBarWidth = getScrollBarWidth();
    }
  },

  destroy() {
    reset();

    if (requestId) {
      window.cancelAnimationFrame(requestId);
    }

    this._super(...arguments);
  },

  /**
   * Updates the scroll position
   * it will be a single transition
   * @method updateScrollPosition
   * @param {transition|transition[]} transition If before Ember 3.6, this will be an array of transitions, otherwise
   * @param {Boolean} recursiveCheck -  if "true", check until document height is >= y. `y` is the last coordinate the target page was on
   */
  updateScrollPosition(transition, recursiveCheck) {
    const url = get(this, 'currentURL');
    const hashElement = url ? document.getElementById(url.split('#').pop()) : null;

    if (get(this, 'service.isFirstLoad')) {
      get(this, 'service').unsetFirstLoad();
    }

    let scrollPosition;

    if (url && url.indexOf('#') > -1 && hashElement) {
      scrollPosition = { x: hashElement.offsetLeft, y: hashElement.offsetTop };
    } else {
      scrollPosition = get(this, 'service.position');
    }

    let preserveScrollPosition;
    if (gte('3.6.0-beta.1')) {
      preserveScrollPosition = getWithDefault(transition, 'router.currentRouteInfos', []).some((routeInfo) => get(routeInfo, 'route.controller.preserveScrollPosition'));
    } else {
      preserveScrollPosition = transition.some((t) => get(t, 'handler.controller.preserveScrollPosition'));
    }

    // If `preserveScrollPosition` was not set on the controller, attempt fallback to `preserveScrollPosition` which was set on the router service.
    if(!preserveScrollPosition) {
      preserveScrollPosition = get(this, 'service.preserveScrollPosition')
    }

    if (!preserveScrollPosition) {
      const scrollElement = get(this, 'service.scrollElement');
      const targetElement = get(this, 'service.targetElement');

      if (targetElement || 'window' === scrollElement) {
        if (recursiveCheck) {
          // our own implementation
          tryScrollRecursively(window.scrollTo, scrollPosition);
        } else {
          // using ember-app-scheduler
          window.scrollTo(scrollPosition.x, scrollPosition.y);
        }
      } else if ('#' === scrollElement.charAt(0)) {
        const element = document.getElementById(scrollElement.substring(1));

        if (element) {
          element.scrollLeft = scrollPosition.x;
          element.scrollTop = scrollPosition.y;
        }
      }
    }
  },

  _routeWillChange() {
    if (get(this, 'isFastBoot')) {
      return;
    }

    get(this, 'service').update();
  },

  _routeDidChange(transition) {
    if (get(this, 'isFastBoot')) {
      return;
    }

    const delayScrollTop = get(this, 'service.delayScrollTop');
    const scrollWhenPainted = get(this, 'service.scrollWhenPainted');
    const scrollWhenIdle = get(this, 'service.scrollWhenIdle');

    if (!delayScrollTop && !scrollWhenPainted && !scrollWhenIdle) {
      // out of the 3 options, this happens on the tightest schedule
      scheduleOnce('render', this, () => this.updateScrollPosition(transition, true));
    } else if (scrollWhenPainted) {
      // as described in ember-app-scheduler, this addon can be used to delay rendering until after First Meaningful Paint.
      // If you loading your routes progressively, this may be a good option to delay scrollTop until the remaining DOM elements are painted.
      whenRoutePainted().then(() => {
        this.updateScrollPosition(transition);
      });
    } else {
      // as described in ember-app-scheduler, this addon can be used to delay rendering until after the route is idle
      whenRouteIdle().then(() => {
        this.updateScrollPosition(transition);
      });
    }
  }
});

if (!gte('3.6.0-beta.1')) {
  RouterScrollMixin = Mixin.create(RouterScrollMixin, {
    willTransition(...args) {
      this._super(...args);

      this._routeWillChange();
    },

    didTransition(transitions, ...args) {
      this._super(transitions, ...args);

      this._routeDidChange(transitions);
    }
  });
}

export default RouterScrollMixin;
<|endoftext|>


<commit_before>'use strict';

var SockJS = require('sockjs-client');

var defs = {
	server  		: 'http://83.212.100.253:8080',
	debug  			: false
}

function Surge(options){

	var events = {};
	var channels = {};
	var socket    = null;
	var rconnect = true;
	var recInterval = null;
	var reconnecting = false;
	var buffer = [];

	var o = options || {};

	var url = o.host || defs.server;
	var debug = o.debug || defs.debug;
	var authEndpoint = o.authEndpoint;

	var connection = new Connection();

	//TODO: check if url is ip or not
	socket = _connect();

	_surgeEvents();

	var api = {
		on 					: on,
		subscribe 	: subscribe,
		unsubscribe : unsubscribe,
		disconnect 	: disconnect,
		connect 		: connect,
		emit 				: emit,
		connection  : connection,
		socket  		: socket
	};
	return api;

	function on(name,callback){
    if(!events[name]) {
    	events[name] = [];
    }
    // Append event
    events[name].push(callback);
  };

	function subscribe(room){
		emit('surge-subscribe',{room:room});
		var channel = new Channel(room);
		channels[room] = channel;
		return channel;
	};
	function unsubscribe(room){
		emit('surge-unsubscribe',{room:room});
	};
	function disconnect(){
		rconnect = false;
		socket.close();
		buffer = [];
	};

	function connect(){
    socket = _connect();
    _surgeEvents();
	}

	function emit(channel,name,data){
		var data = {};

		if(arguments.length<2){
			console.error('emit needs at least 2 arguments');
			return;
		}

		data.name = arguments[arguments.length-2];
		data.message = arguments[arguments.length-1];
		data.channel = arguments.length === 3 ? arguments[0] : undefined;

		if(socket){
			if(debug===true){
				console.log('Surge : Event sent : ' + JSON.stringify(data));
			}
			socket.emit(data);
		}
		else{
			if(debug===true){
				console.log('Surge : Event buffered : ' + JSON.stringify(data));
			}
			buffer.push(JSON.stringify(data));
		}
	};

	function _connect(){
		if(socket) {
        // Get auto-reconnect and re-setup
        connection.state = 'connecting';
        var p = rconnect;
        disconnect();
        rconnect = p;
    }
		connection.state='connecting';
		return new SockJS(url);
	};

	function _catchEvent(response) {
		var name = response.name,
		data = response.data;
		var _events = events[name];
		if(_events) {
			var parsed = (typeof(data) === "object" && data !== null) ? data : data;
			for(var i=0, l=_events.length; i<l; ++i) {
				var fct = _events[i];
				if(typeof(fct) === "function") {
					// Defer call on setTimeout
					(function(f) {
					    setTimeout(function() {f(parsed);}, 0);
					})(fct);
				}
			}
		}
	};
	//Private functions
	function _surgeEvents(){
    on('surge-joined-room',function(room){
    	alert("running");
	  	if(!connection.inRoom(room)){
	  		connection.rooms.push(room);
	  		channels[room].state = 'connected';

	  		//TODO: introduce private channels
	  		channels[room].type = 'public';
			}
		});
		on('surge-left-room',function(room){
			if(connection.inRoom(room)){
				connection.rooms.splice(connection.rooms.indexOf(room), 1);

				channels[room].state = 'connected';
				channels[room].on = null;
			}
		});
		on('open',function(data){
			console.log('Socket id is : '+data);
			socket.id = data;
		})
		socket.onopen = function() {
			connection.state = 'connected';
			//In case of reconnection, resubscribe to rooms
			if(reconnecting){
				reconnecting = false;
				reconnect();
			}
			else{
				flushBuffer();
			}
		};
		socket.onclose = function() {
			socket = null;
			_catchEvent({name:'close',data:{}});
			if(rconnect){
				connection.state='attempting reconnection';
				reconnecting = true;
				recInterval = setInterval(function() {
					socket = connect();
					clearInterval(recInterval);
					_surgeEvents();
				}, 2000);
			}
			else{
				connection.state = 'disconnected';
			}
		};
		socket.onmessage = function (e) {
			if(!e.data){
				console.info('no data received');
				return;
			}
			var data = JSON.parse(e.data);
			if(debug===true){
				console.log('Surge : Event received : ' + e.data);
			}
			_catchEvent(data);
		};
		socket.emit = function (data){
			if(connection.state==='connected'){
				this.send(JSON.stringify(data));
			}
			else{
				//enter to buffer
				buffer.push(JSON.stringify(data));
			}

		}

		function reconnect(){
			//resubscribe to rooms
			for (var i = connection.rooms.length - 1; i >= 0; i--) {
				subscribe(connection.rooms[i]);
			};
			//send all events that were buffered
			flushBuffer();
		}
	}
	function flushBuffer(){
		if(buffer.length>0){
			for (var i = 0; i < buffer.length; i++) {
				console.log('sending message from buffer : '+buffer[i]);
				socket.send(buffer[i]);
			};
			buffer = [];
		}
	}
	function Channel(room){
		this.room = room;
		this.state = 'initializing';
		this.type = 'initializing';//public,private
		this.unsubscribe = function(){
			emit('surge-unsubscribe',{room:this.room});
		}
	}
};

//	Connection class
//	Keeps details regarding the connection state,rooms,.etc
function Connection(){
	this.rooms  = [];
	this.state 	= 'not initialized';
}

Connection.prototype.inRoom = function(room){
	return this.rooms.indexOf(room)>=0 ? true:false;
}

module.exports = Surge;<commit_msg>removed alert<commit_after>'use strict';

var SockJS = require('sockjs-client');

var defs = {
	server  		: 'http://83.212.100.253:8080',
	debug  			: false
}

function Surge(options){

	var events = {};
	var channels = {};
	var socket    = null;
	var rconnect = true;
	var recInterval = null;
	var reconnecting = false;
	var buffer = [];

	var o = options || {};

	var url = o.host || defs.server;
	var debug = o.debug || defs.debug;
	var authEndpoint = o.authEndpoint;

	var connection = new Connection();

	//TODO: check if url is ip or not
	socket = _connect();

	_surgeEvents();

	var api = {
		on 					: on,
		subscribe 	: subscribe,
		unsubscribe : unsubscribe,
		disconnect 	: disconnect,
		connect 		: connect,
		emit 				: emit,
		connection  : connection,
		socket  		: socket
	};
	return api;

	function on(name,callback){
    if(!events[name]) {
    	events[name] = [];
    }
    // Append event
    events[name].push(callback);
  };

	function subscribe(room){
		emit('surge-subscribe',{room:room});
		var channel = new Channel(room);
		channels[room] = channel;
		return channel;
	};
	function unsubscribe(room){
		emit('surge-unsubscribe',{room:room});
	};
	function disconnect(){
		rconnect = false;
		socket.close();
		buffer = [];
	};

	function connect(){
    socket = _connect();
    _surgeEvents();
	}

	function emit(channel,name,data){
		var data = {};

		if(arguments.length<2){
			console.error('emit needs at least 2 arguments');
			return;
		}

		data.name = arguments[arguments.length-2];
		data.message = arguments[arguments.length-1];
		data.channel = arguments.length === 3 ? arguments[0] : undefined;

		if(socket){
			if(debug===true){
				console.log('Surge : Event sent : ' + JSON.stringify(data));
			}
			socket.emit(data);
		}
		else{
			if(debug===true){
				console.log('Surge : Event buffered : ' + JSON.stringify(data));
			}
			buffer.push(JSON.stringify(data));
		}
	};

	function _connect(){
		if(socket) {
        // Get auto-reconnect and re-setup
        connection.state = 'connecting';
        var p = rconnect;
        disconnect();
        rconnect = p;
    }
		connection.state='connecting';
		return new SockJS(url);
	};

	function _catchEvent(response) {
		var name = response.name,
		data = response.data;
		var _events = events[name];
		if(_events) {
			var parsed = (typeof(data) === "object" && data !== null) ? data : data;
			for(var i=0, l=_events.length; i<l; ++i) {
				var fct = _events[i];
				if(typeof(fct) === "function") {
					// Defer call on setTimeout
					(function(f) {
					    setTimeout(function() {f(parsed);}, 0);
					})(fct);
				}
			}
		}
	};
	//Private functions
	function _surgeEvents(){
    on('surge-joined-room',function(room){
	  	if(!connection.inRoom(room)){
	  		connection.rooms.push(room);
	  		channels[room].state = 'connected';

	  		//TODO: introduce private channels
	  		channels[room].type = 'public';
			}
		});
		on('surge-left-room',function(room){
			if(connection.inRoom(room)){
				connection.rooms.splice(connection.rooms.indexOf(room), 1);

				channels[room].state = 'connected';
				channels[room].on = null;
			}
		});
		on('open',function(data){
			console.log('Socket id is : '+data);
			socket.id = data;
		})
		socket.onopen = function() {
			connection.state = 'connected';
			//In case of reconnection, resubscribe to rooms
			if(reconnecting){
				reconnecting = false;
				reconnect();
			}
			else{
				flushBuffer();
			}
		};
		socket.onclose = function() {
			socket = null;
			_catchEvent({name:'close',data:{}});
			if(rconnect){
				connection.state='attempting reconnection';
				reconnecting = true;
				recInterval = setInterval(function() {
					socket = connect();
					clearInterval(recInterval);
					_surgeEvents();
				}, 2000);
			}
			else{
				connection.state = 'disconnected';
			}
		};
		socket.onmessage = function (e) {
			if(!e.data){
				console.info('no data received');
				return;
			}
			var data = JSON.parse(e.data);
			if(debug===true){
				console.log('Surge : Event received : ' + e.data);
			}
			_catchEvent(data);
		};
		socket.emit = function (data){
			if(connection.state==='connected'){
				this.send(JSON.stringify(data));
			}
			else{
				//enter to buffer
				buffer.push(JSON.stringify(data));
			}

		}

		function reconnect(){
			//resubscribe to rooms
			for (var i = connection.rooms.length - 1; i >= 0; i--) {
				subscribe(connection.rooms[i]);
			};
			//send all events that were buffered
			flushBuffer();
		}
	}
	function flushBuffer(){
		if(buffer.length>0){
			for (var i = 0; i < buffer.length; i++) {
				console.log('sending message from buffer : '+buffer[i]);
				socket.send(buffer[i]);
			};
			buffer = [];
		}
	}
	function Channel(room){
		this.room = room;
		this.state = 'initializing';
		this.type = 'initializing';//public,private
		this.unsubscribe = function(){
			emit('surge-unsubscribe',{room:this.room});
		}
	}
};

//	Connection class
//	Keeps details regarding the connection state,rooms,.etc
function Connection(){
	this.rooms  = [];
	this.state 	= 'not initialized';
}

Connection.prototype.inRoom = function(room){
	return this.rooms.indexOf(room)>=0 ? true:false;
}

module.exports = Surge;<|endoftext|>