<commit_before>(function(tinymce) {
	var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE;

	/**
	 * Fixes a WebKit bug when deleting contents using backspace or delete key.
	 * WebKit will produce a span element if you delete across two block elements.
	 *
	 * Example:
	 *
a

|b

	 *
	 * Will produce this on backspace:
	 *
a<span class="Apple-style-span" style="<all runtime styles>">b

	 *
	 * This fixes the backspace to produce:
	 *
a|b

	 *
	 * See bug: https://bugs.webkit.org/show_bug.cgi?id=45784
	 *
	 * This code is a bit of a hack and hopefully it will be fixed soon in WebKit.
	 */
	function cleanupStylesWhenDeleting(ed) {
		var dom = ed.dom, selection = ed.selection;

		ed.onKeyDown.add(function(ed, e) {
			var rng, blockElm, node, clonedSpan, isDelete;

			if (e.isDefaultPrevented()) {
				return;
			}

			isDelete = e.keyCode == DELETE;
			if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
				e.preventDefault();
				rng = selection.getRng();

				// Find root block
				blockElm = dom.getParent(rng.startContainer, dom.isBlock);

				// On delete clone the root span of the next block element
				if (isDelete)
					blockElm = dom.getNext(blockElm, dom.isBlock);

				// Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace
				if (blockElm) {
					node = blockElm.firstChild;

					// Ignore empty text nodes
					while (node && node.nodeType == 3 && node.nodeValue.length == 0)
						node = node.nextSibling;

					if (node && node.nodeName === 'SPAN') {
						clonedSpan = node.cloneNode(false);
					}
				}

				// Do the backspace/delete action
				ed.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);

				// Find all odd apple-style-spans
				blockElm = dom.getParent(rng.startContainer, dom.isBlock);
				tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) {
					var bm = selection.getBookmark();

					if (clonedSpan) {
						dom.replace(clonedSpan.cloneNode(false), span, true);
					} else {
						dom.remove(span, true);
					}

					// Restore the selection
					selection.moveToBookmark(bm);
				});
			}
		});
	};

	/**
	 * WebKit and IE doesn't empty the editor if you select all contents and hit backspace or delete. This fix will check if the body is empty
	 * like a

 or

 and then forcefully remove all contents.
	 */
	function emptyEditorWhenDeleting(ed) {

		function serializeRng(rng) {
			var body = ed.dom.create("body");
			var contents = rng.cloneContents();
			body.appendChild(contents);
			return ed.selection.serializer.serialize(body, {format: 'html'});
		}

		function allContentsSelected(rng) {
			var selection = serializeRng(rng);

			var allRng = ed.dom.createRng();
			allRng.selectNode(ed.getBody());

			var allSelection = serializeRng(allRng);
			return selection === allSelection;
		}

		ed.onKeyDown.addToTop(function(ed, e) {
			var keyCode = e.keyCode;
			if (keyCode == DELETE || keyCode == BACKSPACE) {
				var rng = ed.selection.getRng(true);
				if (!rng.collapsed && allContentsSelected(rng)) {
					ed.setContent('', {format : 'raw'});
					ed.nodeChanged();
					e.preventDefault();
				}
			}
		});

	};

	/**
	 * WebKit on MacOS X has a weird issue where it some times fails to properly convert keypresses to input method keystrokes.
	 * So a fix where we just get the range and set the range back seems to do the trick.
	 */
	function inputMethodFocus(ed) {
		ed.dom.bind(ed.getDoc(), 'focusin', function() {
			ed.selection.setRng(ed.selection.getRng());
		});
	};

	/**
	 * Backspacing in FireFox/IE from a paragraph into a horizontal rule results in a floating text node because the
	 * browser just deletes the paragraph - the browser fails to merge the text node with a horizontal rule so it is
	 * left there. TinyMCE sees a floating text node and wraps it in a paragraph on the key up event (ForceBlocks.js
	 * addRootBlocks), meaning the action does nothing. With this code, FireFox/IE matche the behaviour of other
     * browsers
	 */
	function removeHrOnBackspace(ed) {
		ed.onKeyDown.add(function(ed, e) {
			if (e.keyCode === BACKSPACE) {
				if (ed.selection.isCollapsed() && ed.selection.getRng(true).startOffset === 0) {
					var node = ed.selection.getNode();
					var previousSibling = node.previousSibling;
					if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") {
						ed.dom.remove(previousSibling);
						tinymce.dom.Event.cancel(e);
					}
				}
			}
		})
	}

	/**
	 * Firefox 3.x has an issue where the body element won't get proper focus if you click out
	 * side it's rectangle.
	 */
	function focusBody(ed) {
		// Fix for a focus bug in FF 3.x where the body element
		// wouldn't get proper focus if the user clicked on the HTML element
		if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
			ed.onMouseDown.add(function(ed, e) {
				if (e.target.nodeName === "HTML") {
					var body = ed.getBody();

					// Blur the body it's focused but not correctly focused
					body.blur();

					// Refocus the body after a little while
					setTimeout(function() {
						body.focus();
					}, 0);
				}
			});
		}
	};

	/**
	 * WebKit has a bug where it isn't possible to select image, hr or anchor elements
	 * by clicking on them so we need to fake that.
	 */
	function selectControlElements(ed) {
		ed.onClick.add(function(ed, e) {
			e = e.target;

			// Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
			// WebKit can't even do simple things like selecting an image
			// Needs tobe the setBaseAndExtend or it will fail to select floated images
			if (/^(IMG|HR)$/.test(e.nodeName))
				ed.selection.getSel().setBaseAndExtent(e, 0, e, 1);

			if (e.nodeName == 'A' && ed.dom.hasClass(e, 'mceItemAnchor'))
				ed.selection.select(e);

			ed.nodeChanged();
		});
	};

	/**
	 * If you hit enter from a heading in IE, the resulting P tag below it shares the style property (bad)
	 * */
	function removeStylesOnPTagsInheritedFromHeadingTag(ed) {
		ed.onKeyDown.add(function(ed, event) {
			function checkInHeadingTag(ed) {
				var currentNode = ed.selection.getNode();
				var headingTags = 'h1,h2,h3,h4,h5,h6';
				return ed.dom.is(currentNode, headingTags) || ed.dom.getParent(currentNode, headingTags) !== null;
			}

			if (event.keyCode === VK.ENTER && !VK.modifierPressed(event) && checkInHeadingTag(ed)) {
				setTimeout(function() {
					var currentNode = ed.selection.getNode();
					if (ed.dom.is(currentNode, 'p')) {
						ed.dom.setAttrib(currentNode, 'style', null);
						// While tiny's content is correct after this method call, the content shown is not representative of it and needs to be 'repainted'
						ed.execCommand('mceCleanup');
					}
				}, 0);
			}
		});
	}
	/**
	 * Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5. It only fires the nodeChange
	 * event every 50ms since it would other wise update the UI when you type and it hogs the CPU.
	 */
	function selectionChangeNodeChanged(ed) {
		var lastRng, selectionTimer;

		ed.dom.bind(ed.getDoc(), 'selectionchange', function() {
			if (selectionTimer) {
				clearTimeout(selectionTimer);
				selectionTimer = 0;
			}

			selectionTimer = window.setTimeout(function() {
				var rng = ed.selection.getRng();

				// Compare the ranges to see if it was a real change or not
				if (!lastRng || !tinymce.dom.RangeUtils.compareRanges(rng, lastRng)) {
					ed.nodeChanged();
					lastRng = rng;
				}
			}, 50);
		});
	}

	/**
	 * Screen readers on IE needs to have the role application set on the body.
	 */
	function ensureBodyHasRoleApplication(ed) {
		document.body.setAttribute("role", "application");
	}

	tinymce.create('tinymce.util.Quirks', {
		Quirks: function(ed) {
			// WebKit
			if (tinymce.isWebKit) {
				cleanupStylesWhenDeleting(ed);
				emptyEditorWhenDeleting(ed);
				inputMethodFocus(ed);
				selectControlElements(ed);

				// iOS
				if (tinymce.isIDevice) {
					selectionChangeNodeChanged(ed);
				}
			}

			// IE
			if (tinymce.isIE) {
				removeHrOnBackspace(ed);
				emptyEditorWhenDeleting(ed);
				ensureBodyHasRoleApplication(ed);
				removeStylesOnPTagsInheritedFromHeadingTag(ed)
			}

			// Gecko
			if (tinymce.isGecko) {
				removeHrOnBackspace(ed);
				focusBody(ed);
			}
		}
	});
})(tinymce);
<commit_msg>Removed removeStylesOnPTagsInheritedFromHeadingTag from Quirks.js since the enter/return behavior is now normalized.<commit_after>(function(tinymce) {
	var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE;

	/**
	 * Fixes a WebKit bug when deleting contents using backspace or delete key.
	 * WebKit will produce a span element if you delete across two block elements.
	 *
	 * Example:
	 *
a

|b

	 *
	 * Will produce this on backspace:
	 *
a<span class="Apple-style-span" style="<all runtime styles>">b

	 *
	 * This fixes the backspace to produce:
	 *
a|b

	 *
	 * See bug: https://bugs.webkit.org/show_bug.cgi?id=45784
	 *
	 * This code is a bit of a hack and hopefully it will be fixed soon in WebKit.
	 */
	function cleanupStylesWhenDeleting(ed) {
		var dom = ed.dom, selection = ed.selection;

		ed.onKeyDown.add(function(ed, e) {
			var rng, blockElm, node, clonedSpan, isDelete;

			if (e.isDefaultPrevented()) {
				return;
			}

			isDelete = e.keyCode == DELETE;
			if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
				e.preventDefault();
				rng = selection.getRng();

				// Find root block
				blockElm = dom.getParent(rng.startContainer, dom.isBlock);

				// On delete clone the root span of the next block element
				if (isDelete)
					blockElm = dom.getNext(blockElm, dom.isBlock);

				// Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace
				if (blockElm) {
					node = blockElm.firstChild;

					// Ignore empty text nodes
					while (node && node.nodeType == 3 && node.nodeValue.length == 0)
						node = node.nextSibling;

					if (node && node.nodeName === 'SPAN') {
						clonedSpan = node.cloneNode(false);
					}
				}

				// Do the backspace/delete action
				ed.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);

				// Find all odd apple-style-spans
				blockElm = dom.getParent(rng.startContainer, dom.isBlock);
				tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) {
					var bm = selection.getBookmark();

					if (clonedSpan) {
						dom.replace(clonedSpan.cloneNode(false), span, true);
					} else {
						dom.remove(span, true);
					}

					// Restore the selection
					selection.moveToBookmark(bm);
				});
			}
		});
	};

	/**
	 * WebKit and IE doesn't empty the editor if you select all contents and hit backspace or delete. This fix will check if the body is empty
	 * like a

 or

 and then forcefully remove all contents.
	 */
	function emptyEditorWhenDeleting(ed) {

		function serializeRng(rng) {
			var body = ed.dom.create("body");
			var contents = rng.cloneContents();
			body.appendChild(contents);
			return ed.selection.serializer.serialize(body, {format: 'html'});
		}

		function allContentsSelected(rng) {
			var selection = serializeRng(rng);

			var allRng = ed.dom.createRng();
			allRng.selectNode(ed.getBody());

			var allSelection = serializeRng(allRng);
			return selection === allSelection;
		}

		ed.onKeyDown.addToTop(function(ed, e) {
			var keyCode = e.keyCode;
			if (keyCode == DELETE || keyCode == BACKSPACE) {
				var rng = ed.selection.getRng(true);
				if (!rng.collapsed && allContentsSelected(rng)) {
					ed.setContent('', {format : 'raw'});
					ed.nodeChanged();
					e.preventDefault();
				}
			}
		});

	};

	/**
	 * WebKit on MacOS X has a weird issue where it some times fails to properly convert keypresses to input method keystrokes.
	 * So a fix where we just get the range and set the range back seems to do the trick.
	 */
	function inputMethodFocus(ed) {
		ed.dom.bind(ed.getDoc(), 'focusin', function() {
			ed.selection.setRng(ed.selection.getRng());
		});
	};

	/**
	 * Backspacing in FireFox/IE from a paragraph into a horizontal rule results in a floating text node because the
	 * browser just deletes the paragraph - the browser fails to merge the text node with a horizontal rule so it is
	 * left there. TinyMCE sees a floating text node and wraps it in a paragraph on the key up event (ForceBlocks.js
	 * addRootBlocks), meaning the action does nothing. With this code, FireFox/IE matche the behaviour of other
     * browsers
	 */
	function removeHrOnBackspace(ed) {
		ed.onKeyDown.add(function(ed, e) {
			if (e.keyCode === BACKSPACE) {
				if (ed.selection.isCollapsed() && ed.selection.getRng(true).startOffset === 0) {
					var node = ed.selection.getNode();
					var previousSibling = node.previousSibling;
					if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") {
						ed.dom.remove(previousSibling);
						tinymce.dom.Event.cancel(e);
					}
				}
			}
		})
	}

	/**
	 * Firefox 3.x has an issue where the body element won't get proper focus if you click out
	 * side it's rectangle.
	 */
	function focusBody(ed) {
		// Fix for a focus bug in FF 3.x where the body element
		// wouldn't get proper focus if the user clicked on the HTML element
		if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
			ed.onMouseDown.add(function(ed, e) {
				if (e.target.nodeName === "HTML") {
					var body = ed.getBody();

					// Blur the body it's focused but not correctly focused
					body.blur();

					// Refocus the body after a little while
					setTimeout(function() {
						body.focus();
					}, 0);
				}
			});
		}
	};

	/**
	 * WebKit has a bug where it isn't possible to select image, hr or anchor elements
	 * by clicking on them so we need to fake that.
	 */
	function selectControlElements(ed) {
		ed.onClick.add(function(ed, e) {
			e = e.target;

			// Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
			// WebKit can't even do simple things like selecting an image
			// Needs tobe the setBaseAndExtend or it will fail to select floated images
			if (/^(IMG|HR)$/.test(e.nodeName))
				ed.selection.getSel().setBaseAndExtent(e, 0, e, 1);

			if (e.nodeName == 'A' && ed.dom.hasClass(e, 'mceItemAnchor'))
				ed.selection.select(e);

			ed.nodeChanged();
		});
	};

	/**
	 * If you hit enter from a heading in IE, the resulting P tag below it shares the style property (bad)
	 * */
	 /*
	function removeStylesOnPTagsInheritedFromHeadingTag(ed) {
		ed.onKeyDown.add(function(ed, event) {
			function checkInHeadingTag(ed) {
				var currentNode = ed.selection.getNode();
				var headingTags = 'h1,h2,h3,h4,h5,h6';
				return ed.dom.is(currentNode, headingTags) || ed.dom.getParent(currentNode, headingTags) !== null;
			}

			if (event.keyCode === VK.ENTER && !VK.modifierPressed(event) && checkInHeadingTag(ed)) {
				setTimeout(function() {
					var currentNode = ed.selection.getNode();
					if (ed.dom.is(currentNode, 'p')) {
						ed.dom.setAttrib(currentNode, 'style', null);
						// While tiny's content is correct after this method call, the content shown is not representative of it and needs to be 'repainted'
						ed.execCommand('mceCleanup');
					}
				}, 0);
			}
		});
	}
	*/

	/**
	 * Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5. It only fires the nodeChange
	 * event every 50ms since it would other wise update the UI when you type and it hogs the CPU.
	 */
	function selectionChangeNodeChanged(ed) {
		var lastRng, selectionTimer;

		ed.dom.bind(ed.getDoc(), 'selectionchange', function() {
			if (selectionTimer) {
				clearTimeout(selectionTimer);
				selectionTimer = 0;
			}

			selectionTimer = window.setTimeout(function() {
				var rng = ed.selection.getRng();

				// Compare the ranges to see if it was a real change or not
				if (!lastRng || !tinymce.dom.RangeUtils.compareRanges(rng, lastRng)) {
					ed.nodeChanged();
					lastRng = rng;
				}
			}, 50);
		});
	}

	/**
	 * Screen readers on IE needs to have the role application set on the body.
	 */
	function ensureBodyHasRoleApplication(ed) {
		document.body.setAttribute("role", "application");
	}

	tinymce.create('tinymce.util.Quirks', {
		Quirks: function(ed) {
			// WebKit
			if (tinymce.isWebKit) {
				cleanupStylesWhenDeleting(ed);
				emptyEditorWhenDeleting(ed);
				inputMethodFocus(ed);
				selectControlElements(ed);

				// iOS
				if (tinymce.isIDevice) {
					selectionChangeNodeChanged(ed);
				}
			}

			// IE
			if (tinymce.isIE) {
				removeHrOnBackspace(ed);
				emptyEditorWhenDeleting(ed);
				ensureBodyHasRoleApplication(ed);
				//removeStylesOnPTagsInheritedFromHeadingTag(ed)
			}

			// Gecko
			if (tinymce.isGecko) {
				removeHrOnBackspace(ed);
				focusBody(ed);
			}
		}
	});
})(tinymce);
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import { searchRequest, loadAll as loadGuests} from 'redux/modules/guests';
import FixedDataTable from 'fixed-data-table';
const {Table, Column, Cell} = FixedDataTable;

const DateCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data[rowIndex][col].toLocaleString()}
  </Cell>
);

const TextCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data[rowIndex][col]}
  </Cell>
);

function select(state) {
  return {
    guests: state.guests.data,
    filteredGuests: state.guests.filteredData,
    error: state.guests.error,
    loading: state.guests.loading,
    loaded: state.guests.loaded
  };
}

@connect(select)
export default class GuestList extends Component {
  static propTypes = {
    guests: PropTypes.array,
    filteredGuests: PropTypes.array,
    error: PropTypes.string,
    loading: PropTypes.bool,
    loaded: PropTypes.bool,
    dispatch: PropTypes.func.isRequired
  }

  constructor(props) {
    super(props);
    this._onFilterChange = this._onFilterChange.bind(this);
    require('fixed-data-table/dist/fixed-data-table.min.css');
  }

  /**
   * Loading the data if not loaded yet.
   * @return {[type]} [description]
   */
  componentWillMount() {
    if (!this.props.loaded) {
      return this.props.dispatch(loadGuests());
    }
  }

  _onFilterChange(event) {
    let filterBy;
    if (!event || !event.target.value) {
      filterBy = '';
    } else {
      filterBy = event.target.value.toLowerCase();
    }
    this.props.dispatch(searchRequest(filterBy));
  }

  render() {
    const { filteredGuests, loaded } = this.props;
    const styles = require('./GuestList.scss');
    if (!loaded) {
      return (

 Loading ...

      );
    }
    return (

        <input
          onChange={this._onFilterChange}
          className={styles.search_input + ' form-control'}
          placeholder="Filter by first, last or nickname"
        />

          <Column
            header={<Cell>First Name</Cell>}
            cell={<TextCell data={filteredGuests} col="first_name" />}
            fixed
            width={100}
          />
          <Column
            header={<Cell>Last Name</Cell>}
            cell={<TextCell data={filteredGuests} col="last_name" />}
            fixed
            width={100}
          />
          <Column
            header={<Cell>Nickname</Cell>}
            cell={<TextCell data={filteredGuests} col="nickname" />}
            fixed
            width={100}
          />
          <Column
            header={<Cell>DOB</Cell>}
            cell={<DateCell data={filteredGuests} col="birthdate" />}
            width={200}
          />

    );
  }
}
<commit_msg>Changing the table dimension<commit_after>import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import { searchRequest, loadAll as loadGuests} from 'redux/modules/guests';
import FixedDataTable from 'fixed-data-table';
const {Table, Column, Cell} = FixedDataTable;

const DateCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data[rowIndex][col].toLocaleString()}
  </Cell>
);

const TextCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data[rowIndex][col]}
  </Cell>
);

function select(state) {
  return {
    guests: state.guests.data,
    filteredGuests: state.guests.filteredData,
    error: state.guests.error,
    loading: state.guests.loading,
    loaded: state.guests.loaded
  };
}

@connect(select)
export default class GuestList extends Component {
  static propTypes = {
    guests: PropTypes.array,
    filteredGuests: PropTypes.array,
    error: PropTypes.string,
    loading: PropTypes.bool,
    loaded: PropTypes.bool,
    dispatch: PropTypes.func.isRequired
  }

  constructor(props) {
    super(props);
    this._onFilterChange = this._onFilterChange.bind(this);
    require('fixed-data-table/dist/fixed-data-table.min.css');
  }

  /**
   * Loading the data if not loaded yet.
   * @return {[type]} [description]
   */
  componentWillMount() {
    if (!this.props.loaded) {
      return this.props.dispatch(loadGuests());
    }
  }

  _onFilterChange(event) {
    let filterBy;
    if (!event || !event.target.value) {
      filterBy = '';
    } else {
      filterBy = event.target.value.toLowerCase();
    }
    this.props.dispatch(searchRequest(filterBy));
  }

  render() {
    const { filteredGuests, loaded } = this.props;
    const styles = require('./GuestList.scss');
    if (!loaded) {
      return (

 Loading ...

      );
    }
    return (

        <input
          onChange={this._onFilterChange}
          className={styles.search_input + ' form-control'}
          placeholder="Filter by first, last or nickname"
        />

          <Column
            header={<Cell>First Name</Cell>}
            cell={<TextCell data={filteredGuests} col="first_name" />}
            fixed
            width={100}
          />
          <Column
            header={<Cell>Last Name</Cell>}
            cell={<TextCell data={filteredGuests} col="last_name" />}
            fixed
            width={100}
          />
          <Column
            header={<Cell>Nickname</Cell>}
            cell={<TextCell data={filteredGuests} col="nickname" />}
            fixed
            width={100}
          />
          <Column
            header={<Cell>Birthdate</Cell>}
            cell={<DateCell data={filteredGuests} col="birthdate" />}
            width={200}
          />

    );
  }
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Field, reduxForm } from 'redux-form';
import Button from 'react-bootstrap/lib/Button';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';
import FormControl from 'react-bootstrap/lib/FormControl';
import { connect } from 'react-redux';
import styles from 'common/Common.scss';
import patientStyles from 'containers/Patients/Patients.scss';
import DateTimePicker from 'react-widgets/lib/DateTimePicker';

const Moment = require('moment');
const momentLocalizer = require('react-widgets/lib/localizers/moment');
const numberLocalizer = require('react-widgets/lib/localizers/simple-number');

momentLocalizer(Moment);
numberLocalizer();

