<commit_before>import React from 'react';
import classNames from 'classnames';
import { connect } from 'react-redux';
import $ from 'jquery/dist/jquery.slim';
import ColorPicker from 'react-simple-colorpicker';

import * as actions from '../../../actions';
import * as libs from '../../../lib';

import Button from './Button';
import EditLayoutSetting from './EditLayoutSetting';

class Toolbar extends React.Component {

	static displayName = 'Toolbar';

	static defaultProps = {
		dispatch: null,
		tree: null,
	};

	constructor(props)
	{
		super(props);

		this.state = {
			active: {
				setting: false,
				editBlockColor: false,
			},
			visible: {
				setting: true,
				shuffle: true,
				add: true,
				select: true,
				edit: false,
				removeImage: false,
				duplicate: false,
				removeBlock: false,
				editColor: false
			}
		}
	}

	componentWillReceiveProps(nextProps)
	{
		const { state, props } = this;

		let newState = Object.assign({}, state);
		let updated = false;

		// select block
		if (props.tree.body.activeBlock.length !== nextProps.tree.body.activeBlock.length)
		{
			let active = !!(nextProps.tree.body.activeBlock.length);
			newState.visible = Object.assign({}, newState.visible, {
				edit: false,
				removeImage: false,
				duplicate: active,
				removeBlock: active,
				editColor: active
			});
			updated = true;
		}

		if (nextProps.tree.body.activeBlock[0])
		{
			// check image block
			let isImage = false;
			nextProps.tree.body.activeBlock.some(k => {
				if (nextProps.tree.body.grid[k].image)
				{
					isImage = true;
					return true;
				}
			});

			// select image block
			let block = nextProps.tree.body.grid[nextProps.tree.body.activeBlock[0]];
			newState.visible = Object.assign({}, newState.visible, {
				removeImage: isImage,
				edit: !!(block && block.image)
			});
			updated = true;
		}

		if (updated)
		{
			this.setState(newState);
		}
	}

	changeActive(keyName, userSW, event)
	{
		const { state } = this;
		const sw = userSW || !state.active[keyName];
		const cTarget = event ? event.currentTarget : null;

		if (sw)
		{
			$(document).on('click.pleToolbar', (e) => {
				if ($(e.target).closest('.ple-toolbar__pop').length) return;
				if (!(e.target === cTarget) && !(e.target.parentNode === cTarget))
				{
					this.changeActive(keyName, false);
				}
			});
		}
		else
		{
			$(document).off('click.pleToolbar');
		}

		this.setState({
			active: {
				...state.active,
				setting: false,
				editColor: false,
				[keyName] : sw,
			}
		});
	}

	deactivate()
	{
		$(document).off('click.pleToolbar');
		return new Promise((reject) => {
			this.setState({
				active: {
					setting: false,
					editColor: false,
				}
			}, reject);
		});
	}

	submitEditSetting(state)
	{
		this.props.dispatch(actions.body.updateSetting(state));
		this.changeActive('setting', false);
		return false;
	}

	render()
	{
		const { state, props } = this;
		let activeBlockColor = '#fff';

		if (typeof props.tree.body.grid === 'object' && libs.object.isArray(props.tree.body.activeBlock))
		{
			const n = props.tree.body.activeBlock[0];
			activeBlockColor = (props.tree.body.grid[n] && props.tree.body.grid[n].color) ?
				props.tree.body.grid[n].color :
				props.setting.body.blockColor;
		}

		return (

					{state.visible.setting && (
						<Button
							iconClass="ple-ico-setting"
							className={classNames('ple-edit-setting', {
								'ple-toolbar__block-active': state.active.setting
							})}
							onClick={(e) => {
								e.persist();
								if (!state.active.setting)
								{
									this.deactivate().then(() => {
										this.changeActive('setting', null, e);
									});
								}
							}}
							title="Edit preference">
							<EditLayoutSetting
								submit={(e) => this.submitEditSetting(e)}
								setting={props.tree.body.setting}
								defaultSetting={props.setting.body.setting}/>
						</Button>
					)}
					{state.visible.shuffle && (
						<Button
							iconClass="ple-ico-arrow-random"
							onClick={() => props.api.grid.shuffle()}
							title="Shuffle block"/>
					)}
					{state.visible.add && (
						<Button
							iconClass="ple-ico-plus"
							onClick={() => props.api.grid.add()}
							title="Add block"/>
					)}
					{state.visible.select && (
						<Button
							iconClass="ple-ico-select"
							onClick={() => props.api.grid.toggleSelectAll()}
							title="Toggle select block"/>
					)}

					{state.visible.edit && (
						<Button
							iconClass="ple-ico-pencil"
							className="ple-toolbar__block-key"
							onClick={() => props.api.cropper.open(props.tree.body.activeBlock[0])}
							title="Edit block"/>
					)}
					{state.visible.removeImage && (
						<Button
							iconClass="ple-ico-empty"
							className="ple-toolbar__block-key"
							onClick={() => props.api.grid.removeImages(props.tree.body.activeBlock)}
							title="Remove image in block"/>
					)}
					{state.visible.duplicate && (
						<Button
							iconClass="ple-ico-duplicate"
							className="ple-toolbar__block-key"
							onClick={() => {
								if (props.tree.body.activeBlock === null)
								{
									alert('Not found select block');
									return;
								}
								props.dispatch(actions.body.duplicateBlock(props.tree.body.activeBlock));
							}}
							title="Duplicate block"/>
					)}
					{state.visible.removeBlock && (
						<Button
							iconClass="ple-ico-trash"
							className="ple-toolbar__block-key"
							onClick={() => {
								if (props.tree.body.activeBlock === null)
								{
									alert('Not found select block');
									return;
								}
								props.api.grid.remove(props.tree.body.activeBlock);
							}}
							title="Remove block"/>
					)}
					{state.visible.editColor && (
						<Button
							iconClass="ple-ico-palette"
							className={classNames(
								'ple-edit-color',
								'ple-toolbar__block-key',
								{ 'ple-toolbar__block-active': state.active.editColor }
							)}
							onClick={(e) => {
								e.persist();
								if (!state.active.editColor)
								{
									this.deactivate().then(() => this.changeActive('editColor', null, e));
								}
							}}
							title="Change color">

								<ColorPicker
									onChange={(color) => {
										if (!color) return;
										props.dispatch(actions.body.changeColorBlock(props.tree.body.activeBlock, color));
									}}
									color={activeBlockColor}
									className="ple-colorPicker__body"/>

						</Button>
					)}

		);
	}

}

export default connect((state) => Object.assign({}, state, {}))(Toolbar);<commit_msg>#11 설정 팔레트 안닫히는 현상 수정<commit_after>import React from 'react';
import classNames from 'classnames';
import { connect } from 'react-redux';
import $ from 'jquery/dist/jquery.slim';
import ColorPicker from 'react-simple-colorpicker';

import * as actions from '../../../actions';
import * as libs from '../../../lib';

import Button from './Button';
import EditLayoutSetting from './EditLayoutSetting';

class Toolbar extends React.Component {

	static displayName = 'Toolbar';

	static defaultProps = {
		dispatch: null,
		tree: null,
	};

	constructor(props)
	{
		super(props);

		this.state = {
			active: {
				setting: false,
				editBlockColor: false,
			},
			visible: {
				setting: true,
				shuffle: true,
				add: true,
				select: true,
				edit: false,
				removeImage: false,
				duplicate: false,
				removeBlock: false,
				editColor: false
			}
		}
	}

	componentWillReceiveProps(nextProps)
	{
		const { state, props } = this;

		let newState = Object.assign({}, state);
		let updated = false;

		// select block
		if (props.tree.body.activeBlock.length !== nextProps.tree.body.activeBlock.length)
		{
			let active = !!(nextProps.tree.body.activeBlock.length);
			newState.visible = Object.assign({}, newState.visible, {
				edit: false,
				removeImage: false,
				duplicate: active,
				removeBlock: active,
				editColor: active
			});
			updated = true;
		}

		if (nextProps.tree.body.activeBlock[0])
		{
			// check image block
			let isImage = false;
			nextProps.tree.body.activeBlock.some(k => {
				if (nextProps.tree.body.grid[k].image)
				{
					isImage = true;
					return true;
				}
			});

			// select image block
			let block = nextProps.tree.body.grid[nextProps.tree.body.activeBlock[0]];
			newState.visible = Object.assign({}, newState.visible, {
				removeImage: isImage,
				edit: !!(block && block.image)
			});
			updated = true;
		}

		if (updated)
		{
			this.setState(newState);
		}
	}

	changeActive(keyName, userSW, event)
	{
		const { state } = this;
		const sw = userSW || !state.active[keyName];
		const cTarget = event ? event.currentTarget : null;

		if (sw)
		{
			$(document).on('click.pleToolbar', (e) => {
				if ($(e.target).closest('.ple-toolbar__pop').length) return;
				if (!(e.target === cTarget) && !(e.target.parentNode === cTarget))
				{
					this.changeActive(keyName, false);
				}
			});
		}
		else
		{
			$(document).off('click.pleToolbar');
		}

		this.setState({
			active: {
				...state.active,
				setting: false,
				editColor: false,
				[keyName] : sw,
			}
		});
	}

	deactivate()
	{
		$(document).off('click.pleToolbar');
		return new Promise((reject) => {
			this.setState({
				active: {
					setting: false,
					editColor: false,
				}
			}, reject);
		});
	}

	/**
	 * Submit edit setting
	 *
	 * @param {Object} state
	 * @return {Boolean}
	 */
	submitEditSetting(state)
	{
		// update setting
		this.props.dispatch(actions.body.updateSetting(state));

		// close palette
		libs.util.sleep(50).then(() => this.changeActive('setting', false));

		return false;
	}