const renderField = ({ input, label, meta: { touched, error, warning }, ...rest }) => {
  return (
    <FormGroup controlId={input.name} className={(error && touched ? ' has-error' : '')}>
      <ControlLabel>{label}</ControlLabel>
      <FormControl {...input} {...rest} />
      {touched && ((error && {error}) || (warning && {warning}))}
    </FormGroup>
  );
};

const renderDateInput = ({ input, label, meta: { touched, error, warning }, ...rest }) => {
  console.log(input.onBlur);
  const {onBlur, ...args} = input;
  return (
    <FormGroup controlId={input.name} className={(error && touched ? 'has-error' : '')}>
      <ControlLabel>{label}</ControlLabel>
        <Field
          {...args}
          {...rest}
          time={false}
          component={DateTimePicker}
          defaultValue={null} />
      {touched && ((error && {error}) || (warning && {warning}))}
    </FormGroup>
  );
};

const renderCheckbox = ({ input, label, meta: { touched, error, warning }, ...rest }) => {
  return (

      <FormControl {...input} {...rest} />
      <ControlLabel>{label}</ControlLabel>
      {touched && ((error && {error}) || (warning && {warning}))}

  );
};

const validate = values => {
  const errors = {};
  const {gender, firstname, lastname, dateofbirth} = values;

  if (!/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}$/.test(dateofbirth)) {
    errors.dateofbirth = 'Invalid Date Format';
  }

  if (!firstname) {
    errors.firstname = 'Required';
  }

  if (!lastname) {
    errors.lastname = 'Required';
  }

  if (!gender) {
    errors.gender = 'Required';
  }

  if (!dateofbirth) {
    errors.dateofbirth = 'Required';
  }

  return errors;
};

@connect(state => ({
  ethnicity: state.lookups.ethnicity,
  gender: state.lookups.gender,
  title: state.lookups.title
}))
@reduxForm({
  form: 'Patient',
  validate
})
export default class PatientForm extends Component {
  static propTypes = {
    submitting: PropTypes.bool.isRequired,
    ethnicity: PropTypes.arrayOf(PropTypes.shape({
      lookupname: PropTypes.string.isRequired,
      lookupvalue: PropTypes.number.isRequired,
      lookuptext: PropTypes.string.isRequired,
      displayorder: PropTypes.number.isRequired,
      createddate: PropTypes.string.isRequired,
      updateddate: PropTypes.string.isRequired,
      recordstatusid: PropTypes.number.isRequired,
      id: PropTypes.string.isRequired
    }).isRequired).isRequired,
    gender: PropTypes.arrayOf(PropTypes.shape({
      lookupname: PropTypes.string.isRequired,
      lookupvalue: PropTypes.number.isRequired,
      lookuptext: PropTypes.string.isRequired,
      displayorder: PropTypes.number.isRequired,
      createddate: PropTypes.string.isRequired,
      updateddate: PropTypes.string.isRequired,
      recordstatusid: PropTypes.number.isRequired,
      id: PropTypes.string.isRequired
    }).isRequired).isRequired,
    title: PropTypes.arrayOf(PropTypes.shape({
      lookupname: PropTypes.string.isRequired,
      lookupvalue: PropTypes.number.isRequired,
      lookuptext: PropTypes.string.isRequired,
      displayorder: PropTypes.number.isRequired,
      createddate: PropTypes.string.isRequired,
      updateddate: PropTypes.string.isRequired,
      recordstatusid: PropTypes.number.isRequired,
      id: PropTypes.string.isRequired
    }).isRequired).isRequired,
    handleSubmit: PropTypes.func.isRequired
  }

  render() {
    const {handleSubmit, ethnicity, title, gender} = this.props;
    return (

        <form onSubmit={handleSubmit}>

Details

                <Button style={{ width: '100%' }}>Cancel</Button>

                <Button style={{ width: '100%' }} type="submit" bsStyle="primary">Save</Button>

                  Title
                  <Field name="title" component="select" className="form-control">
                    <option value="0">Title</option>
                    {
                      title.map(lookup =>
                        <option value={lookup.lookupvalue} key={lookup.lookupvalue}>{lookup.lookuptext}</option>
                      )
                    }
                  </Field>

                  <Field name="firstname" label="First Name" maxLength="100" type="text" component={renderField} placeholder="First Name" />

                  <Field name="middlename" label="Middle Name" maxLength="100" type="text" component={renderField} placeholder="Middle Name" />

                  <Field name="lastname" label="Last Name" maxLength="100" type="text" component={renderField} placeholder="Last Name" />

                  <Field name="preferredname" label="Preferred Name" maxLength="100" type="text" component={renderField} placeholder="Preferred Name" />

                  <Field name="previouslyknownas" label="Previously Known As" maxLength="100" type="text" component={renderField} placeholder="Previously Known As" />

                  <Field name="onenameonly" type="checkbox" className="styled" component={renderCheckbox} label="One Name Only" />

                  <Field name="dateofbirth" label="Date of Birth" maxLength="100" type="text" component={renderDateInput} placeholder="Date of Birth" />

                  Gender
                  <Field name="gender" component="select" className="form-control">
                    <option value="0">Gender</option>
                    {
                      gender.map(lookup =>
                        <option value={lookup.lookupvalue} key={lookup.lookupvalue}>{lookup.lookuptext}</option>
                      )
                    }
                  </Field>

                  Ethinicity
                  <Field name="ethinicity" component="select" className="form-control">
                    <option value="0">Ethinicity</option>
                    {
                      ethnicity.map(lookup =>
                        <option value={lookup.lookupvalue} key={lookup.lookupvalue}>{lookup.lookuptext}</option>
                      )
                    }
                  </Field>

                  <Field name="englishis2ndlanguage" type="checkbox" className="styled" component={renderCheckbox} label="English is a second language" />

                  <Field name="notes" componentClass="textarea" rows="5" component={renderField} label="Enter Notes" placeholder="Enter Notes" />

        </form>

    );
  }
}
<commit_msg>dev(patient) set locale to 'id' => indonesia<commit_after>import React, { Component, PropTypes } from 'react';
import { Field, reduxForm } from 'redux-form';
import Button from 'react-bootstrap/lib/Button';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';
import FormControl from 'react-bootstrap/lib/FormControl';
import { connect } from 'react-redux';
import styles from 'common/Common.scss';
import patientStyles from 'containers/Patients/Patients.scss';
import DateTimePicker from 'react-widgets/lib/DateTimePicker';

const Moment = require('moment');
const momentLocalizer = require('react-widgets/lib/localizers/moment');
const numberLocalizer = require('react-widgets/lib/localizers/simple-number');

Moment.locale('id');
momentLocalizer(Moment);
numberLocalizer();

const renderField = ({ input, label, meta: { touched, error, warning }, ...rest }) => {
  return (
    <FormGroup controlId={input.name} className={(error && touched ? ' has-error' : '')}>
      <ControlLabel>{label}</ControlLabel>
      <FormControl {...input} {...rest} />
      {touched && ((error && {error}) || (warning && {warning}))}
    </FormGroup>
  );
};

const renderDateInput = ({ input, label, meta: { touched, error, warning }, ...rest }) => {
  return (
    <FormGroup controlId={input.name + '_input'} className={(error && touched ? 'has-error' : '')}>
      <ControlLabel>{label}</ControlLabel>
        <Field
          {...input}
          {...rest}
          id={input.name}
          time={false}
          component={DateTimePicker}
          defaultValue={null} />
      {touched && ((error && {error}) || (warning && {warning}))}
    </FormGroup>
  );
};

const renderCheckbox = ({ input, label, meta: { touched, error, warning }, ...rest }) => {
  return (

      <FormControl {...input} {...rest} />
      <ControlLabel>{label}</ControlLabel>
      {touched && ((error && {error}) || (warning && {warning}))}

  );
};

const validate = values => {
  const errors = {};
  const {gender, firstname, lastname, dateofbirth} = values;

  if (!firstname) {
    errors.firstname = 'Required';
  }

  if (!lastname) {
    errors.lastname = 'Required';
  }

  if (!gender) {
    errors.gender = 'Required';
  }

  if (!dateofbirth) {
    errors.dateofbirth = 'Required';
  }

  return errors;
};

@connect(state => ({
  ethnicity: state.lookups.ethnicity,
  gender: state.lookups.gender,
  title: state.lookups.title
}))
@reduxForm({
  form: 'Patient',
  validate
})
export default class PatientForm extends Component {
  static propTypes = {
    submitting: PropTypes.bool.isRequired,
    ethnicity: PropTypes.arrayOf(PropTypes.shape({
      lookupname: PropTypes.string.isRequired,
      lookupvalue: PropTypes.number.isRequired,
      lookuptext: PropTypes.string.isRequired,
      displayorder: PropTypes.number.isRequired,
      createddate: PropTypes.string.isRequired,
      updateddate: PropTypes.string.isRequired,
      recordstatusid: PropTypes.number.isRequired,
      id: PropTypes.string.isRequired
    }).isRequired).isRequired,
    gender: PropTypes.arrayOf(PropTypes.shape({
      lookupname: PropTypes.string.isRequired,
      lookupvalue: PropTypes.number.isRequired,
      lookuptext: PropTypes.string.isRequired,
      displayorder: PropTypes.number.isRequired,
      createddate: PropTypes.string.isRequired,
      updateddate: PropTypes.string.isRequired,
      recordstatusid: PropTypes.number.isRequired,
      id: PropTypes.string.isRequired
    }).isRequired).isRequired,
    title: PropTypes.arrayOf(PropTypes.shape({
      lookupname: PropTypes.string.isRequired,
      lookupvalue: PropTypes.number.isRequired,
      lookuptext: PropTypes.string.isRequired,
      displayorder: PropTypes.number.isRequired,
      createddate: PropTypes.string.isRequired,
      updateddate: PropTypes.string.isRequired,
      recordstatusid: PropTypes.number.isRequired,
      id: PropTypes.string.isRequired
    }).isRequired).isRequired,
    handleSubmit: PropTypes.func.isRequired
  }

  render() {
    const {handleSubmit, ethnicity, title, gender} = this.props;
    return (

        <form onSubmit={handleSubmit}>

Details

                <Button style={{ width: '100%' }}>Cancel</Button>

                <Button style={{ width: '100%' }} type="submit" bsStyle="primary">Save</Button>

                  Title
                  <Field name="title" component="select" className="form-control">
                    <option value="0">Title</option>
                    {
                      title.map(lookup =>
                        <option value={lookup.lookupvalue} key={lookup.lookupvalue}>{lookup.lookuptext}</option>
                      )
                    }
                  </Field>

                  <Field name="firstname" label="First Name" maxLength="100" type="text" component={renderField} placeholder="First Name" />

                  <Field name="middlename" label="Middle Name" maxLength="100" type="text" component={renderField} placeholder="Middle Name" />

                  <Field name="lastname" label="Last Name" maxLength="100" type="text" component={renderField} placeholder="Last Name" />

                  <Field name="preferredname" label="Preferred Name" maxLength="100" type="text" component={renderField} placeholder="Preferred Name" />

                  <Field name="previouslyknownas" label="Previously Known As" maxLength="100" type="text" component={renderField} placeholder="Previously Known As" />

                  <Field name="onenameonly" type="checkbox" className="styled" component={renderCheckbox} label="One Name Only" />

                  <Field name="dateofbirth" label="Date of Birth" maxLength="100" type="text" component={renderDateInput} placeholder="Date of Birth" />

                  Gender
                  <Field name="gender" component="select" className="form-control">
                    <option value="0">Gender</option>
                    {
                      gender.map(lookup =>
                        <option value={lookup.lookupvalue} key={lookup.lookupvalue}>{lookup.lookuptext}</option>
                      )
                    }
                  </Field>

                  Ethinicity
                  <Field name="ethinicity" component="select" className="form-control">
                    <option value="0">Ethinicity</option>
                    {
                      ethnicity.map(lookup =>
                        <option value={lookup.lookupvalue} key={lookup.lookupvalue}>{lookup.lookuptext}</option>
                      )
                    }
                  </Field>

                  <Field name="englishis2ndlanguage" type="checkbox" className="styled" component={renderCheckbox} label="English is a second language" />

                  <Field name="notes" componentClass="textarea" rows="5" component={renderField} label="Enter Notes" placeholder="Enter Notes" />

        </form>

    );
  }
}
<|endoftext|>