	render()
	{
		const { state, props } = this;
		let activeBlockColor = '#fff';

		if (typeof props.tree.body.grid === 'object' && libs.object.isArray(props.tree.body.activeBlock))
		{
			const n = props.tree.body.activeBlock[0];
			activeBlockColor = (props.tree.body.grid[n] && props.tree.body.grid[n].color) ?
				props.tree.body.grid[n].color :
				props.setting.body.blockColor;
		}

		return (

					{state.visible.setting && (
						<Button
							iconClass="ple-ico-setting"
							className={classNames('ple-edit-setting', {
								'ple-toolbar__block-active': state.active.setting
							})}
							onClick={(e) => {
								e.persist();
								if (!state.active.setting)
								{
									this.deactivate().then(() => {
										this.changeActive('setting', null, e);
									});
								}
							}}
							title="Edit preference">
							<EditLayoutSetting
								submit={(e) => this.submitEditSetting(e)}
								setting={props.tree.body.setting}
								defaultSetting={props.setting.body.setting}/>
						</Button>
					)}
					{state.visible.shuffle && (
						<Button
							iconClass="ple-ico-arrow-random"
							onClick={() => props.api.grid.shuffle()}
							title="Shuffle block"/>
					)}
					{state.visible.add && (
						<Button
							iconClass="ple-ico-plus"
							onClick={() => props.api.grid.add()}
							title="Add block"/>
					)}
					{state.visible.select && (
						<Button
							iconClass="ple-ico-select"
							onClick={() => props.api.grid.toggleSelectAll()}
							title="Toggle select block"/>
					)}

					{state.visible.edit && (
						<Button
							iconClass="ple-ico-pencil"
							className="ple-toolbar__block-key"
							onClick={() => props.api.cropper.open(props.tree.body.activeBlock[0])}
							title="Edit block"/>
					)}
					{state.visible.removeImage && (
						<Button
							iconClass="ple-ico-empty"
							className="ple-toolbar__block-key"
							onClick={() => props.api.grid.removeImages(props.tree.body.activeBlock)}
							title="Remove image in block"/>
					)}
					{state.visible.duplicate && (
						<Button
							iconClass="ple-ico-duplicate"
							className="ple-toolbar__block-key"
							onClick={() => {
								if (props.tree.body.activeBlock === null)
								{
									alert('Not found select block');
									return;
								}
								props.dispatch(actions.body.duplicateBlock(props.tree.body.activeBlock));
							}}
							title="Duplicate block"/>
					)}
					{state.visible.removeBlock && (
						<Button
							iconClass="ple-ico-trash"
							className="ple-toolbar__block-key"
							onClick={() => {
								if (props.tree.body.activeBlock === null)
								{
									alert('Not found select block');
									return;
								}
								props.api.grid.remove(props.tree.body.activeBlock);
							}}
							title="Remove block"/>
					)}
					{state.visible.editColor && (
						<Button
							iconClass="ple-ico-palette"
							className={classNames(
								'ple-edit-color',
								'ple-toolbar__block-key',
								{ 'ple-toolbar__block-active': state.active.editColor }
							)}
							onClick={(e) => {
								e.persist();
								if (!state.active.editColor)
								{
									this.deactivate().then(() => this.changeActive('editColor', null, e));
								}
							}}
							title="Change color">

								<ColorPicker
									onChange={(color) => {
										if (!color) return;
										props.dispatch(actions.body.changeColorBlock(props.tree.body.activeBlock, color));
									}}
									color={activeBlockColor}
									className="ple-colorPicker__body"/>

						</Button>
					)}

		);
	}

}

export default connect((state) => Object.assign({}, state, {}))(Toolbar);<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 * @format
 */

'use strict';

import Platform from '../Utilities/Platform';
import typeof AnimatedFlatList from './components/AnimatedFlatList';
import typeof AnimatedImage from './components/AnimatedImage';
import typeof AnimatedScrollView from './components/AnimatedScrollView';
import typeof AnimatedSectionList from './components/AnimatedSectionList';
import typeof AnimatedText from './components/AnimatedText';
import typeof AnimatedView from './components/AnimatedView';

const AnimatedMock = require('./AnimatedMock');
const AnimatedImplementation = require('./AnimatedImplementation');

const Animated = ((Platform.isTesting ||
(Platform.OS === 'android' && global.RN$Bridgeless)
  ? AnimatedMock
  : AnimatedImplementation): typeof AnimatedMock);

module.exports = {
  get FlatList(): AnimatedFlatList {
    return require('./components/AnimatedFlatList');
  },
  get Image(): AnimatedImage {
    return require('./components/AnimatedImage');
  },
  get ScrollView(): AnimatedScrollView {
    return require('./components/AnimatedScrollView');
  },
  get SectionList(): AnimatedSectionList {
    return require('./components/AnimatedSectionList');
  },
  get Text(): AnimatedText {
    return require('./components/AnimatedText');
  },
  get View(): AnimatedView {
    return require('./components/AnimatedView');
  },
  ...Animated,
};
<commit_msg>Re-enable animations on Android<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 * @format
 */

'use strict';

import Platform from '../Utilities/Platform';
import typeof AnimatedFlatList from './components/AnimatedFlatList';
import typeof AnimatedImage from './components/AnimatedImage';
import typeof AnimatedScrollView from './components/AnimatedScrollView';
import typeof AnimatedSectionList from './components/AnimatedSectionList';
import typeof AnimatedText from './components/AnimatedText';
import typeof AnimatedView from './components/AnimatedView';

const AnimatedMock = require('./AnimatedMock');
const AnimatedImplementation = require('./AnimatedImplementation');

const Animated = ((Platform.isTesting
  ? AnimatedMock
  : AnimatedImplementation): typeof AnimatedMock);

module.exports = {
  get FlatList(): AnimatedFlatList {
    return require('./components/AnimatedFlatList');
  },
  get Image(): AnimatedImage {
    return require('./components/AnimatedImage');
  },
  get ScrollView(): AnimatedScrollView {
    return require('./components/AnimatedScrollView');
  },
  get SectionList(): AnimatedSectionList {
    return require('./components/AnimatedSectionList');
  },
  get Text(): AnimatedText {
    return require('./components/AnimatedText');
  },
  get View(): AnimatedView {
    return require('./components/AnimatedView');
  },
  ...Animated,
};
<|endoftext|>


<commit_before>(function() {

var checkVersion = Dagaz.Model.checkVersion;

Dagaz.Model.checkVersion = function(design, name, value) {
  if (name != "sovereign-chess-promotion") {
     checkVersion(design, name, value);
  }
}

var PostProcessing = Dagaz.Model.PostProcessing;

Dagaz.Model.PostProcessing = function(board, moves) {
  var design = Dagaz.Model.design;
  var player = board.getValue(board.player);
  if (player === null) {
      player = board.player;
  }
  var king = null;
  _.each(design.allPositions(), function(pos) {
      if (king !== null) return;
      var piece = board.getPiece(pos);
      if (piece === null) return;
      if (piece.player != player) return;
      if (piece.type != design.getPieceType("King")) return;
      king = pos;
  });
  if (king !== null) {
      _.each(moves, function(move) {
          if (move.actions.length < 1) return;
          if (move.actions[0][0] === null) return;
          if (move.actions[0][1] === null) return;
          if (move.actions[0][2] === null) return;
          var piece = move.actions[0][2][0];
          if (piece.type != design.getPieceType("King")) return;
          move.capturePiece(king);
          if (piece.player != player) {
              move.setValue(board.player, piece.player);
          }
      });
  }
  if (!_.isUndefined(PostProcessing)) {
      PostProcessing(board, moves);
  }
}

var CheckInvariants = Dagaz.Model.CheckInvariants;

Dagaz.Model.CheckInvariants = function(board) {
  var design = Dagaz.Model.design;
  var pawn   = design.getPieceType("Pawn");
  _.each(board.moves, function(move) {
      if (move.actions.length < 1) return;
      if (move.actions[0][0] === null) return;
      if (move.actions[0][1] === null) return;
      if (move.actions[0][2] === null) return;
      var pos = move.actions[0][0][0];
      var piece = board.getPiece(pos);
      if ((piece !== null) && (piece.type == pawn) && design.inZone(0, 1, move.actions[0][1][0])) {
          piece = move.actions[0][2][0];
          var pieces = [];
          pieces.push(piece.promote(design.getPieceType("Bishop")));
          pieces.push(piece.promote(design.getPieceType("Knight")));
          pieces.push(piece.promote(design.getPieceType("Rook")));
          pieces.push(piece.promote(design.getPieceType("Queen")));
          pieces.push(piece.promote(design.getPieceType("King")));
          move.actions[0][2] = pieces;
      }
  });
  CheckInvariants(board);
}

})();
<commit_msg>Sovereign Chess (promotion fixed)<commit_after>(function() {

var checkVersion = Dagaz.Model.checkVersion;

Dagaz.Model.checkVersion = function(design, name, value) {
  if (name != "sovereign-chess-promotion") {
     checkVersion(design, name, value);
  }
}

Dagaz.Model.moveToString = function(move) {
  var r = "";
  _.each(move.actions, function(a) {
      if (a[1] === null) return;
      if (r != "") {
          r = r + " ";
      }
      if (a[0] != null) {
          r = r + Dagaz.Model.posToString(a[0][0]);
          if (a[1] !== null) {
              r = r + ' - ';
          }
      }
      if (a[1] !== null) {
          r = r + Dagaz.Model.posToString(a[1][0]);
      }
      if ((a[2] !== null) && ((a[0] != null) || (a[1] !== null))) {
          r = r + " " + a[2][0].toString();
      }
  });
  return r;
}

var PostProcessing = Dagaz.Model.PostProcessing;

Dagaz.Model.PostProcessing = function(board, moves) {
  var design = Dagaz.Model.design;
  var player = board.getValue(board.player);
  if (player === null) {
      player = board.player;
  }
  var king = null;
  _.each(design.allPositions(), function(pos) {
      if (king !== null) return;
      var piece = board.getPiece(pos);
      if (piece === null) return;
      if (piece.player != player) return;
      if (piece.type != design.getPieceType("King")) return;
      king = pos;
  });
  if (king !== null) {
      _.each(moves, function(move) {
          if (move.actions.length < 1) return;
          if (move.actions[0][0] === null) return;
          if (move.actions[0][1] === null) return;
          if (move.actions[0][2] === null) return;
          var piece = move.actions[0][2][0];
          if (piece.type != design.getPieceType("King")) return;
          move.capturePiece(king);
          if (piece.player != player) {
              move.setValue(board.player, piece.player);
          }
      });
  }
  if (!_.isUndefined(PostProcessing)) {
      PostProcessing(board, moves);
  }
}

var CheckInvariants = Dagaz.Model.CheckInvariants;

Dagaz.Model.CheckInvariants = function(board) {
  var design = Dagaz.Model.design;
  var pawn   = design.getPieceType("Pawn");
  _.each(board.moves, function(move) {
      if (move.actions.length < 1) return;
      if (move.actions[0][0] === null) return;
      if (move.actions[0][1] === null) return;
      if (move.actions[0][2] === null) return;
      var pos = move.actions[0][0][0];
      var piece = board.getPiece(pos);
      if ((piece !== null) && (piece.type == pawn) && design.inZone(0, 1, move.actions[0][1][0])) {
          piece = move.actions[0][2][0];
          var pieces = [];
          pieces.push(piece.promote(design.getPieceType("Bishop")));
          pieces.push(piece.promote(design.getPieceType("Knight")));
          pieces.push(piece.promote(design.getPieceType("Rook")));
          pieces.push(piece.promote(design.getPieceType("Queen")));
          pieces.push(piece.promote(design.getPieceType("King")));
          move.actions[0][2] = pieces;
      }
  });
  CheckInvariants(board);
}

})();
<|endoftext|>


<commit_before>var doEncryptDomains = [
    "facebook.com",
    "mail.google.com"
];
var emailWindowSelectors = [
    '.I5'
];
var textareaSelectors = [
    '.Am'
];

var usernameGetters = {
    '.oL' : function($usernameField) {
        var emailSpans = $usernameField.children().toArray();
        return emailSpans.map(function(emailSpan) {
            return $(emailSpan).attr('email');
        });
    }
}