<commit_before>define('BandController', [
    'audioConfig',
    'bandConfig',
    'bandService',
    'arrayHelpers'
], function(audioConfig, bandConfig, bandService, arrayHelpers) {
    'use strict';

    var $bandContainer =
        document.querySelector('#animalBand .band__container'),
        renderer,
        stage,
        numberOfClicksOnMonkey = 0,
        text,
        animationObjects = {},
        blinkingIdle;

    return {
        init: init,
        setIdleAnimationState: setIdleAnimationState
    };

    function init() {
        setRenderer();
        setStage();
    }

    function setRenderer() {
        renderer = PIXI.autoDetectRenderer(
            $bandContainer.offsetWidth,
            $bandContainer.offsetHeight,
            bandConfig.rendererOptions
        );
        bandService.setRendererStyle(renderer);
        renderer.autoResize = true;
        $bandContainer.appendChild(renderer.view);
    }

    function setStage() {
        stage = new PIXI.Container();
        PIXI.ticker.shared.add(renderHandler);
        initAnimalAnimation();

        function renderHandler (deltaTime) {
            renderer.render(stage);
        };
    }

    function initAnimalAnimation() {
        var factory = new dragonBones.PixiFactory(),
            animationData;

        for(var animation in bandConfig.animations) {
            animationData = bandConfig.animations[animation].data
            PIXI.loader.add(animation + 'Bones', animationData.bones)
            PIXI.loader.add(animation + 'Texture', animationData.texture)
            PIXI.loader.add(animation + 'Atlas', animationData.atlas)
        }

        PIXI.loader.once("complete", onLoadComplete);
        PIXI.loader.load();

        function onLoadComplete (loader, object) {
            for(var animation in bandConfig.animations) {
                factory.parseDragonBonesData(
                    object[animation + 'Bones'].data
                );
                factory.parseTextureAtlasData(
                    object[animation + 'Texture'].data,
                    object[animation + 'Atlas'].texture
                );
                animationObjects[animation] = factory.buildArmatureDisplay(
                    animation.charAt(0).toUpperCase() + animation.slice(1)
                );
                animationObjects[animation].scale.set(
                    bandConfig.animations[animation].scale
                );
                animationObjects[animation].x =
                    renderer.width * bandConfig.animations[animation].position.x;
                animationObjects[animation].y =
                    renderer.height * bandConfig.animations[animation].position.y;
                animationObjects[animation].animation.timeScale = 1;
                animationObjects[animation].animation.gotoAndPlay('Idle', 0.3, -1, 0);
            }
            setBackground();
            setMusicHandler();
            setIdleAnimationState();
        }

        function setBackground() {
            var backgroud = new PIXI.Sprite(
                PIXI.Texture.fromImage(bandConfig.backgroundImg
            ));
            backgroud.width = renderer.width;
            backgroud.height = renderer.height;
            stage.addChild(backgroud);
        }

        function setAnimationItemsonStage() {
            for(var animation in animations) {
                stage.addChild(animationObjects[animation]);
            }
        }
    }

    function setIdleAnimationState() {
        for(var animation in bandConfig.animations) {
            animationObjects[animation].animation.timeScale = 1;
            animationObjects[animation].animation.gotoAndPlay('Idle', 0.3, -1, 0);
            stage.addChild(animationObjects[animation]);
        }
    }

    function setMusicHandler() {
        document.querySelector('.timeline')
            .addEventListener('animalBand.audio.rhythmIndex', function(e) {
                audioConfig.matrix.result.map(function(instrument, index) {
                    var rhythmIndex = e.detail.rhythmIndex,
                        animationId = bandConfig.animationsMapping[instrument],
                        animationData = bandConfig.animations[animationId],
                        isInstrumentSet = audioConfig.matrix.entities[instrument][rhythmIndex],
                        isTom1Set = audioConfig.matrix.entities['tom1'][rhythmIndex],
                        isTom2Set = audioConfig.matrix.entities['tom2'][rhythmIndex],
                        animationType;

                    if(isInstrumentSet) {
                        if(animationId === 'lion') {
                            if(isTom1Set && isTom2Set) {
                                animationType = arrayHelpers.getRandomValue(
                                    animationData.types.tom1tom2
                                );
                            } else if (isTom1Set) {
                                animationType = arrayHelpers.getRandomValue(
                                    animationData.types.tom1
                                );
                            } else if (isTom2Set) {
                                animationType = arrayHelpers.getRandomValue(
                                    animationData.types.tom2
                                );
                            }
                        } else {
                            animationType = arrayHelpers.getRandomValue(
                                animationData.types
                            );
                        }
                        animationObjects[animationId].animation.timeScale = 2;
                        animationObjects[animationId].animation.gotoAndPlay(
                            animationType, -1, -1, 1
                        );
                    } else {
                        if(!isTom1Set){
                            animationObjects[animationId].animation.timeScale = 2;
                            var animation = bandConfig.animations[instrument]
                            var rand = Math.floor((Math.random() * 100) + 1);
                            if(rand < 10) {
                                animationObjects[animationId].animation.gotoAndPlay(
                                    'Idle_Blink', -1, -1, 1
                                );
                            }
                            else {
                                 animationObjects[animationId].animation.gotoAndPlay(
                                     'Idle', -1, -1, 1
                                 );
                            }
                        }
                    }
                });
            });
    }
});
<commit_msg>Bug fix<commit_after>define('BandController', [
    'audioConfig',
    'bandConfig',
    'bandService',
    'arrayHelpers'
], function(audioConfig, bandConfig, bandService, arrayHelpers) {
    'use strict';

    var $bandContainer =
        document.querySelector('#animalBand .band__container'),
        renderer,
        stage,
        numberOfClicksOnMonkey = 0,
        text,
        animationObjects = {},
        blinkingIdle;

    return {
        init: init,
        setIdleAnimationState: setIdleAnimationState
    };

    function init() {
        setRenderer();
        setStage();
    }

    function setRenderer() {
        renderer = PIXI.autoDetectRenderer(
            $bandContainer.offsetWidth,
            $bandContainer.offsetHeight,
            bandConfig.rendererOptions
        );
        bandService.setRendererStyle(renderer);
        renderer.autoResize = true;
        $bandContainer.appendChild(renderer.view);
    }

    function setStage() {
        stage = new PIXI.Container();
        PIXI.ticker.shared.add(renderHandler);
        initAnimalAnimation();

        function renderHandler (deltaTime) {
            renderer.render(stage);
        };
    }

    function initAnimalAnimation() {
        var factory = new dragonBones.PixiFactory(),
            animationData;

        for(var animation in bandConfig.animations) {
            animationData = bandConfig.animations[animation].data
            PIXI.loader.add(animation + 'Bones', animationData.bones)
            PIXI.loader.add(animation + 'Texture', animationData.texture)
            PIXI.loader.add(animation + 'Atlas', animationData.atlas)
        }

        PIXI.loader.once("complete", onLoadComplete);
        PIXI.loader.load();

        function onLoadComplete (loader, object) {
            for(var animation in bandConfig.animations) {
                factory.parseDragonBonesData(
                    object[animation + 'Bones'].data
                );
                factory.parseTextureAtlasData(
                    object[animation + 'Texture'].data,
                    object[animation + 'Atlas'].texture
                );
                animationObjects[animation] = factory.buildArmatureDisplay(
                    animation.charAt(0).toUpperCase() + animation.slice(1)
                );
                animationObjects[animation].scale.set(
                    bandConfig.animations[animation].scale
                );
                animationObjects[animation].x =
                    renderer.width * bandConfig.animations[animation].position.x;
                animationObjects[animation].y =
                    renderer.height * bandConfig.animations[animation].position.y;
                animationObjects[animation].animation.timeScale = 1;
                animationObjects[animation].animation.gotoAndPlay('Idle', 0.3, -1, 0);
            }
            setBackground();
            setMusicHandler();
            setIdleAnimationState();
        }

        function setBackground() {
            var backgroud = new PIXI.Sprite(
                PIXI.Texture.fromImage(bandConfig.backgroundImg
            ));
            backgroud.width = renderer.width;
            backgroud.height = renderer.height;
            stage.addChild(backgroud);
        }

        function setAnimationItemsonStage() {
            for(var animation in animations) {
                stage.addChild(animationObjects[animation]);
            }
        }
    }

    function setIdleAnimationState() {
        for(var animation in bandConfig.animations) {
            animationObjects[animation].animation.timeScale = 1;
            animationObjects[animation].animation.gotoAndPlay('Idle', 0.3, -1, 0);
            stage.addChild(animationObjects[animation]);
        }
    }

    function setMusicHandler() {
        document.querySelector('.timeline')
            .addEventListener('animalBand.audio.rhythmIndex', function(e) {
                audioConfig.matrix.result.map(function(instrument, index) {
                    var rhythmIndex = e.detail.rhythmIndex,
                        animationId = bandConfig.animationsMapping[instrument],
                        animationData = bandConfig.animations[animationId],
                        isInstrumentSet = audioConfig.matrix.entities[instrument][rhythmIndex],
                        isTom1Set = audioConfig.matrix.entities['tom1'][rhythmIndex],
                        isTom2Set = audioConfig.matrix.entities['tom2'][rhythmIndex],
                        animationType;

                    if(isInstrumentSet) {
                        if(animationId === 'lion') {
                            if(isTom1Set && isTom2Set) {
                                animationType = arrayHelpers.getRandomValue(
                                    animationData.types.tom1tom2
                                );
                            } else if (isTom1Set) {
                                animationType = arrayHelpers.getRandomValue(
                                    animationData.types.tom1
                                );
                            } else if (isTom2Set) {
                                animationType = arrayHelpers.getRandomValue(
                                    animationData.types.tom2
                                );
                            }
                        } else {
                            animationType = arrayHelpers.getRandomValue(
                                animationData.types
                            );
                        }
                        animationObjects[animationId].animation.timeScale = 2;
                        animationObjects[animationId].animation.gotoAndPlay(
                            animationType, -1, -1, 1
                        );
                    } else {
                        animationObjects[animationId].animation.timeScale = 2;
                        var animation = bandConfig.animations[instrument]
                        var rand = Math.floor((Math.random() * 100) + 1);
                        if(rand < 10) {
                            animationObjects[animationId].animation.gotoAndPlay(
                                'Idle_Blink', -1, -1, 1
                            );
                        }
                        else {
                            animationObjects[animationId].animation.gotoAndPlay(
                                'Idle', -1, -1, 1
                            );
                        }
                    }
                });
            });
    }
});
<|endoftext|>


<commit_before>'use strict';