$(function() {
    console.log('hi');
    if (doEncryptDomains.indexOf(document.domain) < 0) {
        return
    }

    $(document).on('DOMNodeInserted', function(e) {
        for (var i in emailWindowSelectors) {
            var $emailWindow = $(e.target).closest(emailWindowSelectors[i]);
            var $textarea = textareaSelectors.reduce(function(prev, selector) {
                return prev.concat($(e.target).find(selector).toArray());
            }, []);

            if ($emailWindow.length > 0 && $textarea.length > 0) {
                if (! $emailWindow.hasClass('hasOverlay')) {
                    makeOverlay($emailWindow);
                }
                break;
            }
        }
        usernameHandler(e.target);
    });

    $(document).on('DOMNodeRemoved', function(e) {
        usernameHandler(e.target);
    })

});

function makeOverlay($email) {

    for (var i in textareaSelectors) {
        //ehhh this just sets the textarea to the first element inside the email whose class matches...maybe not the best
        $textarea = $email.find(textareaSelectors[i]);
        if ($textarea.length > 0) {
            break;
        }
    }

    var $unencryptedArea = $textarea.clone();
    $textarea.after($unencryptedArea);
    // $textarea.hide();
    $unencryptedArea.data('encryptedArea', $textarea);

    for (var selector in usernameGetters) {
        $usernameField = $email.find(selector);
        if ($usernameField.length > 0) {
            //do initial call to get addresses and decide whether or not to encrypt
            updateUsernames($usernameField, selector, $unencryptedArea);
            break;
        }
    }

    //what should happen if fail to find username field? for now, set doEncrypt to false I guess :/
    if ($unencryptedArea.data('doEncrypt') === undefined) {
        $unencryptedArea.data('doEncrypt', false);
    }

    $unencryptedArea.keyup(function(e) {
        encryptHandler($(this));
    });

    $email.addClass('hasOverlay');
}

function requestEncrypt($encryptedArea, message, usernames) {
    sendMessage({
        "action" : "encrypt",
        "message" : message,
        "usernames" : usernames,
        "which_network" : "gmail"
    }, function(response) {
        var res = $.parseJSON(response).res;
        var msg;
        if (typeof res === "string") {
            msg = res;
        } else {
            var json_encoded = JSON.stringify(res);
            msg = "|fakeblock|" +
                encodeString(json_encoded) +
                "|endfakeblock|";
        }
        $encryptedArea.text(msg);
    });
}

function requestCanEncryptFor($unencryptedArea, usernames) {
    sendMessage({
        "action" : "can_encrypt_for",
        "usernames" : usernames,
        "which_network" : "gmail"
    }, function(response) {
        var res = $.parseJSON(response).res;
        if (res !== $unencryptedArea.data('doEncrypt')) {
            //TODO: will have to encrypt or decrypt the current message if state changed
        }
        $unencryptedArea.data('doEncrypt', res.can_encrypt);
    });
}

function encryptHandler($unencryptedArea) {
    var $encryptedArea = $unencryptedArea.data('encryptedArea');
    var message = $unencryptedArea.text();
    var usernames = $unencryptedArea.data('usernames');
    if ($unencryptedArea.data('doEncrypt')) {
        requestEncrypt($encryptedArea, message, usernames);
    } else {
        $encryptedArea.text(message);
    }

}

function usernameHandler(emailSpan) {
    if ('email' in emailSpan.attributes) {
        $usernameField = $(emailSpan).parent();
        matchedSelectors = Object.keys(usernameGetters).filter(function(klass) {
            return $usernameField.hasClass(klass.split('.')[1]);
        });
        //defaulting to the first selector that matches for now...
        //TODO: think about actually accounting for multiple matched selectors, if we should at all
        updateUsernames($usernameField, matchedSelectors[0]);
    }
}

function updateUsernames($usernameField, selector, $unencryptedArea) {
    var usernames = usernameGetters[selector]($usernameField);

    //give username field a reference to the unencrypted area so it can update usernames on change event
    if ($unencryptedArea) {
        $usernameField.data('unencryptedArea', $unencryptedArea);
    } else {
        $unencryptedArea = $usernameField.data('unencryptedArea');
    }

    $unencryptedArea.data('usernames', usernames);
    requestCanEncryptFor($unencryptedArea, usernames);
}<commit_msg>everything is broken<commit_after>var hasOverlay = false;
var doEncryptDomains = [
    "facebook.com",
    "mail.google.com"
];
var emailWindowSelectors = [
    '.I5'
];
var textareaSelectors = [
    '.Am'
];

var usernameGetters = {
    '.oL' : function($usernameField) {
        var emailSpans = $usernameField.children().toArray();
        return emailSpans.map(function(emailSpan) {
            return $(emailSpan).attr('email');
        });
    }
}

$(function() {
    console.log('hi');
    if (doEncryptDomains.indexOf(document.domain) < 0) {
        return
    }

    $(document).on('DOMNodeInserted', function(e) {
        for (var i in emailWindowSelectors) {
            // var $emailWindow = $(e.target).closest(emailWindowSelectors[i]);
            // var $textarea = textareaSelectors.reduce(function(prev, selector) {
            //     return prev.concat($(e.target).find(selector).toArray());
            // }, []);

            // var $textarea = $('.a07').find('.a09')
            var $emailWindow = $('.I5')
            //this is so hacky...
            // var ina07 = false;
            try {
                var ina07 = $('.Am').parent().hasClass('aO7');
            } catch(err) {
                var ina07 = false;
            }

            // if ($emailWindow.length > 0 && $textarea.length > 0) {
            if ($emailWindow.length > 0 && ina07) {
                // if (! $emailWindow.hasClass('hasOverlay')) {
                if (! hasOverlay) {
                    makeOverlay($emailWindow);
                }
                break;
            }
        }
        usernameHandler(e.target);
    });

    $(document).on('DOMNodeRemoved', function(e) {
        usernameHandler(e.target);
    })

});

function makeOverlay($email) {

    for (var i in textareaSelectors) {
        //ehhh this just sets the textarea to the first element inside the email whose class matches...maybe not the best
        $textarea = $email.find(textareaSelectors[i]);
        if ($textarea.length > 0) {
            break;
        }
    }

    var $unencryptedArea = $textarea.clone();
    $textarea.after($unencryptedArea);
    // $textarea.hide();
    $unencryptedArea.data('encryptedArea', $textarea);

    for (var selector in usernameGetters) {
        $usernameField = $email.find(selector);
        if ($usernameField.length > 0) {
            //do initial call to get addresses and decide whether or not to encrypt
            updateUsernames($usernameField, selector, $unencryptedArea);
            break;
        }
    }

    //what should happen if fail to find username field? for now, set doEncrypt to false I guess :/
    if ($unencryptedArea.data('doEncrypt') === undefined) {
        $unencryptedArea.data('doEncrypt', false);
    }

    $unencryptedArea.keyup(function(e) {
        encryptHandler($(this));
    });
    hasOverlay = true;
    // $email.addClass('hasOverlay');
}

function requestEncrypt($encryptedArea, message, usernames) {
    sendMessage({
        "action" : "encrypt",
        "message" : message,
        "usernames" : usernames,
        "which_network" : "gmail"
    }, function(response) {
        var res = $.parseJSON(response).res;
        var msg;
        if (typeof res === "string") {
            msg = res;
        } else {
            var json_encoded = JSON.stringify(res);
            msg = "|fakeblock|" +
                encodeString(json_encoded) +
                "|endfakeblock|";
        }
        $encryptedArea.text(msg);
    });
}

function requestCanEncryptFor($unencryptedArea, usernames) {
    sendMessage({
        "action" : "can_encrypt_for",
        "usernames" : usernames,
        "which_network" : "gmail"
    }, function(response) {
        var res = $.parseJSON(response).res;
        if (res !== $unencryptedArea.data('doEncrypt')) {
            //TODO: will have to encrypt or decrypt the current message if state changed
        }
        $unencryptedArea.data('doEncrypt', res.can_encrypt);
    });
}

function encryptHandler($unencryptedArea) {
    var $encryptedArea = $unencryptedArea.data('encryptedArea');
    var message = $unencryptedArea.text();
    var usernames = $unencryptedArea.data('usernames');
    if ($unencryptedArea.data('doEncrypt')) {
        requestEncrypt($encryptedArea, message, usernames);
    } else {
        $encryptedArea.text(message);
    }

}

function usernameHandler(emailSpan) {
    if ('email' in emailSpan.attributes) {
        $usernameField = $(emailSpan).parent();
        matchedSelectors = Object.keys(usernameGetters).filter(function(klass) {
            return $usernameField.hasClass(klass.split('.')[1]);
        });
        //defaulting to the first selector that matches for now...
        //TODO: think about actually accounting for multiple matched selectors, if we should at all
        updateUsernames($usernameField, matchedSelectors[0]);
    }
}

function updateUsernames($usernameField, selector, $unencryptedArea) {
    var usernames = usernameGetters[selector]($usernameField);

    //give username field a reference to the unencrypted area so it can update usernames on change event
    if ($unencryptedArea) {
        $usernameField.data('unencryptedArea', $unencryptedArea);
    } else {
        $unencryptedArea = $usernameField.data('unencryptedArea');
    }

    if (! $unencryptedArea) {
        return;
    }
    $unencryptedArea.data('usernames', usernames);
    requestCanEncryptFor($unencryptedArea, usernames);
}<|endoftext|>


<commit_before>// @flow weak

import React, { Component, PropTypes } from 'react';
import { createStyleSheet } from 'stylishly';
import Text from 'material-ui/Text';
import Button from 'material-ui/Button';

import muiLogo from '../../assets/images/material-ui-logo.svg';

export const styleSheet = createStyleSheet('Home', (theme) => {
  const { palette, breakpoints } = theme;

  return {
    root: {
      display: 'flex',
      flexDirection: 'column',
      flex: '1 0 100%',
    },
    hero: {
      flex: '0 0 auto',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: palette.primary[500],
      color: palette.getContrastText(palette.primary[500]),
    },
    content: {
      padding: '60px 30px',
      textAlign: 'center',
      [breakpoints.up('sm')]: {
        padding: '120px 30px',
      },
    },
    button: {
      marginTop: 20,
    },
    logo: {
      maxWidth: '180%',
      margin: '20px -40%',
    },
  };
});

export default class Home extends Component {
  static contextTypes = {
    styleManager: PropTypes.object.isRequired,
  };

  render() {
    const classes = this.context.styleManager.render(styleSheet);
    return (

            <Text type="display2">Material-UI</Text>
            <Text type="subheading">
              A React component library implementing Google's Material Design
            </Text>
            <Button className={classes.button} raised>Get Started</Button>

    );
  }
}
<commit_msg>[docs] Add a link on the home button<commit_after>// @flow weak

import React, { Component, PropTypes } from 'react';
import { createStyleSheet } from 'stylishly';
import Link from 'react-router/lib/Link';
import Text from 'material-ui/Text';
import Button from 'material-ui/Button';
import muiLogo from '../../assets/images/material-ui-logo.svg';