var axesAttrs = require('../../plots/cartesian/layout_attributes');
var fontAttrs = require('../../plots/font_attributes');
var extendFlat = require('../../lib/extend').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;

module.exports = overrideAll({
// TODO: only right is supported currently
//     orient: {
//         valType: 'enumerated',
//         values: ['left', 'right', 'top', 'bottom'],
//         dflt: 'right',
//         description: [
//             'Determines which side are the labels on',
//             '(so left and right make vertical bars, etc.)'
//         ].join(' ')
//     },
    thicknessmode: {
        valType: 'enumerated',
        values: ['fraction', 'pixels'],
        dflt: 'pixels',
        description: [
            'Determines whether this color bar\'s thickness',
            '(i.e. the measure in the constant color direction)',
            'is set in units of plot *fraction* or in *pixels*.',
            'Use `thickness` to set the value.'
        ].join(' ')
    },
    thickness: {
        valType: 'number',
        min: 0,
        dflt: 30,
        description: [
            'Sets the thickness of the color bar',
            'This measure excludes the size of the padding, ticks and labels.'
        ].join(' ')
    },
    lenmode: {
        valType: 'enumerated',
        values: ['fraction', 'pixels'],
        dflt: 'fraction',
        description: [
            'Determines whether this color bar\'s length',
            '(i.e. the measure in the color variation direction)',
            'is set in units of plot *fraction* or in *pixels.',
            'Use `len` to set the value.'
        ].join(' ')
    },
    len: {
        valType: 'number',
        min: 0,
        dflt: 1,
        description: [
            'Sets the length of the color bar',
            'This measure excludes the padding of both ends.',
            'That is, the color bar length is this length minus the',
            'padding on both ends.'
        ].join(' ')
    },
    x: {
        valType: 'number',
        dflt: 1.02,
        min: -2,
        max: 3,
        description: [
            'Sets the x position of the color bar (in plot fraction).'
        ].join(' ')
    },
    xanchor: {
        valType: 'enumerated',
        values: ['left', 'center', 'right'],
        dflt: 'left',
        description: [
            'Sets this color bar\'s horizontal position anchor.',
            'This anchor binds the `x` position to the *left*, *center*',
            'or *right* of the color bar.'
        ].join(' ')
    },
    xpad: {
        valType: 'number',
        min: 0,
        dflt: 10,
        description: 'Sets the amount of padding (in px) along the x direction.'
    },
    y: {
        valType: 'number',
        dflt: 0.5,
        min: -2,
        max: 3,
        description: [
            'Sets the y position of the color bar (in plot fraction).'
        ].join(' ')
    },
    yanchor: {
        valType: 'enumerated',
        values: ['top', 'middle', 'bottom'],
        dflt: 'middle',
        description: [
            'Sets this color bar\'s vertical position anchor',
            'This anchor binds the `y` position to the *top*, *middle*',
            'or *bottom* of the color bar.'
        ].join(' ')
    },
    ypad: {
        valType: 'number',
        min: 0,
        dflt: 10,
        description: 'Sets the amount of padding (in px) along the y direction.'
    },
    // a possible line around the bar itself
    outlinecolor: axesAttrs.linecolor,
    outlinewidth: axesAttrs.linewidth,
    // Should outlinewidth have {dflt: 0} ?
    // another possible line outside the padding and tick labels
    bordercolor: axesAttrs.linecolor,
    borderwidth: {
        valType: 'number',
        min: 0,
        dflt: 0,
        description: [
            'Sets the width (in px) or the border enclosing this color bar.'
        ].join(' ')
    },
    bgcolor: {
        valType: 'color',
        dflt: 'rgba(0,0,0,0)',
        description: 'Sets the color of padded area.'
    },
    // tick and title properties named and function exactly as in axes
    tickmode: axesAttrs.tickmode,
    nticks: axesAttrs.nticks,
    tick0: axesAttrs.tick0,
    dtick: axesAttrs.dtick,
    tickvals: axesAttrs.tickvals,
    ticktext: axesAttrs.ticktext,
    ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
    ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {dflt: 'allow'}),
    ticklabelposition: {
        valType: 'enumerated',
        values: [
            'outside', 'inside',
            'outside top', 'inside top',
            'outside bottom', 'inside bottom'
        ],
        dflt: 'outside',
        description: [
            'Determines where tick labels are drawn.'
        ].join(' ')
    },
    ticklen: axesAttrs.ticklen,
    tickwidth: axesAttrs.tickwidth,
    tickcolor: axesAttrs.tickcolor,
    showticklabels: axesAttrs.showticklabels,
    tickfont: fontAttrs({
        description: 'Sets the color bar\'s tick label font'
    }),
    tickangle: axesAttrs.tickangle,
    tickformat: axesAttrs.tickformat,
    tickformatstops: axesAttrs.tickformatstops,
    tickprefix: axesAttrs.tickprefix,
    showtickprefix: axesAttrs.showtickprefix,
    ticksuffix: axesAttrs.ticksuffix,
    showticksuffix: axesAttrs.showticksuffix,
    separatethousands: axesAttrs.separatethousands,
    exponentformat: axesAttrs.exponentformat,
    minexponent: axesAttrs.minexponent,
    showexponent: axesAttrs.showexponent,
    title: {
        text: {
            valType: 'string',
            description: [
                'Sets the title of the color bar.',
                'Note that before the existence of `title.text`, the title\'s',
                'contents used to be defined as the `title` attribute itself.',
                'This behavior has been deprecated.'
            ].join(' ')
        },
        font: fontAttrs({
            description: [
                'Sets this color bar\'s title font.',
                'Note that the title\'s font used to be set',
                'by the now deprecated `titlefont` attribute.'
            ].join(' ')
        }),
        side: {
            valType: 'enumerated',
            values: ['right', 'top', 'bottom'],
            dflt: 'top',
            description: [
                'Determines the location of color bar\'s title',
                'with respect to the color bar.',
                'Note that the title\'s location used to be set',
                'by the now deprecated `titleside` attribute.'
            ].join(' ')
        }
    },

    _deprecated: {
        title: {
            valType: 'string',
            description: [
                'Deprecated in favor of color bar\'s `title.text`.',
                'Note that value of color bar\'s `title` is no longer a simple',
                '*string* but a set of sub-attributes.'
            ].join(' ')
        },
        titlefont: fontAttrs({
            description: 'Deprecated in favor of color bar\'s `title.font`.'
        }),
        titleside: {
            valType: 'enumerated',
            values: ['right', 'top', 'bottom'],
            dflt: 'top',
            description: 'Deprecated in favor of color bar\'s `title.side`.'
        }
    }
}, 'colorbars', 'from-root');
<commit_msg>remove colorbar dflt and update description<commit_after>'use strict';

var axesAttrs = require('../../plots/cartesian/layout_attributes');
var fontAttrs = require('../../plots/font_attributes');
var extendFlat = require('../../lib/extend').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;

module.exports = overrideAll({
// TODO: only right is supported currently
//     orient: {
//         valType: 'enumerated',
//         values: ['left', 'right', 'top', 'bottom'],
//         dflt: 'right',
//         description: [
//             'Determines which side are the labels on',
//             '(so left and right make vertical bars, etc.)'
//         ].join(' ')
//     },
    thicknessmode: {
        valType: 'enumerated',
        values: ['fraction', 'pixels'],
        dflt: 'pixels',
        description: [
            'Determines whether this color bar\'s thickness',
            '(i.e. the measure in the constant color direction)',
            'is set in units of plot *fraction* or in *pixels*.',
            'Use `thickness` to set the value.'
        ].join(' ')
    },
    thickness: {
        valType: 'number',
        min: 0,
        dflt: 30,
        description: [
            'Sets the thickness of the color bar',
            'This measure excludes the size of the padding, ticks and labels.'
        ].join(' ')
    },
    lenmode: {
        valType: 'enumerated',
        values: ['fraction', 'pixels'],
        dflt: 'fraction',
        description: [
            'Determines whether this color bar\'s length',
            '(i.e. the measure in the color variation direction)',
            'is set in units of plot *fraction* or in *pixels.',
            'Use `len` to set the value.'
        ].join(' ')
    },
    len: {
        valType: 'number',
        min: 0,
        dflt: 1,
        description: [
            'Sets the length of the color bar',
            'This measure excludes the padding of both ends.',
            'That is, the color bar length is this length minus the',
            'padding on both ends.'
        ].join(' ')
    },
    x: {
        valType: 'number',
        dflt: 1.02,
        min: -2,
        max: 3,
        description: [
            'Sets the x position of the color bar (in plot fraction).'
        ].join(' ')
    },
    xanchor: {
        valType: 'enumerated',
        values: ['left', 'center', 'right'],
        dflt: 'left',
        description: [
            'Sets this color bar\'s horizontal position anchor.',
            'This anchor binds the `x` position to the *left*, *center*',
            'or *right* of the color bar.'
        ].join(' ')
    },
    xpad: {
        valType: 'number',
        min: 0,
        dflt: 10,
        description: 'Sets the amount of padding (in px) along the x direction.'
    },
    y: {
        valType: 'number',
        dflt: 0.5,
        min: -2,
        max: 3,
        description: [
            'Sets the y position of the color bar (in plot fraction).'
        ].join(' ')
    },
    yanchor: {
        valType: 'enumerated',
        values: ['top', 'middle', 'bottom'],
        dflt: 'middle',
        description: [
            'Sets this color bar\'s vertical position anchor',
            'This anchor binds the `y` position to the *top*, *middle*',
            'or *bottom* of the color bar.'
        ].join(' ')
    },
    ypad: {
        valType: 'number',
        min: 0,
        dflt: 10,
        description: 'Sets the amount of padding (in px) along the y direction.'
    },
    // a possible line around the bar itself
    outlinecolor: axesAttrs.linecolor,
    outlinewidth: axesAttrs.linewidth,
    // Should outlinewidth have {dflt: 0} ?
    // another possible line outside the padding and tick labels
    bordercolor: axesAttrs.linecolor,
    borderwidth: {
        valType: 'number',
        min: 0,
        dflt: 0,
        description: [
            'Sets the width (in px) or the border enclosing this color bar.'
        ].join(' ')
    },
    bgcolor: {
        valType: 'color',
        dflt: 'rgba(0,0,0,0)',
        description: 'Sets the color of padded area.'
    },
    // tick and title properties named and function exactly as in axes
    tickmode: axesAttrs.tickmode,
    nticks: axesAttrs.nticks,
    tick0: axesAttrs.tick0,
    dtick: axesAttrs.dtick,
    tickvals: axesAttrs.tickvals,
    ticktext: axesAttrs.ticktext,
    ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
    ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {
        description: [
            'Determines how we handle tick labels that would overflow either the graph div or the domain of the axis.',
            'The default value for inside tick labels is *hide past domain*.',
            'In other cases the default is *hide past div*.'
        ].join(' ')
    }),
    ticklabelposition: {
        valType: 'enumerated',
        values: [
            'outside', 'inside',
            'outside top', 'inside top',
            'outside bottom', 'inside bottom'
        ],
        dflt: 'outside',
        description: [
            'Determines where tick labels are drawn.'
        ].join(' ')
    },
    ticklen: axesAttrs.ticklen,
    tickwidth: axesAttrs.tickwidth,
    tickcolor: axesAttrs.tickcolor,
    showticklabels: axesAttrs.showticklabels,
    tickfont: fontAttrs({
        description: 'Sets the color bar\'s tick label font'
    }),
    tickangle: axesAttrs.tickangle,
    tickformat: axesAttrs.tickformat,
    tickformatstops: axesAttrs.tickformatstops,
    tickprefix: axesAttrs.tickprefix,
    showtickprefix: axesAttrs.showtickprefix,
    ticksuffix: axesAttrs.ticksuffix,
    showticksuffix: axesAttrs.showticksuffix,
    separatethousands: axesAttrs.separatethousands,
    exponentformat: axesAttrs.exponentformat,
    minexponent: axesAttrs.minexponent,
    showexponent: axesAttrs.showexponent,
    title: {
        text: {
            valType: 'string',
            description: [
                'Sets the title of the color bar.',
                'Note that before the existence of `title.text`, the title\'s',
                'contents used to be defined as the `title` attribute itself.',
                'This behavior has been deprecated.'
            ].join(' ')
        },
        font: fontAttrs({
            description: [
                'Sets this color bar\'s title font.',
                'Note that the title\'s font used to be set',
                'by the now deprecated `titlefont` attribute.'
            ].join(' ')
        }),
        side: {
            valType: 'enumerated',
            values: ['right', 'top', 'bottom'],
            dflt: 'top',
            description: [
                'Determines the location of color bar\'s title',
                'with respect to the color bar.',
                'Note that the title\'s location used to be set',
                'by the now deprecated `titleside` attribute.'
            ].join(' ')
        }
    },

    _deprecated: {
        title: {
            valType: 'string',
            description: [
                'Deprecated in favor of color bar\'s `title.text`.',
                'Note that value of color bar\'s `title` is no longer a simple',
                '*string* but a set of sub-attributes.'
            ].join(' ')
        },
        titlefont: fontAttrs({
            description: 'Deprecated in favor of color bar\'s `title.font`.'
        }),
        titleside: {
            valType: 'enumerated',
            values: ['right', 'top', 'bottom'],
            dflt: 'top',
            description: 'Deprecated in favor of color bar\'s `title.side`.'
        }
    }
}, 'colorbars', 'from-root');
<|endoftext|>


<commit_before>import React from 'react';
import { connect } from 'react-redux';
import { PERMISSION_TOPIC_READ, PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN,
         PERMISSION_ADMIN, PERMISSION_MEDIA_EDIT, PERMISSION_STORY_EDIT, PERMISSION_LOGGED_IN } from '../../lib/auth';

/**
 * Use this to restrict who is allowed to see what.
 **/
const Permissioned = (props) => {
  const { children, onlyTopic, onlyRole, userTopicPermission, user } = props;
  let userRolePermissions = [];
  if (('profile' in user) && ('auth_roles' in user.profile)) {
    // need to check this carefully because if they aren't logged in these sub-objects won't exist
    userRolePermissions = user.profile.auth_roles;
  }
  let allowed = false;
  if (onlyTopic) {
    // check topic-level permissions
    if (![PERMISSION_TOPIC_READ, PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN].includes(onlyTopic)) {
      const error = { message: `Invalid topic permission (${onlyTopic})` };
      throw error;
    }
    switch (onlyTopic) {
      case PERMISSION_TOPIC_READ:
        allowed = [PERMISSION_TOPIC_READ, PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN].includes(userTopicPermission);
        break;
      case PERMISSION_TOPIC_WRITE:
        allowed = [PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN].includes(userTopicPermission);
        break;
      case PERMISSION_TOPIC_ADMIN:
        allowed = (PERMISSION_TOPIC_ADMIN === userTopicPermission);
        break;
      default:
        allowed = false;
    }
  } else if (onlyRole) {
    // check role-level permissions
    if (![PERMISSION_ADMIN, PERMISSION_MEDIA_EDIT, PERMISSION_STORY_EDIT, PERMISSION_LOGGED_IN].includes(onlyRole)) {
      const error = { message: `Invalid permission (${onlyRole})` };
      throw error;
    }
    if (userRolePermissions.includes(PERMISSION_ADMIN)) {
      allowed = true; // because admins are allowed to do anything
    } else {
      switch (onlyRole) {
        case PERMISSION_LOGGED_IN:
          allowed = user.isLoggedIn;
          break;
        case PERMISSION_ADMIN:
          allowed = userRolePermissions.includes(PERMISSION_ADMIN);
          break;
        case PERMISSION_MEDIA_EDIT:
          allowed = userRolePermissions.includes(PERMISSION_MEDIA_EDIT);
          break;
        case PERMISSION_STORY_EDIT:
          allowed = userRolePermissions.includes(PERMISSION_STORY_EDIT);
          break;
        default:
          allowed = false;
      }
    }
  }
  let content = null;
  if (allowed) {
    content = children;
  }
  let cssClasses = 'permissioned';
  if (onlyTopic) cssClasses += ` topic-${onlyTopic}`;
  if (onlyRole) cssClasses += ` role-${onlyRole}`;
  return (

      {content}

  );
};

Permissioned.propTypes = {
  // from parent
  children: React.PropTypes.node.isRequired,
  onlyTopic: React.PropTypes.string,
  onlyRole: React.PropTypes.string,
  // from state
  userTopicPermission: React.PropTypes.string,
  user: React.PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  userTopicPermission: state.topics.selected.info.user_permission,
  user: state.user,
});

export default
  connect(mapStateToProps)(
    Permissioned
  );
<commit_msg>don't require children<commit_after>import React from 'react';
import { connect } from 'react-redux';
import { PERMISSION_TOPIC_READ, PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN,
         PERMISSION_ADMIN, PERMISSION_MEDIA_EDIT, PERMISSION_STORY_EDIT, PERMISSION_LOGGED_IN } from '../../lib/auth';

/**
 * Use this to restrict who is allowed to see what.
 **/
const Permissioned = (props) => {
  const { children, onlyTopic, onlyRole, userTopicPermission, user } = props;
  let userRolePermissions = [];
  if (('profile' in user) && ('auth_roles' in user.profile)) {
    // need to check this carefully because if they aren't logged in these sub-objects won't exist
    userRolePermissions = user.profile.auth_roles;
  }
  let allowed = false;
  if (onlyTopic) {
    // check topic-level permissions
    if (![PERMISSION_TOPIC_READ, PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN].includes(onlyTopic)) {
      const error = { message: `Invalid topic permission (${onlyTopic})` };
      throw error;
    }
    switch (onlyTopic) {
      case PERMISSION_TOPIC_READ:
        allowed = [PERMISSION_TOPIC_READ, PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN].includes(userTopicPermission);
        break;
      case PERMISSION_TOPIC_WRITE:
        allowed = [PERMISSION_TOPIC_WRITE, PERMISSION_TOPIC_ADMIN].includes(userTopicPermission);
        break;
      case PERMISSION_TOPIC_ADMIN:
        allowed = (PERMISSION_TOPIC_ADMIN === userTopicPermission);
        break;
      default:
        allowed = false;
    }
  } else if (onlyRole) {
    // check role-level permissions
    if (![PERMISSION_ADMIN, PERMISSION_MEDIA_EDIT, PERMISSION_STORY_EDIT, PERMISSION_LOGGED_IN].includes(onlyRole)) {
      const error = { message: `Invalid permission (${onlyRole})` };
      throw error;
    }
    if (userRolePermissions.includes(PERMISSION_ADMIN)) {
      allowed = true; // because admins are allowed to do anything
    } else {
      switch (onlyRole) {
        case PERMISSION_LOGGED_IN:
          allowed = user.isLoggedIn;
          break;
        case PERMISSION_ADMIN:
          allowed = userRolePermissions.includes(PERMISSION_ADMIN);
          break;
        case PERMISSION_MEDIA_EDIT:
          allowed = userRolePermissions.includes(PERMISSION_MEDIA_EDIT);
          break;
        case PERMISSION_STORY_EDIT:
          allowed = userRolePermissions.includes(PERMISSION_STORY_EDIT);
          break;
        default:
          allowed = false;
      }
    }
  }
  let content = null;
  if (allowed) {
    content = children;
  }
  let cssClasses = 'permissioned';
  if (onlyTopic) cssClasses += ` topic-${onlyTopic}`;
  if (onlyRole) cssClasses += ` role-${onlyRole}`;
  return (

      {content}

  );
};

Permissioned.propTypes = {
  // from parent
  children: React.PropTypes.node, // not required, because the content passed in could be null (if some property isn't filled in on an object)
  onlyTopic: React.PropTypes.string,
  onlyRole: React.PropTypes.string,
  // from state
  userTopicPermission: React.PropTypes.string,
  user: React.PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  userTopicPermission: state.topics.selected.info.user_permission,
  user: state.user,
});

export default
  connect(mapStateToProps)(
    Permissioned
  );
<|endoftext|>


<commit_before>import Vue from '../../utils/vue'
import identity from '../../utils/identity'
import { from as arrayFrom, isArray, concat } from '../../utils/array'
import { getComponentConfig } from '../../utils/config'
import { isFile, isFunction, isUndefinedOrNull } from '../../utils/inspect'
import { File } from '../../utils/safe-types'
import { toString } from '../../utils/string'
import { warn } from '../../utils/warn'
import formCustomMixin from '../../mixins/form-custom'
import formMixin from '../../mixins/form'
import formStateMixin from '../../mixins/form-state'
import idMixin from '../../mixins/id'
import normalizeSlotMixin from '../../mixins/normalize-slot'

const NAME = 'BFormFile'

const VALUE_EMPTY_DEPRECATED_MSG =
  'Setting "value"/"v-model" to an empty string for reset is deprecated. Set to "null" instead.'