export const styleSheet = createStyleSheet('Home', (theme) => {
  const { palette, breakpoints } = theme;

  return {
    root: {
      display: 'flex',
      flexDirection: 'column',
      flex: '1 0 100%',
    },
    hero: {
      flex: '0 0 auto',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: palette.primary[500],
      color: palette.getContrastText(palette.primary[500]),
    },
    content: {
      padding: '60px 30px',
      textAlign: 'center',
      [breakpoints.up('sm')]: {
        padding: '120px 30px',
      },
    },
    button: {
      marginTop: 20,
    },
    logo: {
      maxWidth: '180%',
      margin: '20px -40%',
    },
  };
});

export default class Home extends Component {
  static contextTypes = {
    styleManager: PropTypes.object.isRequired,
  };

  render() {
    const classes = this.context.styleManager.render(styleSheet);
    return (

            <Text type="display2">Material-UI</Text>
            <Text type="subheading">
              A React component library implementing Google's Material Design
            </Text>
            <Button
              component={Link}
              className={classes.button}
              raised
              to="/getting-started/installation"
            >
              Get Started
            </Button>

    );
  }
}
<|endoftext|>


<commit_before>'use strict'

class ArrayOptionOutput {
	constructor(option,writeOption,i18n,generateId) {
		this.option=option
		this.$dragged=null
		this.$entries=$("
").append(
			option.entries.map(subOption=>this.writeDraggableSubOption(subOption,writeOption,i18n))
		)
		const $buttons=$("
")
		option.availableTypes.forEach((type,i)=>{
			if (i) $buttons.append(" ")
			$buttons.append(
				$("<button type='button'>").html(
					i18n('options.'+option.fullName+'.'+type+'.add')
				).click(()=>{
					//option.addEntry(type,entry=>this.$entries.append(this.writeDraggableSubOption(entry,writeOption,i18n)))
					this.$entries.append(
						this.writeDraggableSubOption(option.makeEntry(type),writeOption,i18n)
					)
					this.updateArrayEntries()
				})
			)
		})
		this.$output=option.$=$("<fieldset>").append(
			"<legend>"+i18n('options.'+option.fullName)+"</legend>",
			this.$entries,
			$buttons
		)
	}
	updateArrayEntries() {
		this.option.entries=this.$entries.children().map(function(){
			return $(this).data('option')
		}).get()
	}
	writeDraggableSubOption(subOption,writeOption,i18n) {
		// have to make drag handler 'draggable', not the whole item
		// because inputs and labels don't like to be inside 'draggable'
		// http://stackoverflow.com/questions/13017177/selection-disabled-while-using-html5-drag-and-drop
		const moveUp=$moved=>{
			$moved.prev().before($moved)
			this.updateArrayEntries()
		}
		const moveDown=$moved=>{
			$moved.next().after($moved)
			this.updateArrayEntries()
		}
		const This=this
		return $("
").data('option',subOption).append(
			$("
")
				.on('dragstart',function(ev){
					This.$dragged=$(this).parent()
					ev.originalEvent.dataTransfer.effectAllowed='move'
					ev.originalEvent.dataTransfer.setData('Text',name)
					if (ev.originalEvent.dataTransfer.setDragImage) { // doesn't work in IE
						ev.originalEvent.dataTransfer.setDragImage(This.$dragged[0],0,0)
					}
					setTimeout(function(){
						This.$dragged.addClass('ghost')
					},0)
				})
				.keydown(function(ev){
					const $handle=$(this)
					const $sorted=$handle.parent()
					if (ev.keyCode==38) {
						moveUp($sorted)
						$handle.focus()
						return false
					} else if (ev.keyCode==40) {
						moveDown($sorted)
						$handle.focus()
						return false
					}
				}),
			writeOption(subOption),
			$("
").click(function(){
				$(this).parent().remove()
				This.updateArrayEntries()
			}).keydown(function(ev){
				if (ev.keyCode==13 || ev.keyCode==32) {
					$(this).parent().remove()
					This.updateArrayEntries()
					return false
				}
			})
		).on('dragover',function(ev){
			ev.preventDefault()
			ev.originalEvent.dataTransfer.dropEffect='move'
			const $target=$(this)
			if (This.$dragged) {
				if ($target.next().is(This.$dragged)) {
					const dh=This.$dragged.height()
					const y=ev.pageY-$target.offset().top
					if (y<dh) {
						moveUp(This.$dragged)
					}
				} else if ($target.nextAll().is(This.$dragged)) {
					moveUp(This.$dragged)
				} else if ($target.prev().is(This.$dragged)) {
					const th=$target.height()
					const dh=This.$dragged.height()
					const y=ev.pageY-$target.offset().top
					if (y>th-dh) {
						moveDown(This.$dragged)
					}
				} else if ($target.prevAll().is(This.$dragged)) {
					moveDown(This.$dragged)
				}
			}
		}).on('drop',function(ev){
			ev.preventDefault()
		}).on('dragend',function(ev){
			ev.preventDefault()
			if (This.$dragged) {
				This.$dragged.removeClass('ghost')
				This.$dragged=null
			}
		})
	}
}

module.exports=ArrayOptionOutput
<commit_msg>array output: hook to check if can delete entry<commit_after>'use strict'

class ArrayOptionOutput {
	constructor(option,writeOption,i18n,generateId) {
		this.option=option
		this.$dragged=null
		this.$entries=$("
").append(
			option.entries.map(subOption=>this.writeDraggableSubOption(subOption,writeOption,i18n))
		)
		const $buttons=$("
")
		option.availableTypes.forEach((type,i)=>{
			if (i) $buttons.append(" ")
			$buttons.append(
				$("<button type='button'>").html(
					i18n('options.'+option.fullName+'.'+type+'.add')
				).click(()=>{
					//option.addEntry(type,entry=>this.$entries.append(this.writeDraggableSubOption(entry,writeOption,i18n)))
					this.$entries.append(
						this.writeDraggableSubOption(option.makeEntry(type),writeOption,i18n)
					)
					this.updateArrayEntries()
				})
			)
		})
		this.$output=option.$=$("<fieldset>").append(
			"<legend>"+i18n('options.'+option.fullName)+"</legend>",
			this.$entries,
			$buttons
		)
	}
	canDeleteEntry($entry) {
		return true
	}
	updateArrayEntries() {
		this.option.entries=this.$entries.children().map(function(){
			return $(this).data('option')
		}).get()
	}
	writeDraggableSubOption(subOption,writeOption,i18n) {
		// have to make drag handler 'draggable', not the whole item
		// because inputs and labels don't like to be inside 'draggable'
		// http://stackoverflow.com/questions/13017177/selection-disabled-while-using-html5-drag-and-drop
		const moveUp=$moved=>{
			$moved.prev().before($moved)
			this.updateArrayEntries()
		}
		const moveDown=$moved=>{
			$moved.next().after($moved)
			this.updateArrayEntries()
		}
		const attemptDelete=$entry=>{
			if (this.canDeleteEntry($entry)) {
				$entry.remove()
				this.updateArrayEntries()
			}
		}
		const This=this
		return $("
").data('option',subOption).append(
			$("
")
				.on('dragstart',function(ev){
					This.$dragged=$(this).parent()
					ev.originalEvent.dataTransfer.effectAllowed='move'
					ev.originalEvent.dataTransfer.setData('Text',name)
					if (ev.originalEvent.dataTransfer.setDragImage) { // doesn't work in IE
						ev.originalEvent.dataTransfer.setDragImage(This.$dragged[0],0,0)
					}
					setTimeout(function(){
						This.$dragged.addClass('ghost')
					},0)
				})
				.keydown(function(ev){
					const $handle=$(this)
					const $sorted=$handle.parent()
					if (ev.keyCode==38) {
						moveUp($sorted)
						$handle.focus()
						return false
					} else if (ev.keyCode==40) {
						moveDown($sorted)
						$handle.focus()
						return false
					}
				}),
			writeOption(subOption),
			$("
").click(function(){
				attemptDelete($(this).parent())
			}).keydown(function(ev){
				if (ev.keyCode==13 || ev.keyCode==32) {
					attemptDelete($(this).parent())
					return false
				}
			})
		).on('dragover',function(ev){
			ev.preventDefault()
			ev.originalEvent.dataTransfer.dropEffect='move'
			const $target=$(this)
			if (This.$dragged) {
				if ($target.next().is(This.$dragged)) {
					const dh=This.$dragged.height()
					const y=ev.pageY-$target.offset().top
					if (y<dh) {
						moveUp(This.$dragged)
					}
				} else if ($target.nextAll().is(This.$dragged)) {
					moveUp(This.$dragged)
				} else if ($target.prev().is(This.$dragged)) {
					const th=$target.height()
					const dh=This.$dragged.height()
					const y=ev.pageY-$target.offset().top
					if (y>th-dh) {
						moveDown(This.$dragged)
					}
				} else if ($target.prevAll().is(This.$dragged)) {
					moveDown(This.$dragged)
				}
			}
		}).on('drop',function(ev){
			ev.preventDefault()
		}).on('dragend',function(ev){
			ev.preventDefault()
			if (This.$dragged) {
				This.$dragged.removeClass('ghost')
				This.$dragged=null
			}
		})
	}
}

module.exports=ArrayOptionOutput
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Page switcher
 * This is the class for the left and right navigation arrows that switch
 * between pages.
 */
cr.define('ntp4', function() {

  function PageSwitcher() {
  }

  PageSwitcher.template = {
    __proto__: HTMLButtonElement.prototype,

    decorate: function(el) {
      el.__proto__ = PageSwitcher.template;

      el.addEventListener('click', el.activate_);
      el.addEventListener('mousewheel', el.onMouseWheel_);

      el.direction_ = el.id == 'page-switcher-start' ? -1 : 1;

      el.dragWrapper_ = new DragWrapper(el, el);
    },

    /**
     * Activate the switcher (go to the next card).
     * @private
     */
    activate_: function() {
      var cardSlider = ntp4.getCardSlider();
      cardSlider.selectCard(cardSlider.currentCard + this.direction_, true);
    },

    /**
     * Handler for the mousewheel event on a pager. We pass through the scroll
     * to the page. This is necssary because the page is our sibling in the DOM
     * hierarchy, so the event won't naturally pass through to it.
     * @param {Event} e The mousewheel event.
     * @private
     */
    onMouseWheel_: function(e) {
      var page = ntp4.getCardSlider().currentCardValue;
      page.handleMouseWheel(e);
    },

    shouldAcceptDrag: function(e) {
      return true;
    },

    doDragEnter: function(e) {
      this.scheduleDelayedSwitch_();
    },

    doDragLeave: function(e) {
      this.cancelDelayedSwitch_();
    },

    doDragOver: function(e) {},

    doDrop: function(e) {
      e.stopPropagation();
      this.cancelDelayedSwitch_();

      var tile = ntp4.getCurrentlyDraggingTile();
      if (!tile)
        return;

      var sourcePage = tile.tilePage;
      var targetPage = ntp4.getCardSlider().currentCardValue;
      if (targetPage == sourcePage)
        return;

      targetPage.appendDraggingTile();
    },

    /**
     * Starts a timer to activate the switcher. The timer repeats until
     * cancelled by cancelDelayedSwitch_.
     * @private
     */
    scheduleDelayedSwitch_: function() {
      var self = this;
      function navPageClearTimeout() {
        self.activate_();
        self.dragNavTimeout_ = null;
        self.scheduleDelayedSwitch_();
      }
      this.dragNavTimeout_ = window.setTimeout(navPageClearTimeout, 500);
    },

    /**
     * Cancels the timer that activates the switcher while dragging.
     * @private
     */
    cancelDelayedSwitch_: function() {
      if (this.dragNavTimeout_) {
        window.clearTimeout(this.dragNavTimeout_);
        this.dragNavTimeout_ = null;
      }
    },

  };

  return {
    initializePageSwitcher: PageSwitcher.template.decorate
  }
});
<commit_msg>ntp4: dragging onto page switcher fix<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Page switcher
 * This is the class for the left and right navigation arrows that switch
 * between pages.
 */
cr.define('ntp4', function() {

  function PageSwitcher() {
  }

  PageSwitcher.template = {
    __proto__: HTMLButtonElement.prototype,

    decorate: function(el) {
      el.__proto__ = PageSwitcher.template;

      el.addEventListener('click', el.activate_);
      el.addEventListener('mousewheel', el.onMouseWheel_);

      el.direction_ = el.id == 'page-switcher-start' ? -1 : 1;

      el.dragWrapper_ = new DragWrapper(el, el);
    },

    /**
     * Activate the switcher (go to the next card).
     * @private
     */
    activate_: function() {
      var cardSlider = ntp4.getCardSlider();
      cardSlider.selectCard(cardSlider.currentCard + this.direction_, true);
    },

    /**
     * Handler for the mousewheel event on a pager. We pass through the scroll
     * to the page. This is necssary because the page is our sibling in the DOM
     * hierarchy, so the event won't naturally pass through to it.
     * @param {Event} e The mousewheel event.
     * @private
     */
    onMouseWheel_: function(e) {
      var page = ntp4.getCardSlider().currentCardValue;
      page.handleMouseWheel(e);
    },

    shouldAcceptDrag: function(e) {
      return true;
    },

    doDragEnter: function(e) {
      this.scheduleDelayedSwitch_();
      this.doDragOver(e);
    },

    doDragLeave: function(e) {
      this.cancelDelayedSwitch_();
    },

    doDragOver: function(e) {
      e.preventDefault();
      var targetPage = ntp4.getCardSlider().currentCardValue;
      targetPage.setDropEffect(e.dataTransfer);
    },

    doDrop: function(e) {
      e.stopPropagation();
      this.cancelDelayedSwitch_();

      var tile = ntp4.getCurrentlyDraggingTile();
      if (!tile)
        return;

      var sourcePage = tile.tilePage;
      var targetPage = ntp4.getCardSlider().currentCardValue;
      if (targetPage == sourcePage)
        return;

      targetPage.appendDraggingTile();
    },

    /**
     * Starts a timer to activate the switcher. The timer repeats until
     * cancelled by cancelDelayedSwitch_.
     * @private
     */
    scheduleDelayedSwitch_: function() {
      var self = this;
      function navPageClearTimeout() {
        self.activate_();
        self.dragNavTimeout_ = null;
        self.scheduleDelayedSwitch_();
      }
      this.dragNavTimeout_ = window.setTimeout(navPageClearTimeout, 500);
    },

    /**
     * Cancels the timer that activates the switcher while dragging.
     * @private
     */
    cancelDelayedSwitch_: function() {
      if (this.dragNavTimeout_) {
        window.clearTimeout(this.dragNavTimeout_);
        this.dragNavTimeout_ = null;
      }
    },

  };

  return {
    initializePageSwitcher: PageSwitcher.template.decorate
  }
});
<|endoftext|>


<commit_before>$(function() {
    function TerminalViewModel(parameters) {
        var self = this;

        self.loginState = parameters[0];
        self.settings = parameters[1];

        self.log = ko.observableArray([]);
        self.buffer = ko.observable(300);

        self.command = ko.observable(undefined);

        self.isErrorOrClosed = ko.observable(undefined);
        self.isOperational = ko.observable(undefined);
        self.isPrinting = ko.observable(undefined);
        self.isPaused = ko.observable(undefined);
        self.isError = ko.observable(undefined);
        self.isReady = ko.observable(undefined);
        self.isLoading = ko.observable(undefined);

        self.autoscrollEnabled = ko.observable(true);

        self.filters = self.settings.terminalFilters;
        self.filterRegex = ko.observable();

        self.cmdHistory = [];
        self.cmdHistoryIdx = -1;

        self.displayedLines = ko.computed(function() {
            var regex = self.filterRegex();
            var lineVisible = function(entry) {
                return regex == undefined || !entry.line.match(regex);
            };

            var filtered = false;
            var result = [];
            _.each(self.log(), function(entry) {
                if (lineVisible(entry)) {
                    result.push(entry);
                    filtered = false;
                } else if (!filtered) {
                    result.push(self._toInternalFormat("[...]", "filtered"));
                    filtered = true;
                }
            });

            return result;
        });
        self.displayedLines.subscribe(function() {
            self.updateOutput();
        });

        self.lineCount = ko.computed(function() {
            var total = self.log().length;
            var displayed = _.filter(self.displayedLines(), function(entry) { return entry.type == "line" }).length;
            var filtered = total - displayed;

            if (total == displayed) {
                return _.sprintf(gettext("showing %(displayed)d lines"), {displayed: displayed});
            } else {
                return _.sprintf(gettext("showing %(displayed)d lines (%(filtered)d of %(total)d total lines filtered)"), {displayed: displayed, total: total, filtered: filtered});
            }
        });

        self.autoscrollEnabled.subscribe(function(newValue) {
            if (newValue) {
                self.log(self.log.slice(-self.buffer()));
            }
        });

        self.activeFilters = ko.observableArray([]);
        self.activeFilters.subscribe(function(e) {
            self.updateFilterRegex();
        });

        self.fromCurrentData = function(data) {
            self._processStateData(data.state);
            self._processCurrentLogData(data.logs);
        };

        self.fromHistoryData = function(data) {
            self._processStateData(data.state);
            self._processHistoryLogData(data.logs);
        };

        self._processCurrentLogData = function(data) {
            self.log(self.log().concat(_.map(data, function(line) { return self._toInternalFormat(line) })));
            if (self.autoscrollEnabled()) {
                self.log(self.log.slice(-300));
            }
        };

        self._processHistoryLogData = function(data) {
            self.log(_.map(data, function(line) { return self._toInternalFormat(line) }));
        };

        self._toInternalFormat = function(line, type) {
            if (type == undefined) {
                type = "line";
            }
            return {line: line, type: type}
        };

        self._processStateData = function(data) {
            self.isErrorOrClosed(data.flags.closedOrError);
            self.isOperational(data.flags.operational);
            self.isPaused(data.flags.paused);
            self.isPrinting(data.flags.printing);
            self.isError(data.flags.error);
            self.isReady(data.flags.ready);
            self.isLoading(data.flags.loading);
        };

        self.updateFilterRegex = function() {
            var filterRegexStr = self.activeFilters().join("|").trim();
            if (filterRegexStr == "") {
                self.filterRegex(undefined);
            } else {
                self.filterRegex(new RegExp(filterRegexStr));
            }
            self.updateOutput();
        };

        self.updateOutput = function() {
            if (self.autoscrollEnabled()) {
                self.scrollToEnd();
            }
        };

        self.toggleAutoscroll = function() {
            self.autoscrollEnabled(!self.autoscrollEnabled());
        };

        self.selectAll = function() {
            var container = $("#terminal-output");
            if (container.length) {
                container.selectText();
            }
        };

        self.scrollToEnd = function() {
            var container = $("#terminal-output");
            if (container.length) {
                container.scrollTop(container[0].scrollHeight - container.height())
            }
        };

        self.sendCommand = function() {
            var command = self.command();
            if (!command) {
                return;
            }

            var re = /^([gmt][0-9]+)(\s.*)?/;
            var commandMatch = command.match(re);
            if (commandMatch != null) {
                command = commandMatch[1].toUpperCase() + ((commandMatch[2] !== undefined) ? commandMatch[2] : "");
            }

            if (command) {
                $.ajax({
                    url: API_BASEURL + "printer/command",
                    type: "POST",
                    dataType: "json",
                    contentType: "application/json; charset=UTF-8",
                    data: JSON.stringify({"command": command})
                });

                self.cmdHistory.push(command);
                self.cmdHistory.slice(-300); // just to set a sane limit to how many manually entered commands will be saved...
                self.cmdHistoryIdx = self.cmdHistory.length;
                self.command("");
            }
        };

        self.fakeAck = function() {
            $.ajax({
                url: API_BASEURL + "connection",
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=UTF-8",
                data: JSON.stringify({"command": "fake_ack"})
            });
        };

        self.handleKeyDown = function(event) {
            var keyCode = event.keyCode;

            if (keyCode == 38 || keyCode == 40) {
                if (keyCode == 38 && self.cmdHistory.length > 0 && self.cmdHistoryIdx > 0) {
                    self.cmdHistoryIdx--;
                } else if (keyCode == 40 && self.cmdHistoryIdx < self.cmdHistory.length - 1) {
                    self.cmdHistoryIdx++;
                }

                if (self.cmdHistoryIdx >= 0 && self.cmdHistoryIdx < self.cmdHistory.length) {
                    self.command(self.cmdHistory[self.cmdHistoryIdx]);
                }

                // prevent the cursor from being moved to the beginning of the input field (this is actually the reason
                // why we do the arrow key handling in the keydown event handler, keyup would be too late already to
                // prevent this from happening, causing a jumpy cursor)
                return false;
            }

            // do not prevent default action
            return true;
        };

        self.handleKeyUp = function(event) {
            if (event.keyCode == 13) {
                self.sendCommand();
            }

            // do not prevent default action
            return true;
        };

        self.onAfterTabChange = function(current, previous) {
            if (current != "#term") {
                return;
            }
            if (self.autoscrollEnabled()) {
                self.scrollToEnd();
            }
        };

    }

    OCTOPRINT_VIEWMODELS.push([
        TerminalViewModel,
        ["loginStateViewModel", "settingsViewModel"],
        "#term"
    ]);
});<commit_msg>Fixed a missing self.buffer()<commit_after>$(function() {
    function TerminalViewModel(parameters) {
        var self = this;

        self.loginState = parameters[0];
        self.settings = parameters[1];

        self.log = ko.observableArray([]);
        self.buffer = ko.observable(300);

        self.command = ko.observable(undefined);

        self.isErrorOrClosed = ko.observable(undefined);
        self.isOperational = ko.observable(undefined);
        self.isPrinting = ko.observable(undefined);
        self.isPaused = ko.observable(undefined);
        self.isError = ko.observable(undefined);
        self.isReady = ko.observable(undefined);
        self.isLoading = ko.observable(undefined);

        self.autoscrollEnabled = ko.observable(true);

        self.filters = self.settings.terminalFilters;
        self.filterRegex = ko.observable();

        self.cmdHistory = [];
        self.cmdHistoryIdx = -1;

        self.displayedLines = ko.computed(function() {
            var regex = self.filterRegex();
            var lineVisible = function(entry) {
                return regex == undefined || !entry.line.match(regex);
            };

            var filtered = false;
            var result = [];
            _.each(self.log(), function(entry) {
                if (lineVisible(entry)) {
                    result.push(entry);
                    filtered = false;
                } else if (!filtered) {
                    result.push(self._toInternalFormat("[...]", "filtered"));
                    filtered = true;
                }
            });

            return result;
        });
        self.displayedLines.subscribe(function() {
            self.updateOutput();
        });

        self.lineCount = ko.computed(function() {
            var total = self.log().length;
            var displayed = _.filter(self.displayedLines(), function(entry) { return entry.type == "line" }).length;
            var filtered = total - displayed;

            if (total == displayed) {
                return _.sprintf(gettext("showing %(displayed)d lines"), {displayed: displayed});
            } else {
                return _.sprintf(gettext("showing %(displayed)d lines (%(filtered)d of %(total)d total lines filtered)"), {displayed: displayed, total: total, filtered: filtered});
            }
        });

        self.autoscrollEnabled.subscribe(function(newValue) {
            if (newValue) {
                self.log(self.log.slice(-self.buffer()));
            }
        });

        self.activeFilters = ko.observableArray([]);
        self.activeFilters.subscribe(function(e) {
            self.updateFilterRegex();
        });

        self.fromCurrentData = function(data) {
            self._processStateData(data.state);
            self._processCurrentLogData(data.logs);
        };

        self.fromHistoryData = function(data) {
            self._processStateData(data.state);
            self._processHistoryLogData(data.logs);
        };

        self._processCurrentLogData = function(data) {
            self.log(self.log().concat(_.map(data, function(line) { return self._toInternalFormat(line) })));
            if (self.autoscrollEnabled()) {
                self.log(self.log.slice(-self.buffer()));
            }
        };

        self._processHistoryLogData = function(data) {
            self.log(_.map(data, function(line) { return self._toInternalFormat(line) }));
        };

        self._toInternalFormat = function(line, type) {
            if (type == undefined) {
                type = "line";
            }
            return {line: line, type: type}
        };

        self._processStateData = function(data) {
            self.isErrorOrClosed(data.flags.closedOrError);
            self.isOperational(data.flags.operational);
            self.isPaused(data.flags.paused);
            self.isPrinting(data.flags.printing);
            self.isError(data.flags.error);
            self.isReady(data.flags.ready);
            self.isLoading(data.flags.loading);
        };

        self.updateFilterRegex = function() {
            var filterRegexStr = self.activeFilters().join("|").trim();
            if (filterRegexStr == "") {
                self.filterRegex(undefined);
            } else {
                self.filterRegex(new RegExp(filterRegexStr));
            }
            self.updateOutput();
        };

        self.updateOutput = function() {
            if (self.autoscrollEnabled()) {
                self.scrollToEnd();
            }
        };

        self.toggleAutoscroll = function() {
            self.autoscrollEnabled(!self.autoscrollEnabled());
        };

        self.selectAll = function() {
            var container = $("#terminal-output");
            if (container.length) {
                container.selectText();
            }
        };

        self.scrollToEnd = function() {
            var container = $("#terminal-output");
            if (container.length) {
                container.scrollTop(container[0].scrollHeight - container.height())
            }
        };

        self.sendCommand = function() {
            var command = self.command();
            if (!command) {
                return;
            }

            var re = /^([gmt][0-9]+)(\s.*)?/;
            var commandMatch = command.match(re);
            if (commandMatch != null) {
                command = commandMatch[1].toUpperCase() + ((commandMatch[2] !== undefined) ? commandMatch[2] : "");
            }

            if (command) {
                $.ajax({
                    url: API_BASEURL + "printer/command",
                    type: "POST",
                    dataType: "json",
                    contentType: "application/json; charset=UTF-8",
                    data: JSON.stringify({"command": command})
                });

                self.cmdHistory.push(command);
                self.cmdHistory.slice(-300); // just to set a sane limit to how many manually entered commands will be saved...
                self.cmdHistoryIdx = self.cmdHistory.length;
                self.command("");
            }
        };

        self.fakeAck = function() {
            $.ajax({
                url: API_BASEURL + "connection",
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=UTF-8",
                data: JSON.stringify({"command": "fake_ack"})
            });
        };

        self.handleKeyDown = function(event) {
            var keyCode = event.keyCode;

            if (keyCode == 38 || keyCode == 40) {
                if (keyCode == 38 && self.cmdHistory.length > 0 && self.cmdHistoryIdx > 0) {
                    self.cmdHistoryIdx--;
                } else if (keyCode == 40 && self.cmdHistoryIdx < self.cmdHistory.length - 1) {
                    self.cmdHistoryIdx++;
                }

                if (self.cmdHistoryIdx >= 0 && self.cmdHistoryIdx < self.cmdHistory.length) {
                    self.command(self.cmdHistory[self.cmdHistoryIdx]);
                }

                // prevent the cursor from being moved to the beginning of the input field (this is actually the reason
                // why we do the arrow key handling in the keydown event handler, keyup would be too late already to
                // prevent this from happening, causing a jumpy cursor)
                return false;
            }

            // do not prevent default action
            return true;
        };

        self.handleKeyUp = function(event) {
            if (event.keyCode == 13) {
                self.sendCommand();
            }

            // do not prevent default action
            return true;
        };

        self.onAfterTabChange = function(current, previous) {
            if (current != "#term") {
                return;
            }
            if (self.autoscrollEnabled()) {
                self.scrollToEnd();
            }
        };

    }

    OCTOPRINT_VIEWMODELS.push([
        TerminalViewModel,
        ["loginStateViewModel", "settingsViewModel"],
        "#term"
    ]);
});<|endoftext|>


<commit_before>'use strict';

/**
 * @constructor
 */
function Game() {
    this.$html    = $('#game-area');
    this.apiMgr   = new APIMgr();
    this.pageMgr  = new PageMgr();
    this.alertMgr = new AlertMgr();
    this.modalMgr = new ModalMgr();

    this.setId('undefined');
    this.players  = [];
}

/**
 * @property {int}      id
 * @property {Player[]} players
 */
Game.prototype = {
    /**
     * @param {int|string} id
     *
     * @returns {Game}
     */
    setId: function(id) {
        this.id = id;

        return this;
    },
    /**
     * @returns {{id: {int}}}
     */
    getJSON: function() {
        return {id: this.id};
    },
    /**
     * @param {{name: {string}, isCPU: {boolean}}[]} players
     * @param {int} battlefieldSize
     */
    init: function(players, battlefieldSize) {
        this.setId('undefined');
        this.players = [];
        this.pageMgr.switchSection(document.querySelector('.page-sidebar li[data-section="' + PageMgr.resources.config.section.game + '"]'));

        this.$html.html('');
        let self = this,
            requestData = {
                id: this.getJSON(),
                data: []
            };

        players.map(function(el) {
            let player = new Player(self.$html, el.name, el.isCPU || false, battlefieldSize);
            self.players.push(player);

            requestData.data.push({
                player: player.getJSON(),
                battlefield: player.battlefield.getJSON(),
                cells: player.battlefield.cellContainer.getJSON()
            });
        });

        this.apiMgr.request('POST', this.$html.attr(Game.resources.config.route.init), requestData,
            function(response) {
                self.parseInitResponse(response);
            },
            function(response) {
            }
        );
    },
    parseInitResponse: function(response) {
        this.setId(response.id);
        let self = this;

        response.data.map(function(el) {
            let player  = self.findPlayerByName(el.player.name);

            if (undefined !== player) {
                player.setId(el.player.id);
            }
        });
    },
    update: function(el) {
        let config = Player.resources.config,
            pid = el.parentElement.parentElement.parentElement.getAttribute(config.attribute.id),
            player = this.findPlayerById(pid);

        if (undefined !== player && player.isCPU()) {
            let attr = Cell.resources.config.attribute,
                cell = this.findCell(player.id, parseInt(el.getAttribute(attr.xAxis)), parseInt(el.getAttribute(attr.yAxis)));

            if (undefined !== cell) {
                this.cellSend({game: this.getJSON(), player: player.getJSON(), cell: cell.getJSON()});
            }
        }
    },
    findPlayerById: function(id) {
        return this.players.find(el => el.id == id);
    },
    findPlayerByName: function(name) {
        return this.players.find(el => el.name == name);
    },
    findHumanPlayer: function() {
        return this.players.find(el => el.isHuman());
    },
    cellSend: function(cell) {
        var self = this;

        this.apiMgr.request('PATCH', this.$html.attr(Game.resources.config.route.turn), cell,
            function(response) {
                self.parseUpdateResponse(response);
            },
            function(response) {

            }
        );
    },
    /**
     * @param {{cells: [], victory: {Object}}} response
     */
    parseUpdateResponse: function(response) {
        let self = this;
        response.cells.map(function(el) {
            let cell = self.findCell(el.player.id, el.x, el.y);

            if (undefined !== cell) {
                cell.setState(el.s);
            }
        });

        if (undefined !== response.victory) {
            let text = Game.resources.config.text,
                type = AlertMgr.resources.config.type,
                player = this.findPlayerById(response.victory.player.id);

            if (undefined !== player) {
                player.isHuman()
                    ? this.alertMgr.show(text.win, type.success)
                    : this.alertMgr.show(text.loss, type.error);
            }
        }
        //for(var index in response) {
        //    if(index ===  _config.json.victory) {
        //        response[index].player.id != this.findHumanPlayer().id
        //            ? this.alertMgr.show(_config.text.loss, AlertMgr.resources.config.type.error)
        //            : this.alertMgr.show(_config.text.win, AlertMgr.resources.config.type.success);
        //    } else {
        //        var battlefield = response[index];
        //        for(var subIndex in battlefield) {
        //            var cell = this.findCell(battlefield[subIndex].player.id, battlefield[subIndex].x, battlefield[subIndex].y);
        //            if(cell instanceof Cell) {
        //                cell.setState(battlefield[subIndex].s);
        //            }
        //        }
        //    }
        //}
    },
    /**
     * @param {int} pid
     * @param {int} x
     * @param {int} y
     *
     * @returns {Cell|undefined}
     */
    findCell: function(pid, x, y) {
        let player = this.findPlayerById(pid);

        if (player instanceof Player) {
            return player.battlefield.getCell(x, y);
        }
    },
    modalGameInitiation: function() {
        this.alertMgr.hide();
        this.modalMgr.updateHTML(Game.resources.html.modal).show();

        return this;
    },
    /**
     * @param {Element} el
     *
     * @returns {boolean}
     */
    modalValidateInput: function(el) {
        var _config = Game.resources.config;

        switch(el.id) {
            case _config.trigger.player:
                console.log(el.value);
                if(!_config.limits.namePattern.test(el.value)) {
                    el.value = el.value.substr(0, el.value.length - 1);
                    return false;
                }
                return true;
            case _config.trigger.bfsize:
                if(el.value.length > 0 && isNaN(el.value))
                    el.value = el.value.substr(0, el.value.length - 1);
                else if(el.value.length > 1 && el.value < _config.limits.minBFSize)
                    el.value = _config.limits.minBFSize;
                else if(el.value.length > 2 || el.value > _config.limits.maxBFSize)
                    el.value = _config.limits.maxBFSize;
                return el.value >= _config.limits.minBFSize && el.value <= _config.limits.maxBFSize;
        }
    },
    modalUnlockSubmission: function() {
        this.modalMgr.unlockSubmission(false);

        var trigger = Game.resources.config.trigger,
            player  = document.getElementById(trigger.player),
            bfSize  = document.getElementById(trigger.bfsize);

        if(this.modalValidateInput(player) && this.modalValidateInput(bfSize)) {
            this.modalMgr.unlockSubmission(true);
        }
    }
};

Game.resources = {};
Game.resources.config = {
    trigger: {
        player: 'player-nickname',
        bfsize: 'game-battlefield-size'
    },
    text: {
        win: 'you won',
        loss: 'you lost'
    },
    limits: {
        minBFSize: 5,
        maxBFSize: 15,
        namePattern: /^[a-zA-Z0-9\.\-\ \@]{1,255}$/
    },
    route: {
        turn: 'data-turn-link',
        init: 'data-init-link'
    },
    json: {
        victory: 'victory'
    }
};
Game.resources.html = {
    /**
     * @returns {string}
     */
    modal: function() {
        let config = Game.resources.config;

        return '' +
            '
' +
                '
' +
                    '
' +
                        '
' +
                            '<button type="button" class="close" data-dismiss="modal">' +
                                '×' +
                            '</button>' +
                            '
your details
' +
                        '
' +
                        '
' +
                            '
' +
                                'nickname' +
                                '<input type="text" class="form-control" id="' + config.trigger.player + '" placeholder="">' +
                            '
' +
                            '
' +
                                'battlefield size' +
                                '<input type="test" class="form-control" id="' + config.trigger.bfsize + '"' +
                                    ' placeholder="between ' + config.limits.minBFSize + ' and ' + config.limits.maxBFSize + '">' +
                            '
' +
                        '
' +
                        '
' +
                            '<button type="button" id="new-game-btn" class="btn btn-primary" disabled="disabled">next step</button>' +
                        '
' +
                    '
' +
                '
' +
            '
'
    }
};
<commit_msg>cleanup<commit_after>'use strict';

/**
 * @constructor
 */
function Game() {
    this.$html    = $('#game-area');
    this.apiMgr   = new APIMgr();
    this.pageMgr  = new PageMgr();
    this.alertMgr = new AlertMgr();
    this.modalMgr = new ModalMgr();

    this.setId('undefined');
    this.players  = [];
}

/**
 * @property {int}      id
 * @property {Player[]} players
 */
Game.prototype = {
    /**
     * @param {int|string} id
     *
     * @returns {Game}
     */
    setId: function(id) {
        this.id = id;

        return this;
    },
    /**
     * @returns {{id: {int}}}
     */
    getJSON: function() {
        return {id: this.id};
    },
    /**
     * @param {{name: {string}, isCPU: {boolean}}[]} players
     * @param {int} battlefieldSize
     */
    init: function(players, battlefieldSize) {
        this.setId('undefined');
        this.players = [];
        this.pageMgr.switchSection(document.querySelector('.page-sidebar li[data-section="' + PageMgr.resources.config.section.game + '"]'));

        this.$html.html('');
        let self = this,
            requestData = {
                id: this.getJSON(),
                data: []
            };

        players.map(function(el) {
            let player = new Player(self.$html, el.name, el.isCPU || false, battlefieldSize);
            self.players.push(player);

            requestData.data.push({
                player: player.getJSON(),
                battlefield: player.battlefield.getJSON(),
                cells: player.battlefield.cellContainer.getJSON()
            });
        });

        this.apiMgr.request('POST', this.$html.attr(Game.resources.config.route.init), requestData,
            function(response) {
                self.parseInitResponse(response);
            },
            function(response) {
            }
        );
    },
    /**
     * @param {{id: {int}, data: []}}response
     */
    parseInitResponse: function(response) {
        this.setId(response.id);
        let self = this;

        response.data.map(function(el) {
            let player  = self.findPlayerByName(el.player.name);

            if (undefined !== player) {
                player.setId(el.player.id);
            }
        });
    },
    /**
     * @param {Element} el
     */
    update: function(el) {
        let config = Player.resources.config,
            pid = el.parentElement.parentElement.parentElement.getAttribute(config.attribute.id),
            player = this.findPlayerById(pid);

        if (undefined !== player && player.isCPU()) {
            let attr = Cell.resources.config.attribute,
                cell = this.findCell(player.id, parseInt(el.getAttribute(attr.xAxis)), parseInt(el.getAttribute(attr.yAxis)));

            if (undefined !== cell) {
                this.cellSend({game: this.getJSON(), player: player.getJSON(), cell: cell.getJSON()});
            }
        }
    },
    /**
     * @param id {int}
     *
     * @returns {Player|undefined}
     */
    findPlayerById: function(id) {
        return this.players.find(el => el.id == id);
    },
    /**
     * @param name {string}
     *
     * @returns {Player|undefined}
     */
    findPlayerByName: function(name) {
        return this.players.find(el => el.name == name);
    },
    /**
     * @param {Cell} cell
     */
    cellSend: function(cell) {
        var self = this;

        this.apiMgr.request('PATCH', this.$html.attr(Game.resources.config.route.turn), cell,
            function(response) {
                self.parseUpdateResponse(response);
            },
            function(response) {

            }
        );
    },
    /**
     * @param {{cells: [], victory: {Object}}} response
     */
    parseUpdateResponse: function(response) {
        let self = this;
        response.cells.map(function(el) {
            let cell = self.findCell(el.player.id, el.x, el.y);

            if (undefined !== cell) {
                cell.setState(el.s);
            }
        });

        if (undefined !== response.victory) {
            let text = Game.resources.config.text,
                type = AlertMgr.resources.config.type,
                player = this.findPlayerById(response.victory.player.id);

            if (undefined !== player) {
                player.isHuman()
                    ? this.alertMgr.show(text.win, type.success)
                    : this.alertMgr.show(text.loss, type.error);
            }
        }
    },
    /**
     * @param {int} playerId
     * @param {int} x
     * @param {int} y
     *
     * @returns {Cell|undefined}
     */
    findCell: function(playerId, x, y) {
        let player = this.findPlayerById(playerId);

        if (player instanceof Player) {
            return player.battlefield.getCell(x, y);
        }
    },
    modalGameInitiation: function() {
        this.alertMgr.hide();
        this.modalMgr.updateHTML(Game.resources.html.modal).show();

        return this;
    },
    /**
     * @param {Element} el
     *
     * @returns {boolean}
     */
    modalValidateInput: function(el) {
        var _config = Game.resources.config;

        switch(el.id) {
            case _config.trigger.player:
                console.log(el.value);
                if(!_config.limits.namePattern.test(el.value)) {
                    el.value = el.value.substr(0, el.value.length - 1);
                    return false;
                }
                return true;
            case _config.trigger.bfsize:
                if(el.value.length > 0 && isNaN(el.value))
                    el.value = el.value.substr(0, el.value.length - 1);
                else if(el.value.length > 1 && el.value < _config.limits.minBFSize)
                    el.value = _config.limits.minBFSize;
                else if(el.value.length > 2 || el.value > _config.limits.maxBFSize)
                    el.value = _config.limits.maxBFSize;
                return el.value >= _config.limits.minBFSize && el.value <= _config.limits.maxBFSize;
        }
    },
    modalUnlockSubmission: function() {
        this.modalMgr.unlockSubmission(false);

        var trigger = Game.resources.config.trigger,
            player  = document.getElementById(trigger.player),
            bfSize  = document.getElementById(trigger.bfsize);

        if(this.modalValidateInput(player) && this.modalValidateInput(bfSize)) {
            this.modalMgr.unlockSubmission(true);
        }
    }
};

Game.resources = {};
Game.resources.config = {
    trigger: {
        player: 'player-nickname',
        bfsize: 'game-battlefield-size'
    },
    text: {
        win: 'you won',
        loss: 'you lost'
    },
    limits: {
        minBFSize: 5,
        maxBFSize: 15,
        namePattern: /^[a-zA-Z0-9\.\-\ \@]{1,255}$/
    },
    route: {
        turn: 'data-turn-link',
        init: 'data-init-link'
    }
};
Game.resources.html = {
    /**
     * @returns {string}
     */
    modal: function() {
        let config = Game.resources.config;

        return '' +
            '
' +
                '
' +
                    '
' +
                        '
' +
                            '<button type="button" class="close" data-dismiss="modal">' +
                                '×' +
                            '</button>' +
                            '
your details
' +
                        '
' +
                        '
' +
                            '
' +
                                'nickname' +
                                '<input type="text" class="form-control" id="' + config.trigger.player + '" placeholder="">' +
                            '
' +
                            '
' +
                                'battlefield size' +
                                '<input type="test" class="form-control" id="' + config.trigger.bfsize + '"' +
                                    ' placeholder="between ' + config.limits.minBFSize + ' and ' + config.limits.maxBFSize + '">' +
                            '
' +
                        '
' +
                        '
' +
                            '<button type="button" id="new-game-btn" class="btn btn-primary" disabled="disabled">next step</button>' +
                        '
' +
                    '
' +
                '
' +
            '
'
    }
};
<|endoftext|>


<commit_before>var cdb = require('cartodb.js');
var Backbone = require('backbone');
var LayerDefinitionModel = require('../../../../../javascripts/cartodb3/data/layer-definition-model');
var EditorMapView = require('../../../../../javascripts/cartodb3/editor/map/map-view');

describe('editor/map/map-view', function () {
  beforeEach(function () {
    var basemapLayerDefModel = new LayerDefinitionModel({
      type: 'Tiled',
      name: 'Basemap is always first'
    }, {
      configModel: {}
    });

    var analysisDefinitionsCollection = new Backbone.Collection([]);
    analysisDefinitionsCollection.analysisDefinitionNodesCollection = {};

    this.view = new EditorMapView({
      visDefinitionModel: new cdb.core.Model({
        name: 'My super fun vis'
      }),
      modals: {},
      analysisDefinitionsCollection: analysisDefinitionsCollection,
      layerDefinitionsCollection: new Backbone.Collection([basemapLayerDefModel]),
      widgetDefinitionsCollection: new Backbone.Collection()
    });

    this.view.render();
  });

  it('should have no leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });

  it('should render correctly', function () {
    expect(this.view.$el.text()).toContain('My super fun vis');
    expect(this.view.$el.text()).toContain('editor.tab-pane.layers.title-label');
    expect(this.view.$el.text()).toContain('editor.tab-pane.elements.title-label');
    expect(this.view.$el.text()).toContain('editor.tab-pane.widgets.title-label');
  });
});
<commit_msg>Fix failing test<commit_after>var cdb = require('cartodb.js');
var Backbone = require('backbone');
var LayerDefinitionModel = require('../../../../../javascripts/cartodb3/data/layer-definition-model');
var EditorMapView = require('../../../../../javascripts/cartodb3/editor/map/map-view');

describe('editor/map/map-view', function () {
  beforeEach(function () {
    var configModel = 'c';
    var basemapLayerDefModel = new LayerDefinitionModel({
      type: 'Tiled',
      name: 'Basemap is always first'
    }, {
      configModel: {}
    });

    var analysisDefinitionsCollection = new Backbone.Collection([]);
    analysisDefinitionsCollection.analysisDefinitionNodesCollection = {};

    this.view = new EditorMapView({
      visDefinitionModel: new cdb.core.Model({
        name: 'My super fun vis'
      }),
      modals: {},
      configModel: configModel,
      userModel: new cdb.core.Model({}, { configModel: configModel }),
      analysisDefinitionsCollection: analysisDefinitionsCollection,
      layerDefinitionsCollection: new Backbone.Collection([basemapLayerDefModel]),
      widgetDefinitionsCollection: new Backbone.Collection()
    });

    this.view.render();
  });

  it('should have no leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });

  it('should render correctly', function () {
    expect(this.view.$el.text()).toContain('My super fun vis');
    expect(this.view.$el.text()).toContain('editor.tab-pane.layers.title-label');
    expect(this.view.$el.text()).toContain('editor.tab-pane.elements.title-label');
    expect(this.view.$el.text()).toContain('editor.tab-pane.widgets.title-label');
  });
});
<|endoftext|>


<commit_before>// Name: {company.js}
// Module: {Back-end::Models}
// Location: {/MaaS/common/models/}

// History:
// Version         Date            Programmer
// ==========================================

var app = require('../../server/server.js');
var mongoose = require('mongoose');

module.exports = function(Company) {

    // Elimino l'azienda e i relativi utenti
    Company.deleteCompany = function(id, email, cb) {
        console.log("> delete company");
        Company.findById(id, function(err, company) {
            console.log(">if findID");
            if(err || !company)
                return cb(err);
            var user = app.models.user;
            user.findOne({where: {companyId: company.id, email: email}, limit: 1}, function(err, userInstance) {
                if(err || !userInstance)
                    return cb(err);
                if(userInstance.role != "Owner" && company.owner == userInstance) {
                    console.log(">non sono un superAdmin");
                    var error = {
                        message: 'You haven\'t the rights to delete this company'
                    };
                    return cb(null, error);
                }
                console.log(">sono un superAdmin");
                // Remove DSL of the company
                var DSL = app.models.DSL;
                userInstance.dsl({ where: {} }, function(err, DSLList) {
                    if(err || !DSLList)
                    {
                        return cb(err);
                    }
                    // Remove DSL accesses
                    DSLList.forEach(function(DSLInstance, i) {
                        console.log(">cancellazione DSL definition");
                        DSLInstance.users({ where: {} }, function(err, users) {
                            if(err)
                            {
                                return cb(err, null);
                            }
                            users.forEach(function(user, i) {
                                DSLInstance.users.remove(user, function(err) {
                                    if(err)
                                    {
                                        console.log("> Error deleting DSL definition");
                                        return cb(err, null);
                                    }
                                });
                            });
                            // Success
                            DSL.destroyById(DSLInstance.id, function(err) {
                                if(err)
                                {
                                    return cb(err, null);
                                }
                                console.log("> DSL definition deleted:", id);
                                return cb(null, null);
                            });
                        });
                    });

                    //Remove Users of the company
                company.users.destroyAll(function(err) {
                    if(err)
                        return cb(err);
                    Company.deleteById(company.id, function(err) {
                        if(err) console.log("> error deleting company:", company.name);
                        console.log("> company deleted:", company.name);
                        return cb(null, null, company.name);
                    });
                });
                });
                // Remove Users of the company
                // company.users.destroyAll(function(err) {
                //     if(err)
                //         return cb(err);
                //     Company.deleteById(company.id, function(err) {
                //         if(err) console.log("> error deleting company:", company.name);
                //         console.log("> company deleted:", company.name);
                //         return cb(null, null, company.name);
                //     });
                // });
            });
        });
    };

    Company.remoteMethod(
        'deleteCompany',
        {
            description: 'Delete Company by passing id to delete and email of the user making the request.',
            accepts: [
                { arg: 'id', type: 'string', required: true, description: 'Company id to delete'},
                { arg: 'email', type: 'string', required: true, description: 'User email making request'}
            ],
            returns: [
                {arg: 'error', type: 'Object'},
                {arg: 'name', type: 'String'}
            ],
            http: { verb: 'delete', path: '/deleteCompany/:id' }
        }
    );

    //checks if the connection string points to a real mongodb database
    Company.beforeRemote('__create__externalDatabases', function(context, extDbInstance, next){
        var connString = context.args.data.connString;
        console.log('> connection string: ', connString);
        mongoose.connect(connString);
        var db = mongoose.connection;
        db.on('error', function(){
            console.log('> connection error for the connection string: ', connString);
            context.args.data.connected = "false";
        })
    });
    //change name of a company wich as companyId= id
    Company.changeCompanyName = function(id, name, cb){
        Company.findById(id, function(err, company) {
            if(err)
                return cb(err);
           Company.findOne({where: {name: name}, limit: 1}, function(err, companyInstance) {
                if(!companyInstance){
                    var oldName = company.name;
                    company.updateAttribute('name', name, function(err, company) {
                        if(err) {
                          console.log('> Failed changing name');
                          return cb(err);
                        }
                          console.log('> Name changed successfully');
                          var data = {
                              newName: company.name,
                              oldName: oldName
                          };
                          return cb(null, null, data);
                    });
                }else{
                    var error = { message: 'A company with this name already exists' };
                    return cb(null, error);
                }
            });
        });
    }

Company.remoteMethod(
        'changeCompanyName',
        {
            description: "Change the name of a company",
            accepts: [
                { arg: 'id', type: 'string', required: true, description: 'Company id' },
                { arg: 'name', type: 'string', required: true, description: 'New name' },

            ],
            returns: [
                { arg: 'error', type: 'Object' },
                { arg: 'data', type: 'Object'},
            ],
            http: { verb: 'put', path: '/:id/changeCompanyName' }
        }
    );

};
<commit_msg> fix delete<commit_after>// Name: {company.js}
// Module: {Back-end::Models}
// Location: {/MaaS/common/models/}

// History:
// Version         Date            Programmer
// ==========================================

var app = require('../../server/server.js');
var mongoose = require('mongoose');

module.exports = function(Company) {

    // Elimino l'azienda e i relativi utenti
    Company.deleteCompany = function(id, email, cb) {
        console.log("> delete company");
        Company.findById(id, function(err, company) {
            console.log(">if findID");
            if(err || !company)
                return cb(err);
            var user = app.models.user;
            user.findOne({where: {companyId: company.id, email: email}, limit: 1}, function(err, userInstance) {
                if(err || !userInstance)
                    return cb(err);
                if(userInstance.role != "Owner" && company.owner == userInstance) {
                    console.log(">non sono un superAdmin");
                    var error = {
                        message: 'You haven\'t the rights to delete this company'
                    };
                    return cb(null, error);
                }

                // Remove DSL of the company
                var DSL = app.models.DSL;
                userInstance.dsl({ where: {} }, function(err, DSLList) {
                    if(err || !DSLList)
                    {
                        return cb(err);
                    }
                    // Remove DSL accesses
                    DSLList.forEach(function(DSLInstance, i) {

                        DSLInstance.users({ where: {} }, function(err, users) {
                            if(err)
                            {
                                return cb(err, null);
                            }

                        users.forEach(function(user, i) {
                         // QUESTO NON FUNZIONA  ==> NON ENTRA QUI
                            DSLInstance.users.remove(user, function(err) {
                                if(err)
                                {
                                    console.log("> Error deleting DSL definition");
                                    return cb(err, null);
                                }
                                 console.log(">eliminazione dei permessi");
                            });

                        });

                            DSL.destroyById(DSLInstance.id, function(err) {
                                console.log("> sto per distruggere un dsl");
                                if(err)
                                {
                                    return cb(err, null);
                                }
                                console.log("> DSL definition deleted:", id);
                                //return cb(null, null);
                            });
                        });
                    });
                });
                //Remove Users of the company
                company.users.destroyAll(function(err) {
                    if(err)
                        return cb(err);
                    Company.deleteById(company.id, function(err) {
                        if(err) console.log("> error deleting company:", company.name);
                        console.log("> company deleted:", company.name);
                        return cb(null, null, company.name);
                    });
                });
            });
        });
    };

    Company.remoteMethod(
        'deleteCompany',
        {
            description: 'Delete Company by passing id to delete and email of the user making the request.',
            accepts: [
                { arg: 'id', type: 'string', required: true, description: 'Company id to delete'},
                { arg: 'email', type: 'string', required: true, description: 'User email making request'}
            ],
            returns: [
                {arg: 'error', type: 'Object'},
                {arg: 'name', type: 'String'}
            ],
            http: { verb: 'delete', path: '/deleteCompany/:id' }
        }
    );

    //checks if the connection string points to a real mongodb database
    Company.beforeRemote('__create__externalDatabases', function(context, extDbInstance, next){
        var connString = context.args.data.connString;
        console.log('> connection string: ', connString);
        mongoose.connect(connString);
        var db = mongoose.connection;
        db.on('error', function(){
            console.log('> connection error for the connection string: ', connString);
            context.args.data.connected = "false";
        })
    });
    //change name of a company wich as companyId= id
    Company.changeCompanyName = function(id, name, cb){
        Company.findById(id, function(err, company) {
            if(err)
                return cb(err);
           Company.findOne({where: {name: name}, limit: 1}, function(err, companyInstance) {
                if(!companyInstance){
                    var oldName = company.name;
                    company.updateAttribute('name', name, function(err, company) {
                        if(err) {
                          console.log('> Failed changing name');
                          return cb(err);
                        }
                          console.log('> Name changed successfully');
                          var data = {
                              newName: company.name,
                              oldName: oldName
                          };
                          return cb(null, null, data);
                    });
                }else{
                    var error = { message: 'A company with this name already exists' };
                    return cb(null, error);
                }
            });
        });
    }

Company.remoteMethod(
        'changeCompanyName',
        {
            description: "Change the name of a company",
            accepts: [
                { arg: 'id', type: 'string', required: true, description: 'Company id' },
                { arg: 'name', type: 'string', required: true, description: 'New name' },

            ],
            returns: [
                { arg: 'error', type: 'Object' },
                { arg: 'data', type: 'Object'},
            ],
            http: { verb: 'put', path: '/:id/changeCompanyName' }
        }
    );

};
<|endoftext|>