// @vue/component
export const BFormFile = /*#__PURE__*/ Vue.extend({
  name: NAME,
  mixins: [idMixin, formMixin, formStateMixin, formCustomMixin, normalizeSlotMixin],
  inheritAttrs: false,
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    size: {
      type: String,
      default: () => getComponentConfig('BFormControl', 'size')
    },
    value: {
      type: [File, Array],
      default: null,
      validator: val => {
        /* istanbul ignore next */
        if (val === '') {
          warn(VALUE_EMPTY_DEPRECATED_MSG, NAME)
          return true
        }
        return (
          isUndefinedOrNull(val) ||
          isFile(val) ||
          (isArray(val) && (val.length === 0 || val.every(isFile)))
        )
      }
    },
    accept: {
      type: String,
      default: ''
    },
    // Instruct input to capture from camera
    capture: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: () => getComponentConfig(NAME, 'placeholder')
    },
    browseText: {
      type: String,
      default: () => getComponentConfig(NAME, 'browseText')
    },
    dropPlaceholder: {
      type: String,
      default: () => getComponentConfig(NAME, 'dropPlaceholder')
    },
    multiple: {
      type: Boolean,
      default: false
    },
    directory: {
      type: Boolean,
      default: false
    },
    noTraverse: {
      type: Boolean,
      default: false
    },
    noDrop: {
      type: Boolean,
      default: false
    },
    fileNameFormatter: {
      type: Function,
      default: null
    }
  },
  data() {
    return {
      selectedFile: null,
      dragging: false,
      hasFocus: false
    }
  },
  computed: {
    selectLabel() {
      // Draging active
      if (this.dragging && this.dropPlaceholder) {
        return this.dropPlaceholder
      }

      // No file chosen
      if (!this.selectedFile || this.selectedFile.length === 0) {
        return this.placeholder
      }

      // Convert selectedFile to an array (if not already one)
      const files = concat(this.selectedFile).filter(identity)

      if (this.hasNormalizedSlot('file-name')) {
        // There is a slot for formatting the files/names
        return [
          this.normalizeSlot('file-name', {
            files: files,
            names: files.map(f => f.name)
          })
        ]
      } else {
        // Use the user supplied formatter, or the built in one.
        return isFunction(this.fileNameFormatter)
          ? toString(this.fileNameFormatter(files))
          : files.map(file => file.name).join(', ')
      }
    }
  },
  watch: {
    selectedFile(newVal, oldVal) {
      // The following test is needed when the file input is "reset" or the
      // exact same file(s) are selected to prevent an infinite loop.
      // When in `multiple` mode we need to check for two empty arrays or
      // two arrays with identical files
      if (
        newVal === oldVal ||
        (isArray(newVal) &&
          isArray(oldVal) &&
          newVal.length === oldVal.length &&
          newVal.every((v, i) => v === oldVal[i]))
      ) {
        return
      }
      if (!newVal && this.multiple) {
        this.$emit('input', [])
      } else {
        this.$emit('input', newVal)
      }
    },
    value(newVal) {
      if (!newVal || (isArray(newVal) && newVal.length === 0)) {
        this.reset()
      }
    }
  },
  methods: {
    focusHandler(evt) {
      // Bootstrap v4 doesn't have focus styling for custom file input
      // Firefox has a '[type=file]:focus ~ sibling' selector issue,
      // so we add a 'focus' class to get around these bugs
      if (this.plain || evt.type === 'focusout') {
        this.hasFocus = false
      } else {
        // Add focus styling for custom file input
        this.hasFocus = true
      }
    },
    reset() {
      try {
        // Wrapped in try in case IE 11 craps out
        this.$refs.input.value = ''
      } catch (e) {}
      // IE 11 doesn't support setting `input.value` to '' or null
      // So we use this little extra hack to reset the value, just in case.
      // This also appears to work on modern browsers as well.
      this.$refs.input.type = ''
      this.$refs.input.type = 'file'
      this.selectedFile = this.multiple ? [] : null
    },
    onFileChange(evt) {
      // Always emit original event
      this.$emit('change', evt)
      // Check if special `items` prop is available on event (drop mode)
      // Can be disabled by setting no-traverse
      const items = evt.dataTransfer && evt.dataTransfer.items
      /* istanbul ignore next: not supported in JSDOM */
      if (items && !this.noTraverse) {
        const queue = []
        for (let i = 0; i < items.length; i++) {
          const item = items[i].webkitGetAsEntry()
          if (item) {
            queue.push(this.traverseFileTree(item))
          }
        }
        Promise.all(queue).then(filesArr => {
          this.setFiles(arrayFrom(filesArr))
        })
        return
      }
      // Normal handling
      this.setFiles(evt.target.files || evt.dataTransfer.files)
    },
    setFiles(files = []) {
      if (!files) {
        /* istanbul ignore next: this will probably not happen */
        this.selectedFile = null
      } else if (this.multiple) {
        // Convert files to array
        const filesArray = []
        for (let i = 0; i < files.length; i++) {
          filesArray.push(files[i])
        }
        // Return file(s) as array
        this.selectedFile = filesArray
      } else {
        // Return single file object
        this.selectedFile = files[0] || null
      }
    },
    onReset() {
      // Triggered when the parent form (if any) is reset
      this.selectedFile = this.multiple ? [] : null
    },
    onDragover(evt) /* istanbul ignore next: difficult to test in JSDOM */ {
      evt.preventDefault()
      evt.stopPropagation()
      if (this.noDrop || !this.custom) {
        return
      }
      this.dragging = true
      evt.dataTransfer.dropEffect = 'copy'
    },
    onDragleave(evt) /* istanbul ignore next: difficult to test in JSDOM */ {
      evt.preventDefault()
      evt.stopPropagation()
      this.dragging = false
    },
    onDrop(evt) /* istanbul ignore next: difficult to test in JSDOM */ {
      evt.preventDefault()
      evt.stopPropagation()
      if (this.noDrop) {
        return
      }
      this.dragging = false
      if (evt.dataTransfer.files && evt.dataTransfer.files.length > 0) {
        this.onFileChange(evt)
      }
    },
    traverseFileTree(item, path) /* istanbul ignore next: not supported in JSDOM */ {
      // Based on http://stackoverflow.com/questions/3590058
      return new Promise(resolve => {
        path = path || ''
        if (item.isFile) {
          // Get file
          item.file(file => {
            file.$path = path // Inject $path to file obj
            resolve(file)
          })
        } else if (item.isDirectory) {
          // Get folder contents
          item.createReader().readEntries(entries => {
            const queue = []
            for (let i = 0; i < entries.length; i++) {
              queue.push(this.traverseFileTree(entries[i], path + item.name + '/'))
            }
            Promise.all(queue).then(filesArr => {
              resolve(arrayFrom(filesArr))
            })
          })
        }
      })
    }
  },
  render(h) {
    // Form Input
    const input = h('input', {
      ref: 'input',
      class: [
        {
          'form-control-file': this.plain,
          'custom-file-input': this.custom,
          focus: this.custom && this.hasFocus
        },
        this.stateClass
      ],
      attrs: {
        ...this.$attrs,
        type: 'file',
        id: this.safeId(),
        name: this.name,
        disabled: this.disabled,
        required: this.required,
        form: this.form || null,
        capture: this.capture || null,
        accept: this.accept || null,
        multiple: this.multiple,
        webkitdirectory: this.directory,
        'aria-required': this.required ? 'true' : null
      },
      on: {
        change: this.onFileChange,
        focusin: this.focusHandler,
        focusout: this.focusHandler,
        reset: this.onReset
      }
    })

    if (this.plain) {
      return input
    }

    // Overlay Labels
    const label = h(
      'label',
      {
        staticClass: 'custom-file-label',
        class: [this.dragging ? 'dragging' : null],
        attrs: {
          for: this.safeId(),
          'data-browse': this.browseText || null
        }
      },
      this.selectLabel
    )

    // Return rendered custom file input
    return h(
      'div',
      {
        staticClass: 'custom-file b-form-file',
        class: [
          this.stateClass,
          {
            [`b-custom-control-${this.size}`]: this.size
          }
        ],
        attrs: { id: this.safeId('_BV_file_outer_') },
        on: {
          dragover: this.onDragover,
          dragleave: this.onDragleave,
          drop: this.onDrop
        }
      },
      [input, label]
    )
  }
})
<commit_msg>fix(b-form-file): fix value prop validation when using directory mode (fixes #4912) (#4913)<commit_after>import Vue from '../../utils/vue'
import identity from '../../utils/identity'
import { from as arrayFrom, isArray, concat } from '../../utils/array'
import { getComponentConfig } from '../../utils/config'
import { isFile, isFunction, isUndefinedOrNull } from '../../utils/inspect'
import { File } from '../../utils/safe-types'
import { toString } from '../../utils/string'
import { warn } from '../../utils/warn'
import formCustomMixin from '../../mixins/form-custom'
import formMixin from '../../mixins/form'
import formStateMixin from '../../mixins/form-state'
import idMixin from '../../mixins/id'
import normalizeSlotMixin from '../../mixins/normalize-slot'

// --- Constants ---

const NAME = 'BFormFile'

const VALUE_EMPTY_DEPRECATED_MSG =
  'Setting "value"/"v-model" to an empty string for reset is deprecated. Set to "null" instead.'

// --- Helper methods ---

const isValidValue = value => isFile(value) || (isArray(value) && value.every(v => isValidValue(v)))

// @vue/component
export const BFormFile = /*#__PURE__*/ Vue.extend({
  name: NAME,
  mixins: [idMixin, formMixin, formStateMixin, formCustomMixin, normalizeSlotMixin],
  inheritAttrs: false,
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    size: {
      type: String,
      default: () => getComponentConfig('BFormControl', 'size')
    },
    value: {
      type: [File, Array],
      default: null,
      validator: value => {
        /* istanbul ignore next */
        if (value === '') {
          warn(VALUE_EMPTY_DEPRECATED_MSG, NAME)
          return true
        }
        return isUndefinedOrNull(value) || isValidValue(value)
      }
    },
    accept: {
      type: String,
      default: ''
    },
    // Instruct input to capture from camera
    capture: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: () => getComponentConfig(NAME, 'placeholder')
    },
    browseText: {
      type: String,
      default: () => getComponentConfig(NAME, 'browseText')
    },
    dropPlaceholder: {
      type: String,
      default: () => getComponentConfig(NAME, 'dropPlaceholder')
    },
    multiple: {
      type: Boolean,
      default: false
    },
    directory: {
      type: Boolean,
      default: false
    },
    noTraverse: {
      type: Boolean,
      default: false
    },
    noDrop: {
      type: Boolean,
      default: false
    },
    fileNameFormatter: {
      type: Function,
      default: null
    }
  },
  data() {
    return {
      selectedFile: null,
      dragging: false,
      hasFocus: false
    }
  },
  computed: {
    selectLabel() {
      // Draging active
      if (this.dragging && this.dropPlaceholder) {
        return this.dropPlaceholder
      }

      // No file chosen
      if (!this.selectedFile || this.selectedFile.length === 0) {
        return this.placeholder
      }

      // Convert selectedFile to an array (if not already one)
      const files = concat(this.selectedFile).filter(identity)

      if (this.hasNormalizedSlot('file-name')) {
        // There is a slot for formatting the files/names
        return [
          this.normalizeSlot('file-name', {
            files: files,
            names: files.map(f => f.name)
          })
        ]
      } else {
        // Use the user supplied formatter, or the built in one.
        return isFunction(this.fileNameFormatter)
          ? toString(this.fileNameFormatter(files))
          : files.map(file => file.name).join(', ')
      }
    }
  },
  watch: {
    selectedFile(newVal, oldVal) {
      // The following test is needed when the file input is "reset" or the
      // exact same file(s) are selected to prevent an infinite loop.
      // When in `multiple` mode we need to check for two empty arrays or
      // two arrays with identical files
      if (
        newVal === oldVal ||
        (isArray(newVal) &&
          isArray(oldVal) &&
          newVal.length === oldVal.length &&
          newVal.every((v, i) => v === oldVal[i]))
      ) {
        return
      }
      if (!newVal && this.multiple) {
        this.$emit('input', [])
      } else {
        this.$emit('input', newVal)
      }
    },
    value(newVal) {
      if (!newVal || (isArray(newVal) && newVal.length === 0)) {
        this.reset()
      }
    }
  },
  methods: {
    focusHandler(evt) {
      // Bootstrap v4 doesn't have focus styling for custom file input
      // Firefox has a '[type=file]:focus ~ sibling' selector issue,
      // so we add a 'focus' class to get around these bugs
      if (this.plain || evt.type === 'focusout') {
        this.hasFocus = false
      } else {
        // Add focus styling for custom file input
        this.hasFocus = true
      }
    },
    reset() {
      try {
        // Wrapped in try in case IE 11 craps out
        this.$refs.input.value = ''
      } catch (e) {}
      // IE 11 doesn't support setting `input.value` to '' or null
      // So we use this little extra hack to reset the value, just in case.
      // This also appears to work on modern browsers as well.
      this.$refs.input.type = ''
      this.$refs.input.type = 'file'
      this.selectedFile = this.multiple ? [] : null
    },
    onFileChange(evt) {
      // Always emit original event
      this.$emit('change', evt)
      // Check if special `items` prop is available on event (drop mode)
      // Can be disabled by setting no-traverse
      const items = evt.dataTransfer && evt.dataTransfer.items
      /* istanbul ignore next: not supported in JSDOM */
      if (items && !this.noTraverse) {
        const queue = []
        for (let i = 0; i < items.length; i++) {
          const item = items[i].webkitGetAsEntry()
          if (item) {
            queue.push(this.traverseFileTree(item))
          }
        }
        Promise.all(queue).then(filesArr => {
          this.setFiles(arrayFrom(filesArr))
        })
        return
      }
      // Normal handling
      this.setFiles(evt.target.files || evt.dataTransfer.files)
    },
    setFiles(files = []) {
      if (!files) {
        /* istanbul ignore next: this will probably not happen */
        this.selectedFile = null
      } else if (this.multiple) {
        // Convert files to array
        const filesArray = []
        for (let i = 0; i < files.length; i++) {
          filesArray.push(files[i])
        }
        // Return file(s) as array
        this.selectedFile = filesArray
      } else {
        // Return single file object
        this.selectedFile = files[0] || null
      }
    },
    onReset() {
      // Triggered when the parent form (if any) is reset
      this.selectedFile = this.multiple ? [] : null
    },
    onDragover(evt) /* istanbul ignore next: difficult to test in JSDOM */ {
      evt.preventDefault()
      evt.stopPropagation()
      if (this.noDrop || !this.custom) {
        return
      }
      this.dragging = true
      evt.dataTransfer.dropEffect = 'copy'
    },
    onDragleave(evt) /* istanbul ignore next: difficult to test in JSDOM */ {
      evt.preventDefault()
      evt.stopPropagation()
      this.dragging = false
    },
    onDrop(evt) /* istanbul ignore next: difficult to test in JSDOM */ {
      evt.preventDefault()
      evt.stopPropagation()
      if (this.noDrop) {
        return
      }
      this.dragging = false
      if (evt.dataTransfer.files && evt.dataTransfer.files.length > 0) {
        this.onFileChange(evt)
      }
    },
    traverseFileTree(item, path) /* istanbul ignore next: not supported in JSDOM */ {
      // Based on http://stackoverflow.com/questions/3590058
      return new Promise(resolve => {
        path = path || ''
        if (item.isFile) {
          // Get file
          item.file(file => {
            file.$path = path // Inject $path to file obj
            resolve(file)
          })
        } else if (item.isDirectory) {
          // Get folder contents
          item.createReader().readEntries(entries => {
            const queue = []
            for (let i = 0; i < entries.length; i++) {
              queue.push(this.traverseFileTree(entries[i], path + item.name + '/'))
            }
            Promise.all(queue).then(filesArr => {
              resolve(arrayFrom(filesArr))
            })
          })
        }
      })
    }
  },
  render(h) {
    // Form Input
    const input = h('input', {
      ref: 'input',
      class: [
        {
          'form-control-file': this.plain,
          'custom-file-input': this.custom,
          focus: this.custom && this.hasFocus
        },
        this.stateClass
      ],
      attrs: {
        ...this.$attrs,
        type: 'file',
        id: this.safeId(),
        name: this.name,
        disabled: this.disabled,
        required: this.required,
        form: this.form || null,
        capture: this.capture || null,
        accept: this.accept || null,
        multiple: this.multiple,
        webkitdirectory: this.directory,
        'aria-required': this.required ? 'true' : null
      },
      on: {
        change: this.onFileChange,
        focusin: this.focusHandler,
        focusout: this.focusHandler,
        reset: this.onReset
      }
    })

    if (this.plain) {
      return input
    }

    // Overlay Labels
    const label = h(
      'label',
      {
        staticClass: 'custom-file-label',
        class: [this.dragging ? 'dragging' : null],
        attrs: {
          for: this.safeId(),
          'data-browse': this.browseText || null
        }
      },
      this.selectLabel
    )

    // Return rendered custom file input
    return h(
      'div',
      {
        staticClass: 'custom-file b-form-file',
        class: [
          this.stateClass,
          {
            [`b-custom-control-${this.size}`]: this.size
          }
        ],
        attrs: { id: this.safeId('_BV_file_outer_') },
        on: {
          dragover: this.onDragover,
          dragleave: this.onDragleave,
          drop: this.onDrop
        }
      },
      [input, label]
    )
  }
})
<|endoftext|>


<commit_before>/*!
GPII Process Reporter processes bridge -- gpii.processes.

Copyright 2016-2017 Inclusive Design Research Centre, OCAD University

Licensed under the New BSD license. You may not use this file except in
compliance with this License.

You may obtain a copy of the License at
https://github.com/gpii/universal/LICENSE.txt
*/

/*global require */

"use strict";

var path = require("path"),
    // This conditional require is to run the electron version of edge.js
    // when this code runs on electron (gpii-app).
    edge = process.versions.electron ? require("electron-edge-js") : require("edge-js"),
    stringArgv = require("string-argv"),
    fluid = require("gpii-universal");

var gpii = fluid.registerNamespace("gpii");

var dotNetProcesses = edge.func({
    source: path.join(__dirname, "dotNetProcesses.csx"),
    references: ["System.Management.dll"]
});

fluid.defaults("gpii.processes.windows", {
    gradeNames: ["gpii.processes"],
    invokers: {
        getProcessList: {
            funcName: "gpii.processes.windows.getProcessList",
            args: ["{arguments}.0"]
                   // process name or id, optional.
        },
        compareProcessNames: {
            funcName: "gpii.processes.windows.compareProcessNames",
            args: ["{arguments}.0", "{arguments}.1"]
                    // process name A,  process name B
        }
    }
});

/**
 * Return a list of processes -- a snapshot of the current processes.  If the
 * process name or process id is passed, then the return value will be limited
 * to only processes with that name or the process with that pid.
 *
 * @param {String} or {Number} Optional.  Specify a process to find via a name
 *                                        (string), or a process id (number).
 */
gpii.processes.windows.getProcessList = function (processIdentifier) {
    var procInfos = dotNetProcesses(processIdentifier, true);

    // Loop to convert the command line to an argv[].
    fluid.each(procInfos, function (aProcInfo) {
        aProcInfo.argv = stringArgv(aProcInfo.commandLine);
        delete aProcInfo.commandLine;

        // In some cases the first argument is just the command, e.g., "Notepad".
        // In others, it is the full path and may include the ".exe"
        // extension.  Normalize it to always be the full path.
        aProcInfo.argv[0] = aProcInfo.fullPath;
    });
    return procInfos;
};

/**
 * Compares the names of two processes, returning a boolean indicating whether or not they are equal, ignoring case.
 *
 * @param processA {String} Name of a process.
 * @param processB {String} Name of another process.
 */
gpii.processes.windows.compareProcessNames = function (processA, processB) {
    return processA.toLowerCase() === processB.toLowerCase();
};
<commit_msg>GPII-2578: Moved case-insensitive process match into universal<commit_after>/*!
GPII Process Reporter processes bridge -- gpii.processes.

Copyright 2016-2017 Inclusive Design Research Centre, OCAD University

Licensed under the New BSD license. You may not use this file except in
compliance with this License.

You may obtain a copy of the License at
https://github.com/gpii/universal/LICENSE.txt
*/

/*global require */

"use strict";

var path = require("path"),
    // This conditional require is to run the electron version of edge.js
    // when this code runs on electron (gpii-app).
    edge = process.versions.electron ? require("electron-edge-js") : require("edge-js"),
    stringArgv = require("string-argv"),
    fluid = require("gpii-universal");

var gpii = fluid.registerNamespace("gpii");

var dotNetProcesses = edge.func({
    source: path.join(__dirname, "dotNetProcesses.csx"),
    references: ["System.Management.dll"]
});

fluid.defaults("gpii.processes.windows", {
    gradeNames: ["gpii.processes"],
    invokers: {
        getProcessList: {
            funcName: "gpii.processes.windows.getProcessList",
            args: ["{arguments}.0"]
                   // process name or id, optional.
        }
    },
    ignoreCase: true
});

/**
 * Return a list of processes -- a snapshot of the current processes.  If the
 * process name or process id is passed, then the return value will be limited
 * to only processes with that name or the process with that pid.
 *
 * @param {String} or {Number} Optional.  Specify a process to find via a name
 *                                        (string), or a process id (number).
 */
gpii.processes.windows.getProcessList = function (processIdentifier) {
    var procInfos = dotNetProcesses(processIdentifier, true);

    // Loop to convert the command line to an argv[].
    fluid.each(procInfos, function (aProcInfo) {
        aProcInfo.argv = stringArgv(aProcInfo.commandLine);
        delete aProcInfo.commandLine;

        // In some cases the first argument is just the command, e.g., "Notepad".
        // In others, it is the full path and may include the ".exe"
        // extension.  Normalize it to always be the full path.
        aProcInfo.argv[0] = aProcInfo.fullPath;
    });
    return procInfos;
};
<|endoftext|>


<commit_before>import React from 'react';
import { Box, NumericInput } from '../../';

const DurationInput = ({ value, onChange, onKeyDown }) => {
  const handleHoursChanged = (_, hours) => {
    onChange &&
      onChange({
        ...value,
        hours,
      });
  };

  const handleMinutesChange = (_, minutes) => {
    onChange &&
      onChange({
        ...value,
        minutes,
      });
  };

  return (
    <Box display="flex" alignItems="center">
      <NumericInput
        placeholder="00"
        min={0}
        value={value?.hours || ''}
        onChange={handleHoursChanged}
        onKeyDown={onKeyDown}
        size="small"
        flexGrow={1}
      />
      <Box element="span" marginHorizontal={2}>
        :
      </Box>
      <NumericInput
        placeholder="00"
        min={0}
        value={value?.minutes || ''}
        onChange={handleMinutesChange}
        onKeyDown={onKeyDown}
        size="small"
        flexGrow={1}
      />
    </Box>
  );
};

export default DurationInput;
<commit_msg>:sparkles: increment and decrement the hours when reaching the limit for minutes<commit_after>import React from 'react';
import { Box, NumericInput } from '../../';

const DurationInput = ({ value, onChange, onKeyDown }) => {
  const handleHoursChanged = (_, hours) => {
    onChange &&
      onChange({
        ...value,
        hours,
      });
  };

  const handleMinutesChange = (_, minutes) => {
    if (!onChange) {
      return;
    }

    if (minutes >= 60) {
      onChange({
        hours: (value?.hours || 0) + 1,
        minutes: 0,
      });
      return;
    }

    if (minutes < 0) {
      onChange({
        hours: (value?.hours || 1) - 1,
        minutes: 59,
      });
      return;
    }

    onChange({
      ...value,
      minutes,
    });
  };

  return (
    <Box display="flex" alignItems="center">
      <NumericInput
        placeholder="00"
        min={0}
        value={value?.hours ?? ''}
        onChange={handleHoursChanged}
        onKeyDown={onKeyDown}
        size="small"
        flexGrow={1}
      />
      <Box element="span" marginHorizontal={2}>
        :
      </Box>
      <NumericInput
        placeholder="00"
        {...(!value?.hours ? { min: 0 } : {})}
        value={value?.minutes ?? ''}
        onChange={handleMinutesChange}
        onKeyDown={onKeyDown}
        size="small"
        flexGrow={1}
      />
    </Box>
  );
};

export default DurationInput;
<|endoftext|>