<commit_before>/* eslint-disable no-return-assign */
/* @flow */
import * as Immutable from "immutable";
import * as React from "react";
import * as selectors from "../selectors";
import type { ContentRef } from "../state/refs";
import { DragDropContext as dragDropContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import { connect } from "react-redux";
import {
  List as ImmutableList,
  Map as ImmutableMap,
  Set as ImmutableSet,
  isImmutable
} from "immutable";

import { HijackScroll } from "./hijack-scroll";

import MathJax from "@nteract/mathjax";

import MarkdownPreviewer from "./markdown-preview";
import Toolbar from "./toolbar";

import { Display, RichestMime } from "@nteract/display-area";

import Editor from "./editor";

import { displayOrder, transforms } from "@nteract/transforms";

import { Input, Prompt, Source, Pagers, Outputs, Cell } from "./presentational";

import DraggableCell from "./draggable-cell";
import CellCreator from "./cell-creator";
import StatusBar from "./status-bar";

import * as actions from "../actions";

// NOTE: PropTypes are required for the sake of contextTypes
const PropTypes = require("prop-types");

const themes = require("../themes");

type AnyCellProps = {
  id: string,
  contentRef: ContentRef,
  cellType: "markdown" | "code" | "raw",
  theme: string,
  source: string,
  executionCount: *,
  outputs: ImmutableList<*>,
  pager: ImmutableList<*>,
  cellStatus: string,
  cellFocused: boolean, // not the ID of which is focused
  editorFocused: boolean,
  sourceHidden: boolean,
  outputHidden: boolean,
  outputExpanded: boolean,
  displayOrder: typeof displayOrder,
  transforms: typeof transforms,
  models: ImmutableMap<string, *>,
  codeMirrorMode: *,
  selectCell: () => void,
  focusEditor: () => void,
  unfocusEditor: () => void,
  focusAboveCell: () => void,
  focusBelowCell: () => void
};

const mapStateToCellProps = (state, { id }) => {
  const cellMap = selectors.currentCellMap(state);
  const cell = cellMap && cellMap.get(id);
  if (!cell) {
    throw new Error("cell not found inside cell map");
  }

  const cellType = cell.get("cell_type");
  const outputs = cell.get("outputs", ImmutableList());

  const sourceHidden =
    cellType === "code" &&
    (cell.getIn(["metadata", "inputHidden"], false) ||
      cell.getIn(["metadata", "hide_input"], false));

  const outputHidden =
    cellType === "code" &&
    (outputs.size === 0 || cell.getIn(["metadata", "outputHidden"]));

  const outputExpanded =
    cellType === "code" && cell.getIn(["metadata", "outputExpanded"]);

  return {
    cellType,
    source: cell.get("source", ""),
    theme: selectors.userPreferences(state).theme,
    executionCount: cell.get("execution_count"),
    outputs,
    models: selectors.models(state),
    pager: selectors.cellPagers(state).get(id, ImmutableList()),
    cellFocused: selectors.currentFocusedCellId(state) === id,
    editorFocused: selectors.currentFocusedEditorId(state) === id,
    sourceHidden,
    outputHidden,
    outputExpanded,
    cellStatus: selectors.transientCellMap(state).getIn([id, "status"])
  };
};

const mapDispatchToCellProps = (dispatch, { id, contentRef }) => ({
  selectCell: () => dispatch(actions.focusCell({ id, contentRef })),
  focusEditor: () => dispatch(actions.focusCellEditor({ id, contentRef })),
  unfocusEditor: () =>
    dispatch(actions.focusCellEditor({ id: null, contentRef })),
  focusAboveCell: () => {
    dispatch(actions.focusPreviousCell({ id, contentRef }));
    dispatch(actions.focusPreviousCellEditor({ id, contentRef }));
  },
  focusBelowCell: () => {
    dispatch(
      actions.focusNextCell({ id, createCellIfUndefined: true, contentRef })
    );
    dispatch(actions.focusNextCellEditor({ id, contentRef }));
  }
});

class AnyCell extends React.PureComponent<AnyCellProps, *> {
  static contextTypes = {
    store: PropTypes.object
  };

  render(): ?React$Element<any> {
    const {
      cellFocused,
      cellStatus,
      cellType,
      editorFocused,
      focusAboveCell,
      focusBelowCell,
      focusEditor,
      id,
      selectCell,
      unfocusEditor,
      contentRef
    } = this.props;

    const running = cellStatus === "busy";
    const queued = cellStatus === "queued";
    let element = null;

    switch (cellType) {
      case "code":
        element = (
          <React.Fragment>
            <Input hidden={this.props.sourceHidden}>
              <Prompt
                counter={this.props.executionCount}
                running={running}
                queued={queued}
              />
              <Source>
                <Editor
                  tip
                  completion
                  id={id}
                  contentRef={contentRef}
                  value={this.props.source}
                  cellFocused={cellFocused}
                  editorFocused={editorFocused}
                  theme={this.props.theme}
                  focusAbove={focusAboveCell}
                  focusBelow={focusBelowCell}
                  options={{
                    mode: isImmutable(this.props.codeMirrorMode)
                      ? this.props.codeMirrorMode.toJS()
                      : this.props.codeMirrorMode
                  }}
                />
              </Source>
            </Input>
            <Pagers>
              {this.props.pager.map((pager, key) => (
                <RichestMime
                  expanded
                  className="pager"
                  displayOrder={this.props.displayOrder}
                  transforms={this.props.transforms}
                  bundle={pager}
                  theme={this.props.theme}
                  key={key}
                />
              ))}
            </Pagers>
            <Outputs
              hidden={this.props.outputHidden}
              expanded={this.props.outputExpanded}
            >
              <Display
                className="outputs-display"
                outputs={this.props.outputs.toJS()}
                displayOrder={this.props.displayOrder}
                transforms={this.props.transforms}
                theme={this.props.theme}
                expanded={this.props.outputExpanded}
                isHidden={this.props.outputHidden}
                models={this.props.models.toJS()}
              />
            </Outputs>
          </React.Fragment>
        );

        break;
      case "markdown":
        element = (
          <MarkdownPreviewer
            focusAbove={focusAboveCell}
            focusBelow={focusBelowCell}
            focusEditor={focusEditor}
            cellFocused={cellFocused}
            editorFocused={editorFocused}
            unfocusEditor={unfocusEditor}
            source={this.props.source}
          >
            <Source>
              <Editor
                id={id}
                value={this.props.source}
                theme={this.props.theme}
                focusAbove={focusAboveCell}
                focusBelow={focusBelowCell}
                cellFocused={cellFocused}
                editorFocused={editorFocused}
                contentRef={contentRef}
                options={{
                  // Markdown should always be line wrapped
                  lineWrapping: true,
                  // Rely _directly_ on the codemirror mode
                  mode: {
                    name: "gfm",
                    tokenTypeOverrides: {
                      emoji: "emoji"
                    }
                  }
                }}
              />
            </Source>
          </MarkdownPreviewer>
        );
        break;

      default:
        element =
{this.props.source}
;
        break;
    }

    return (
      <HijackScroll focused={cellFocused} onClick={selectCell}>
        <Cell isSelected={cellFocused}>
          <Toolbar
            type={cellType}
            id={id}
            source={this.props.source}
            contentRef={contentRef}
          />
          {element}

        </Cell>
      </HijackScroll>
    );
  }
}

export const ConnectedCell = connect(
  mapStateToCellProps,
  mapDispatchToCellProps
)(AnyCell);

type NotebookProps = NotebookStateProps & NotebookDispatchProps;

type PureNotebookProps = {
  displayOrder?: Array<string>,
  cellOrder?: ImmutableList<any>,
  transforms?: Object,
  theme?: string,
  lastSaved?: Date,
  languageDisplayName?: string,
  kernelStatus?: string,
  codeMirrorMode?: string | ImmutableMap<string, *>,
  // TODO: Once we're willing to do multi-contents views, we should require this
  //       to be passed in
  // TODO: Fill in more from the convo with Andrew here
  contentRef?: ContentRef
};

type NotebookStateProps = {
  displayOrder: Array<string>,
  cellOrder: ImmutableList<any>,
  transforms: Object,
  theme: string,
  lastSaved: ?Date,
  languageDisplayName: string,
  kernelStatus: string,
  codeMirrorMode: string | ImmutableMap<string, *>,
  contentRef: ContentRef
};

type NotebookDispatchProps = {
  moveCell: (payload: *) => *,
  focusCell: (payload: *) => *,
  executeFocusedCell: (payload: *) => *,
  focusNextCell: (*) => *,
  focusNextCellEditor: (*) => *
};

const mapStateToProps = (
  state: Object,
  ownProps: PureNotebookProps
): NotebookStateProps => {
  return {
    theme: selectors.userPreferences(state).theme,
    lastSaved: selectors.currentLastSaved(state),
    cellOrder: selectors.currentCellOrder(state) || Immutable.List(),
    kernelStatus: selectors.currentKernelStatus(state),
    languageDisplayName: selectors.currentDisplayName(state),
    transforms: ownProps.transforms || transforms,
    displayOrder: ownProps.displayOrder || displayOrder,
    codeMirrorMode: selectors.codeMirrorMode(state),
    // TODO: this will need to be a currentNotebookContentRef or some such...
    contentRef: ownProps.contentRef || selectors.currentContentRef(state)
  };
};

const mapDispatchToProps = (dispatch: Dispatch<*>): NotebookDispatchProps => ({
  moveCell: (payload: *) => dispatch(actions.moveCell(payload)),
  focusCell: (payload: *) => dispatch(actions.focusCell(payload)),
  executeFocusedCell: (payload: *) =>
    dispatch(actions.executeFocusedCell(payload)),
  focusNextCell: (payload: *) => dispatch(actions.focusNextCell(payload)),
  focusNextCellEditor: (payload: *) =>
    dispatch(actions.focusNextCellEditor(payload))
});

export class NotebookApp extends React.PureComponent<NotebookProps> {
  static defaultProps = {
    theme: "light",
    displayOrder,
    transforms
  };

  static contextTypes = {
    store: PropTypes.object
  };

  constructor(): void {
    super();
    (this: any).createCellElement = this.createCellElement.bind(this);
    (this: any).keyDown = this.keyDown.bind(this);
    (this: any).renderCell = this.renderCell.bind(this);
  }

  componentDidMount(): void {
    document.addEventListener("keydown", this.keyDown);
  }

  componentWillUnmount(): void {
    document.removeEventListener("keydown", this.keyDown);
  }

  keyDown(e: KeyboardEvent): void {
    // If enter is not pressed, do nothing
    if (e.keyCode !== 13) {
      return;
    }

    const {
      executeFocusedCell,
      focusNextCell,
      focusNextCellEditor,
      contentRef
    } = this.props;

    let ctrlKeyPressed = e.ctrlKey;
    // Allow cmd + enter (macOS) to operate like ctrl + enter
    if (process.platform === "darwin") {
      ctrlKeyPressed = (e.metaKey || e.ctrlKey) && !(e.metaKey && e.ctrlKey);
    }

    const shiftXORctrl =
      (e.shiftKey || ctrlKeyPressed) && !(e.shiftKey && ctrlKeyPressed);
    if (!shiftXORctrl) {
      return;
    }

    e.preventDefault();

    // NOTE: Order matters here because we need it to execute _before_ we
    // focus the next cell
    executeFocusedCell({ contentRef });

    if (e.shiftKey) {
      // Couldn't focusNextCell just do focusing of both?
      focusNextCell({ id: null, createCellIfUndefined: true, contentRef });
      focusNextCellEditor({ id: null, contentRef });
    }
  }

  renderCell(id: string): ?React$Element<any> {
    const { contentRef } = this.props;
    return (
      <ConnectedCell
        id={id}
        transforms={this.props.transforms}
        displayOrder={this.props.displayOrder}
        codeMirrorMode={this.props.codeMirrorMode}
        contentRef={contentRef}
      />
    );
  }

  createCellElement(id: string): React$Element<*> {
    const { moveCell, focusCell, contentRef } = this.props;
    return (
      <div className="cell-container" key={`cell-container-${id}`}>
        <DraggableCell
          moveCell={moveCell}
          id={id}
          focusCell={focusCell}
          contentRef={contentRef}
        >
          {this.renderCell(id)}
        </DraggableCell>
        <CellCreator
          key={`creator-${id}`}
          id={id}
          above={false}
          contentRef={contentRef}
        />

    );
  }

  render(): ?React$Element<any> {
    return (
      <React.Fragment>

          <CellCreator
            id={this.props.cellOrder.get(0)}
            above
            contentRef={this.props.contentRef}
          />
          {this.props.cellOrder.map(this.createCellElement)}

        <StatusBar
          lastSaved={this.props.lastSaved}
          kernelSpecDisplayName={this.props.languageDisplayName}
          kernelStatus={this.props.kernelStatus}
        />

      </React.Fragment>
    );
  }
}

export const ConnectedNotebook = dragDropContext(HTML5Backend)(NotebookApp);
export default connect(mapStateToProps, mapDispatchToProps)(ConnectedNotebook);
<commit_msg>compute fallback to pager<commit_after>/* eslint-disable no-return-assign */
/* @flow */
import * as Immutable from "immutable";
import * as React from "react";
import * as selectors from "../selectors";
import type { ContentRef } from "../state/refs";
import { DragDropContext as dragDropContext } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import { connect } from "react-redux";
import {
  List as ImmutableList,
  Map as ImmutableMap,
  Set as ImmutableSet,
  isImmutable
} from "immutable";

import { HijackScroll } from "./hijack-scroll";

import MathJax from "@nteract/mathjax";

import MarkdownPreviewer from "./markdown-preview";
import Toolbar from "./toolbar";

import { Display, RichestMime } from "@nteract/display-area";

import Editor from "./editor";

import { displayOrder, transforms } from "@nteract/transforms";

import { Input, Prompt, Source, Pagers, Outputs, Cell } from "./presentational";

import DraggableCell from "./draggable-cell";
import CellCreator from "./cell-creator";
import StatusBar from "./status-bar";

import * as actions from "../actions";

// NOTE: PropTypes are required for the sake of contextTypes
const PropTypes = require("prop-types");

const themes = require("../themes");

type AnyCellProps = {
  id: string,
  contentRef: ContentRef,
  cellType: "markdown" | "code" | "raw",
  theme: string,
  source: string,
  executionCount: *,
  outputs: ImmutableList<*>,
  pager: ImmutableList<*>,
  cellStatus: string,
  cellFocused: boolean, // not the ID of which is focused
  editorFocused: boolean,
  sourceHidden: boolean,
  outputHidden: boolean,
  outputExpanded: boolean,
  displayOrder: typeof displayOrder,
  transforms: typeof transforms,
  models: ImmutableMap<string, *>,
  codeMirrorMode: *,
  selectCell: () => void,
  focusEditor: () => void,
  unfocusEditor: () => void,
  focusAboveCell: () => void,
  focusBelowCell: () => void
};

const mapStateToCellProps = (state, { id }) => {
  const cellMap = selectors.currentCellMap(state);
  const cell = cellMap && cellMap.get(id);
  if (!cell) {
    throw new Error("cell not found inside cell map");
  }

  const cellType = cell.get("cell_type");
  const outputs = cell.get("outputs", ImmutableList());

  const sourceHidden =
    cellType === "code" &&
    (cell.getIn(["metadata", "inputHidden"], false) ||
      cell.getIn(["metadata", "hide_input"], false));

  const outputHidden =
    cellType === "code" &&
    (outputs.size === 0 || cell.getIn(["metadata", "outputHidden"]));

  const outputExpanded =
    cellType === "code" && cell.getIn(["metadata", "outputExpanded"]);

  const cellPagers = selectors.cellPagers(state);
  const pager =
    cellPagers && cellPagers.get
      ? cellPagers.get(id, ImmutableList())
      : ImmutableList();

  return {
    cellType,
    source: cell.get("source", ""),
    theme: selectors.userPreferences(state).theme,
    executionCount: cell.get("execution_count"),
    outputs,
    models: selectors.models(state),
    pager,
    cellFocused: selectors.currentFocusedCellId(state) === id,
    editorFocused: selectors.currentFocusedEditorId(state) === id,
    sourceHidden,
    outputHidden,
    outputExpanded,
    cellStatus: selectors.transientCellMap(state).getIn([id, "status"])
  };
};

const mapDispatchToCellProps = (dispatch, { id, contentRef }) => ({
  selectCell: () => dispatch(actions.focusCell({ id, contentRef })),
  focusEditor: () => dispatch(actions.focusCellEditor({ id, contentRef })),
  unfocusEditor: () =>
    dispatch(actions.focusCellEditor({ id: null, contentRef })),
  focusAboveCell: () => {
    dispatch(actions.focusPreviousCell({ id, contentRef }));
    dispatch(actions.focusPreviousCellEditor({ id, contentRef }));
  },
  focusBelowCell: () => {
    dispatch(
      actions.focusNextCell({ id, createCellIfUndefined: true, contentRef })
    );
    dispatch(actions.focusNextCellEditor({ id, contentRef }));
  }
});

class AnyCell extends React.PureComponent<AnyCellProps, *> {
  static contextTypes = {
    store: PropTypes.object
  };

  render(): ?React$Element<any> {
    const {
      cellFocused,
      cellStatus,
      cellType,
      editorFocused,
      focusAboveCell,
      focusBelowCell,
      focusEditor,
      id,
      selectCell,
      unfocusEditor,
      contentRef
    } = this.props;

    const running = cellStatus === "busy";
    const queued = cellStatus === "queued";
    let element = null;

    switch (cellType) {
      case "code":
        element = (
          <React.Fragment>
            <Input hidden={this.props.sourceHidden}>
              <Prompt
                counter={this.props.executionCount}
                running={running}
                queued={queued}
              />
              <Source>
                <Editor
                  tip
                  completion
                  id={id}
                  contentRef={contentRef}
                  value={this.props.source}
                  cellFocused={cellFocused}
                  editorFocused={editorFocused}
                  theme={this.props.theme}
                  focusAbove={focusAboveCell}
                  focusBelow={focusBelowCell}
                  options={{
                    mode: isImmutable(this.props.codeMirrorMode)
                      ? this.props.codeMirrorMode.toJS()
                      : this.props.codeMirrorMode
                  }}
                />
              </Source>
            </Input>
            <Pagers>
              {this.props.pager.map((pager, key) => (
                <RichestMime
                  expanded
                  className="pager"
                  displayOrder={this.props.displayOrder}
                  transforms={this.props.transforms}
                  bundle={pager}
                  theme={this.props.theme}
                  key={key}
                />
              ))}
            </Pagers>
            <Outputs
              hidden={this.props.outputHidden}
              expanded={this.props.outputExpanded}
            >
              <Display
                className="outputs-display"
                outputs={this.props.outputs.toJS()}
                displayOrder={this.props.displayOrder}
                transforms={this.props.transforms}
                theme={this.props.theme}
                expanded={this.props.outputExpanded}
                isHidden={this.props.outputHidden}
                models={this.props.models.toJS()}
              />
            </Outputs>
          </React.Fragment>
        );

        break;
      case "markdown":
        element = (
          <MarkdownPreviewer
            focusAbove={focusAboveCell}
            focusBelow={focusBelowCell}
            focusEditor={focusEditor}
            cellFocused={cellFocused}
            editorFocused={editorFocused}
            unfocusEditor={unfocusEditor}
            source={this.props.source}
          >
            <Source>
              <Editor
                id={id}
                value={this.props.source}
                theme={this.props.theme}
                focusAbove={focusAboveCell}
                focusBelow={focusBelowCell}
                cellFocused={cellFocused}
                editorFocused={editorFocused}
                contentRef={contentRef}
                options={{
                  // Markdown should always be line wrapped
                  lineWrapping: true,
                  // Rely _directly_ on the codemirror mode
                  mode: {
                    name: "gfm",
                    tokenTypeOverrides: {
                      emoji: "emoji"
                    }
                  }
                }}
              />
            </Source>
          </MarkdownPreviewer>
        );
        break;

      default:
        element =
{this.props.source}
;
        break;
    }

    return (
      <HijackScroll focused={cellFocused} onClick={selectCell}>
        <Cell isSelected={cellFocused}>
          <Toolbar
            type={cellType}
            id={id}
            source={this.props.source}
            contentRef={contentRef}
          />
          {element}

        </Cell>
      </HijackScroll>
    );
  }
}

export const ConnectedCell = connect(
  mapStateToCellProps,
  mapDispatchToCellProps
)(AnyCell);

type NotebookProps = NotebookStateProps & NotebookDispatchProps;

type PureNotebookProps = {
  displayOrder?: Array<string>,
  cellOrder?: ImmutableList<any>,
  transforms?: Object,
  theme?: string,
  lastSaved?: Date,
  languageDisplayName?: string,
  kernelStatus?: string,
  codeMirrorMode?: string | ImmutableMap<string, *>,
  // TODO: Once we're willing to do multi-contents views, we should require this
  //       to be passed in
  // TODO: Fill in more from the convo with Andrew here
  contentRef?: ContentRef
};

type NotebookStateProps = {
  displayOrder: Array<string>,
  cellOrder: ImmutableList<any>,
  transforms: Object,
  theme: string,
  lastSaved: ?Date,
  languageDisplayName: string,
  kernelStatus: string,
  codeMirrorMode: string | ImmutableMap<string, *>,
  contentRef: ContentRef
};

type NotebookDispatchProps = {
  moveCell: (payload: *) => *,
  focusCell: (payload: *) => *,
  executeFocusedCell: (payload: *) => *,
  focusNextCell: (*) => *,
  focusNextCellEditor: (*) => *
};

const mapStateToProps = (
  state: Object,
  ownProps: PureNotebookProps
): NotebookStateProps => {
  return {
    theme: selectors.userPreferences(state).theme,
    lastSaved: selectors.currentLastSaved(state),
    cellOrder: selectors.currentCellOrder(state) || Immutable.List(),
    kernelStatus: selectors.currentKernelStatus(state),
    languageDisplayName: selectors.currentDisplayName(state),
    transforms: ownProps.transforms || transforms,
    displayOrder: ownProps.displayOrder || displayOrder,
    codeMirrorMode: selectors.codeMirrorMode(state),
    // TODO: this will need to be a currentNotebookContentRef or some such...
    contentRef: ownProps.contentRef || selectors.currentContentRef(state)
  };
};

const mapDispatchToProps = (dispatch: Dispatch<*>): NotebookDispatchProps => ({
  moveCell: (payload: *) => dispatch(actions.moveCell(payload)),
  focusCell: (payload: *) => dispatch(actions.focusCell(payload)),
  executeFocusedCell: (payload: *) =>
    dispatch(actions.executeFocusedCell(payload)),
  focusNextCell: (payload: *) => dispatch(actions.focusNextCell(payload)),
  focusNextCellEditor: (payload: *) =>
    dispatch(actions.focusNextCellEditor(payload))
});

export class NotebookApp extends React.PureComponent<NotebookProps> {
  static defaultProps = {
    theme: "light",
    displayOrder,
    transforms
  };

  static contextTypes = {
    store: PropTypes.object
  };

  constructor(): void {
    super();
    (this: any).createCellElement = this.createCellElement.bind(this);
    (this: any).keyDown = this.keyDown.bind(this);
    (this: any).renderCell = this.renderCell.bind(this);
  }

  componentDidMount(): void {
    document.addEventListener("keydown", this.keyDown);
  }

  componentWillUnmount(): void {
    document.removeEventListener("keydown", this.keyDown);
  }

  keyDown(e: KeyboardEvent): void {
    // If enter is not pressed, do nothing
    if (e.keyCode !== 13) {
      return;
    }

    const {
      executeFocusedCell,
      focusNextCell,
      focusNextCellEditor,
      contentRef
    } = this.props;

    let ctrlKeyPressed = e.ctrlKey;
    // Allow cmd + enter (macOS) to operate like ctrl + enter
    if (process.platform === "darwin") {
      ctrlKeyPressed = (e.metaKey || e.ctrlKey) && !(e.metaKey && e.ctrlKey);
    }

    const shiftXORctrl =
      (e.shiftKey || ctrlKeyPressed) && !(e.shiftKey && ctrlKeyPressed);
    if (!shiftXORctrl) {
      return;
    }

    e.preventDefault();

    // NOTE: Order matters here because we need it to execute _before_ we
    // focus the next cell
    executeFocusedCell({ contentRef });

    if (e.shiftKey) {
      // Couldn't focusNextCell just do focusing of both?
      focusNextCell({ id: null, createCellIfUndefined: true, contentRef });
      focusNextCellEditor({ id: null, contentRef });
    }
  }

  renderCell(id: string): ?React$Element<any> {
    const { contentRef } = this.props;
    return (
      <ConnectedCell
        id={id}
        transforms={this.props.transforms}
        displayOrder={this.props.displayOrder}
        codeMirrorMode={this.props.codeMirrorMode}
        contentRef={contentRef}
      />
    );
  }

  createCellElement(id: string): React$Element<*> {
    const { moveCell, focusCell, contentRef } = this.props;
    return (
      <div className="cell-container" key={`cell-container-${id}`}>
        <DraggableCell
          moveCell={moveCell}
          id={id}
          focusCell={focusCell}
          contentRef={contentRef}
        >
          {this.renderCell(id)}
        </DraggableCell>
        <CellCreator
          key={`creator-${id}`}
          id={id}
          above={false}
          contentRef={contentRef}
        />

    );
  }

  render(): ?React$Element<any> {
    return (
      <React.Fragment>

          <CellCreator
            id={this.props.cellOrder.get(0)}
            above
            contentRef={this.props.contentRef}
          />
          {this.props.cellOrder.map(this.createCellElement)}

        <StatusBar
          lastSaved={this.props.lastSaved}
          kernelSpecDisplayName={this.props.languageDisplayName}
          kernelStatus={this.props.kernelStatus}
        />

      </React.Fragment>
    );
  }
}

export const ConnectedNotebook = dragDropContext(HTML5Backend)(NotebookApp);
export default connect(mapStateToProps, mapDispatchToProps)(ConnectedNotebook);
<|endoftext|>


<commit_before>/**
Implementation of a binary heap
-- Binary Tree (Structure)
-- Heap property (Parent priority <= to child nodes)
*/
var BinaryHeap = function(comparator) {
  this.heap = [];
  this.comparator = comparator;
  this.length = 0;
};

BinaryHeap.prototype.size = function() {
  return this.length;
};

BinaryHeap.prototype.isEmpty = function() {
  return this.length < 1;
};

BinaryHeap.prototype.peek = function() {
  return this.heap;
};

/**
Returns the left child index of parent n

@param {Number} idx Parent Index
@return {Number} index of the child
*/
BinaryHeap.prototype.getLeftChildIndex = function(idx) {
  return Math.floor((idx << 1));
};

/**
Returns the left child element at position n

@param {Number} idx Index of element to return
@return {Object} Node element
*/
BinaryHeap.prototype.getLeftChild = function(idx) {
  return this.heap[this.getLeftChildIndex(idx)];
};

/**
Returns the right child index of parent n

@param {Number} idx Index of parent element
@return {Number} The index of the child element
*/
BinaryHeap.prototype.getRightChildIndex = function(idx) {
  return Math.floor((idx << 1) + 1);
}

/**
Returns the right child element at position n

@param {Number} idx The index of the child element
@param {Object} Node element
*/
BinaryHeap.prototype.getRightChild = function(idx) {
  return this.heap[this.getRightChildIndex(idx)];
};

/**
Returns the parent index for element at position n

@param {Number} idx Index of child element
@return {Number} Index of parent element
*/
BinaryHeap.prototype.getParentIndex = function(idx) {
  return Math.floor((idx >> 1));
};

BinaryHeap.prototype.getParent = function(idx) {
  return this.heap[this.getParentIndex(idx)];
};

BinaryHeap.prototype.enqueue = function(item) {
  this.heap[(this.length++)] = item;
  this.bubbleUp(this.length - 1);

  return this;
};

/**
Removes the given node from the queue

@param {Object} item Item to remove
@return {Object} this
*/
BinaryHeap.prototype.remove = function(item) {
  if (typeof item === 'undefined') {
    return null;
  }

  for (var i=0; i<this.length; i++) {
    if (this.heap[i] === node) {
      var end = this.heap.pop();
      this.heap.slice(i, 1);
      this.length--;
      this.heap[i] = end;
      this.bubbleUp(i);
      this.sink(i);
      break;
    }
  }

  return this;
};

BinaryHeap.prototype.bubbleUp = function(idx) {
  var item = this.heap[idx];
  var score = this.comparator(item);
  while (idx > 0) {
    // get the parent of the current element
    var parent = this.getParent(idx);
    var parentIdx = this.getParentIndex(idx);

    if (score >= this.comparator(parent)) {
      break;
    }

    this.heap[parentIdx] = item;
    this.heap[idx] = parent;
    idx = parentIdx;
  }

  return this;
};

BinaryHeap.prototype.dequeue = function() {
  var item = this.heap[0];
  var end = this.heap.pop();
  this.length -= 1;

  if (this.length > 0) {
    this.heap[0] = end;
    this.sink(0);
  }

  return item;
};

BinaryHeap.prototype.sink = function(idx) {
  var len = this.length;
  var item = this.heap[idx];
  var score = this.comparator(item);
  var leftChild = null;
  var rightChild = null;
  var leftChildScore = NaN;
  var rightChildScore = NaN;
  var swap = null;
  var left = 0;
  var rigth = 0;

  while(true) {
    // reinitialize to null
    swap = null;

    // get child indexes
    right = this.getRightChildIndex(idx);
    left = this.getLeftChildIndex(idx);

    // reinitialize scores to NaN
    rightChildScore = NaN;
    leftChildScore = NaN;

    if (left < len) {
      leftChild = this.heap[left];
      leftChildScore = this.comparator(leftChild);

      // swap the item with the left child
      if (leftChildScore < score) {
        swap = left;
      }
    }

    if (right < len) {
      rightChild = this.heap[right];
      rightChildScore = this.comparator(rightChild);

      if (rightChildScore < (isNaN(leftChildScore) ? score : leftChildScore)) {
        swap = right;
      }
    }

    if (swap === null) {
      break;
    }

    // move the swappable element into the current index position
    this.heap[idx] = this.heap[swap];

    // move the item into the swappable element's position...
    this.heap[swap] = item;

    // make the current index the swappable element's index
    idx = swap;
  }
};

module.exports = BinaryHeap;

///// TEST ////
var heap = new BinaryHeap(function(task) {
  return task.priority;
});

heap.enqueue({
  'task': 1
  ,priority: 10
});

heap.enqueue({
  'task': 2
  ,priority: 6
});

heap.enqueue({
  'task': 3
  ,priority: 9
});

var node = {
  'task': 4
  ,priority: 7
};

heap.enqueue(node);

heap.remove(node);

heap.enqueue(node);

while(heap.size() > 0) {
  console.log('tasks', heap.dequeue());
};

console.log('size', heap.size());

<commit_msg>Add bitwise operations<commit_after>/**
Implementation of a binary heap
-- Binary Tree (Structure)
-- Heap property (Parent priority <= to child nodes)
*/

var splice = function(arr, idx) {
  var len = array.length;
  var count = 0;
  var tmp = [];

  for (var i=0; i<len; i++) {
    if (i !== idx) {
      tmp[count++] = arr[i];
    }
  }

  return tmp;
};

var BinaryHeap = function(comparator, max) {
  this.heap = [];
  this.comparator = comparator;
  this.length = 0;
};

BinaryHeap.prototype.size = function() {
  return this.length;
};

BinaryHeap.prototype.isEmpty = function() {
  return this.length < 1;
};

BinaryHeap.prototype.peek = function() {
  return (this.length > 0) ? this.heap[0] : null;
};

/**
Returns the left child index of parent n

@param {Number} idx Parent Index
@return {Number} index of the child
*/
BinaryHeap.prototype.getLeftChildIndex = function(idx) {
  return (((idx << 1)) | 0);
};

/**
Returns the left child element at position n

@param {Number} idx Index of element to return
@return {Object} Node element
*/
BinaryHeap.prototype.getLeftChild = function(idx) {
  return this.heap[this.getLeftChildIndex(idx)];
};

/**
Returns the right child index of parent n

@param {Number} idx Index of parent element
@return {Number} The index of the child element
*/
BinaryHeap.prototype.getRightChildIndex = function(idx) {
  return (((idx << 1) + 1) | 0);
}

/**
Returns the right child element at position n

@param {Number} idx The index of the child element
@param {Object} Node element
*/
BinaryHeap.prototype.getRightChild = function(idx) {
  return this.heap[this.getRightChildIndex(idx)];
};

/**
Returns the parent index for element at position n

@param {Number} idx Index of child element
@return {Number} Index of parent element
*/
BinaryHeap.prototype.getParentIndex = function(idx) {
  return ((idx >> 1) | 0);
};

BinaryHeap.prototype.getParent = function(idx) {
  return this.heap[this.getParentIndex(idx)];
};

BinaryHeap.prototype.enqueue = function(item) {
  this.heap[this.length++] = item;
  this.bubbleUp(this.length - 1);

  return this;
};

BinaryHeap.prototype.inRange = function(idx) {
  return (idx >= 0 && idx < this.size());
};

BinaryHeap.prototype.getAt = function(idx) {
  return (this.size() > 0 && this.inRange(idx)) ? this.heap[idx] : null;
};

/**
Removes the given node from the queue

@param {Object} item Item to remove
@return {Object} this
*/
BinaryHeap.prototype.remove = function(item) {
  if (typeof item === 'undefined') {
    return null;
  }

  for (var i=0; i<this.length; i++) {
    if (this.heap[i] === item) {
      var end = this.heap.pop();
      this.heap.slice(i, 1);
      this.length--;
      this.heap[i] = end;
      this.bubbleUp(i);
      this.sink(i);
      break;
    }
  }

  return this;
};

BinaryHeap.prototype.bubbleUp = function(idx) {
  var item = this.heap[idx];
  var score = this.comparator(item);
  while (idx > 0) {
    // get the parent of the current element
    var parent = this.getParent(idx);
    var parentIdx = this.getParentIndex(idx);

    // if the item score is greater than
    // it's parent, break out!
    if (score >= this.comparator(parent)) {
      break;
    }

    // swap parent with child element
    this.heap[parentIdx] = item;
    this.heap[idx] = parent;

    // keep it moving
    idx = parentIdx;
  }

  return this;
};

BinaryHeap.prototype.dequeue = function() {
  var item = this.peek();

  if (this.size() > 0) {
    this.heap[0] = this.heap.pop();
    this.length -= 1;
    this.sink(0);
  }

  return item;
};

BinaryHeap.prototype.swap = function(a, b) {
  var tmp = this.heap[b];
  this.heap[b] = this.heap[a];
  this.heap[a] = tmp;

  //.log('swapping...')
  return this;
};

BinaryHeap.prototype.sink = function(idx) {
  var len = this.length;
  var item = this.heap[idx];
  var score = this.comparator(item);
  var leftChild = null;
  var rightChild = null;
  var leftChildScore = NaN;
  var rightChildScore = NaN;
  var swap = null;
  var leftIndex= 0;
  var rigthIndex = 0;

  while(true) {
    // reinitialize to null
    swap = null;

    // get child indexes
    rightIndex = this.getRightChildIndex(idx);
    leftIndex = this.getLeftChildIndex(idx);

    // reinitialize scores to NaN
    rightChildScore = NaN;
    leftChildScore = NaN;

    if (leftIndex < len) {
      leftChild = this.getAt(leftIndex);
      leftChildScore = this.comparator(leftChild);

      // swap the item with the left child
      if (leftChildScore < score) {
        swap = leftIndex;
      }
    }

    if (rightIndex < len) {
      rightChild = this.getAt(rightIndex)
      rightChildScore = this.comparator(rightChild);

      if (rightChildScore < (isNaN(leftChildScore) ? score : leftChildScore)) {
        swap = rightIndex;
      }
    }

    // nothing to swap, so exit!
    if (swap === null) {
      break;
    }

    // move the swappable element into the current index position
    this.heap[idx] = this.heap[swap];

    // move the item into the swappable element's position...
    this.heap[swap] = item;

    // make the current index the swappable element's index
    idx = swap;
  }
};

module.exports = BinaryHeap;

var max = 10;

// var PriorityQueue = require('priorityqueuejs');

// var queue = new PriorityQueue(function(a, b) {
//   return a.cash - b.cash;
// });

// for (var i=0; i<max; i++) {
//   queue.enq({cash: i, name: 'me'});
// }

// while(true) {
//   console.log(queue.deq());
//   break;
// }

// /// TEST ////
var heap = new BinaryHeap(function(task) {
  return task.priority;
});

for (var i=0; i<max; i++) {
  heap.enqueue({
    task: i
    ,priority: i
  });
}

while(heap.size() > 0) {
   console.log(heap.dequeue());
};
<|endoftext|>


<commit_before>'use strict';

const gt = require('./../../../../modules/gettext');

/**
 * Validate params fields
 * @param {apiService} service
 * @param {Object} params
 */
function validate(service, params) {

    // account or user
    if (service.needRequiredFields(params, ['rightCollection', 'from'])) {
        return;
    }

    saveAccountCollection(service, params);
}

/**
 * Get account ID from query
 * @param {saveItemService} service
 * @param {object} params
 * @param {function} next
 */
function getAccount(service, params, next) {

    if (params.account && params.account._id) {
        next(params.account._id);
        return;
    }

    if (!params.user) {
        service.forbidden(gt.gettext('Cant create accountCollection, missing user or account'));
        return;
    }

    // find account from user
    service.app.db.models.User.findById(params.user, function(err, user) {
        if (service.handleMongoError(err)) {

            if (!user) {
                service.notFound(gt.gettext('User not found'));
                return;
            }

            if (!user.roles.account) {
                service.forbidden(gt.gettext('The user has no vacation account, collections are only linkable to accounts'));
                return;
            }

            next(user.roles.account);
        }
    });
}

/**
 * Update/create the AccountCollection document
 *
 * @param {saveItemService} service
 * @param {Object} params
 */
function saveAccountCollection(service, params) {

    var AccountCollection = service.app.db.models.AccountCollection;
    var util = require('util');

    if (params._id) {

        AccountCollection.findById(params._id, function(err, document) {
            if (service.handleMongoError(err)) {
                if (null === document) {
                    service.notFound(util.format(gt.gettext('AccountCollection document not found for id %s'), params.id));
                    return;
                }

                document.rightCollection 	= params.rightCollection._id;
                document.from 				= params.from;
                document.to 				= params.to;

                document.save(function (err) {

                    if (service.handleMongoError(err)) {

                        var doc = document.toObject();
                        doc.rightCollection = params.rightCollection; // output same populated sub document

                        service.resolveSuccess(
                            doc,
                            gt.gettext('The account collection has been modified')
                        );
                    }
                });
            }
        });

    } else {

        getAccount(service, params, function(accountId) {

            AccountCollection.create({
                    account: accountId,
                    rightCollection: params.rightCollection._id,
                    from: params.from,
                    to: params.to
                }, function(err, document) {

                if (service.handleMongoError(err))
                {
                    var doc = document.toObject();
                    doc.rightCollection = params.rightCollection; // output same populated sub document

                    service.resolveSuccess(
                        doc,
                        gt.gettext('The account collection has been created')
                    );
                }
            });

        });
    }
}

/**
 * Construct the AccountCollection save service
 * @param   {object}          services list of base classes from apiService
 * @param   {express|object}  app      express or headless app
 * @returns {saveItemService}
 */
exports = module.exports = function(services, app) {

    var service = new services.save(app);

    /**
     * Call the calendar save service
     *
     * @param {Object} params
     *
     * @return {Promise}
     */
    service.getResultPromise = function(params) {
        validate(service, params);
        return service.deferred.promise;
    };

    return service;
};

<commit_msg>Force time<commit_after>'use strict';

const gt = require('./../../../../modules/gettext');

/**
 * Validate params fields
 * @param {apiService} service
 * @param {Object} params
 */
function validate(service, params) {

    // account or user
    if (service.needRequiredFields(params, ['rightCollection', 'from'])) {
        return;
    }

    saveAccountCollection(service, params);
}

/**
 * Get account ID from query
 * @param {saveItemService} service
 * @param {object} params
 * @param {function} next
 */
function getAccount(service, params, next) {

    if (params.account && params.account._id) {
        next(params.account._id);
        return;
    }

    if (!params.user) {
        service.forbidden(gt.gettext('Cant create accountCollection, missing user or account'));
        return;
    }

    // find account from user
    service.app.db.models.User.findById(params.user, function(err, user) {
        if (service.handleMongoError(err)) {

            if (!user) {
                service.notFound(gt.gettext('User not found'));
                return;
            }

            if (!user.roles.account) {
                service.forbidden(gt.gettext('The user has no vacation account, collections are only linkable to accounts'));
                return;
            }

            next(user.roles.account);
        }
    });
}

/**
 * Update/create the AccountCollection document
 *
 * @param {saveItemService} service
 * @param {Object} params
 */
function saveAccountCollection(service, params) {

    var AccountCollection = service.app.db.models.AccountCollection;
    var util = require('util');

    if (params.from) {
        params.from = new Date(params.from);
        params.from.setHours(0,0,0,0);
    }

    if (params.to) {
        params.to = new Date(params.to);
        params.to.setHours(23,59,59,999);
    }

    if (params._id) {

        AccountCollection.findById(params._id, function(err, document) {
            if (service.handleMongoError(err)) {
                if (null === document) {
                    service.notFound(util.format(gt.gettext('AccountCollection document not found for id %s'), params.id));
                    return;
                }

                document.rightCollection 	= params.rightCollection._id;
                document.from 				= params.from;
                document.to 				= params.to;

                document.save(function (err) {

                    if (service.handleMongoError(err)) {

                        var doc = document.toObject();
                        doc.rightCollection = params.rightCollection; // output same populated sub document

                        service.resolveSuccess(
                            doc,
                            gt.gettext('The account collection has been modified')
                        );
                    }
                });
            }
        });

    } else {

        getAccount(service, params, function(accountId) {

            AccountCollection.create({
                    account: accountId,
                    rightCollection: params.rightCollection._id,
                    from: params.from,
                    to: params.to
                }, function(err, document) {

                if (service.handleMongoError(err))
                {
                    var doc = document.toObject();
                    doc.rightCollection = params.rightCollection; // output same populated sub document

                    service.resolveSuccess(
                        doc,
                        gt.gettext('The account collection has been created')
                    );
                }
            });

        });
    }
}

/**
 * Construct the AccountCollection save service
 * @param   {object}          services list of base classes from apiService
 * @param   {express|object}  app      express or headless app
 * @returns {saveItemService}
 */
exports = module.exports = function(services, app) {

    var service = new services.save(app);

    /**
     * Call the calendar save service
     *
     * @param {Object} params
     *
     * @return {Promise}
     */
    service.getResultPromise = function(params) {
        validate(service, params);
        return service.deferred.promise;
    };

    return service;
};

<|endoftext|>


<commit_before>import React, { useEffect } from "react";
import { useState } from "react";
import {
  TextField,
  Grid,
  Checkbox,
  FormControlLabel,
  Box,
} from "@material-ui/core";
import {
  MuiPickersUtilsProvider,
  KeyboardDateTimePicker,
} from "@material-ui/pickers";
import DateFnsUtils from "@date-io/date-fns";
import LocationAutocompleteInput from "../Utilities/LocationAutocompleteInput";
import { isValid } from "../../scripts/HelperFunctions";

export default function AddHotel(props) {
  let overwriting = props.data !== undefined;

  // Sets values to previous values if editing, otherwise blank slate
  const [startDate, setStartDate] = useState(
    overwriting ? props.data.startDate : props.startDate
  );
  const [endDate, setEndDate] = useState(
    overwriting ? props.data.endDate : props.startDate
  );
  const [checked, setChecked] = useState(
    overwriting ? props.data.finalized : false
  );
  const [title, setTitle] = useState(overwriting ? props.data.title : "");
  const [location, setLocation] = useState(
    overwriting
      ? {
        address: props.data.location,
        coordinates: props.data.coordinates,
        placeId: props.data.placeId,
      }
      : {
        address: "",
        coordinates: "",
        placeId: "",
      }
  );
  const [description, setDescription] = useState(
    overwriting ? props.data.description : ""
  );

  const handleChecked = (e) => {
    setChecked(e.target.checked);
  };

  const handleTitleChange = (e) => {
    setTitle(e.target.value);
  };

  const handleLocationChange = (location) => {
    setLocation(location);
  };

  const handleDescriptionChange = (e) => {
    setDescription(e.target.value);
  };

  useEffect(() => {
    if (props.data !== undefined && props.data.startDate !== startDate) {
      setStartDate(props.data.startDate);
    }

    if (props.data !== undefined && props.data.endDate !== endDate) {
      setEndDate(props.data.endDate);
    }
  }, [props.data]);
  /*
   * Called once change to hook state is complete. Updates data property in AddForm.
   */
  useEffect(() => {
    props.onDataChange({
      id: overwriting ? props.data.id : undefined,
      title: title,
      type: "hotel",
      startDate: startDate,
      endDate: endDate,
      finalized: checked,
      location: location ? location.address : null,
      coordinates: location ? location.coordinates : null,
      description: description,
    });

    //validating input
    if (title === "") {
      props.onToggleValidation(false);
    } else if (checked && (location===null||location.address==="")) {
      props.onToggleValidation(false);
    } else if (!isValid(startDate) || !isValid(endDate)) {
      props.onToggleValidation(false);
    } else {
      props.onToggleValidation(true);
    }
  }, [startDate, endDate, checked, title, location, description]);

  return (
    <Grid container direction="column">
      <Grid item>
        <TextField
          error={title === ""}
          helperText={title === "" ? "Cannot leave field blank" : ""}
          id="title"
          label={"Add Title"}
          defaultValue={title}
          fullWidth
          onChange={handleTitleChange}
        />
      </Grid>
      <Grid item>
        <FormControlLabel
          control={
            <Checkbox
              checked={checked}
              onChange={handleChecked}
              color="primary"
            />
          }
          label="Finalized"
        />
      </Grid>
      <Grid item container direction="row" justify="space-between">
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
          <KeyboardDateTimePicker
            format="yyyy/MM/dd HH:mm"
            label={"Check in"}
            value={startDate}
            onChange={setStartDate}
          />
        </MuiPickersUtilsProvider>
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
          <KeyboardDateTimePicker
            format="yyyy/MM/dd HH:mm"
            label={"Check out"}
            value={endDate}
            onChange={setEndDate}
          />
        </MuiPickersUtilsProvider>
      </Grid>
      <Grid item>
        <Box my={1}>
          <LocationAutocompleteInput
            onLocationSelected={handleLocationChange}
            error={checked && (location === null || location.address === "")}
            text={location ? location.address : ""}
            type="hotel"
          />
        </Box>
      </Grid>
      <Grid item>
        <TextField
          id="description"
          label={"Add Description"}
          defaultValue={description}
          fullWidth
          multiline
          onChange={handleDescriptionChange}
        />
      </Grid>
    </Grid>
  );
}
<commit_msg>Don't allow for checkin and checkout date to be same<commit_after>import React, { useEffect } from "react";
import { useState } from "react";
import {
  TextField,
  Grid,
  Checkbox,
  FormControlLabel,
  Box,
} from "@material-ui/core";
import {
  MuiPickersUtilsProvider,
  KeyboardDateTimePicker,
} from "@material-ui/pickers";
import DateFnsUtils from "@date-io/date-fns";
import LocationAutocompleteInput from "../Utilities/LocationAutocompleteInput";
import { isValid, sameDate } from "../../scripts/HelperFunctions";

export default function AddHotel(props) {
  let overwriting = props.data !== undefined;

  // Sets values to previous values if editing, otherwise blank slate
  const [startDate, setStartDate] = useState(
    overwriting ? props.data.startDate : props.startDate
  );
  const [endDate, setEndDate] = useState(
    overwriting ? props.data.endDate : props.startDate
  );
  const [checked, setChecked] = useState(
    overwriting ? props.data.finalized : false
  );
  const [title, setTitle] = useState(overwriting ? props.data.title : "");
  const [location, setLocation] = useState(
    overwriting
      ? {
        address: props.data.location,
        coordinates: props.data.coordinates,
        placeId: props.data.placeId,
      }
      : {
        address: "",
        coordinates: "",
        placeId: "",
      }
  );
  const [description, setDescription] = useState(
    overwriting ? props.data.description : ""
  );

  const handleChecked = (e) => {
    setChecked(e.target.checked);
  };

  const handleTitleChange = (e) => {
    setTitle(e.target.value);
  };

  const handleLocationChange = (location) => {
    setLocation(location);
  };

  const handleDescriptionChange = (e) => {
    setDescription(e.target.value);
  };

  useEffect(() => {
    if (props.data !== undefined && props.data.startDate !== startDate) {
      setStartDate(props.data.startDate);
    }

    if (props.data !== undefined && props.data.endDate !== endDate) {
      setEndDate(props.data.endDate);
    }
  }, [props.data]);
  /*
   * Called once change to hook state is complete. Updates data property in AddForm.
   */
  useEffect(() => {
    props.onDataChange({
      id: overwriting ? props.data.id : undefined,
      title: title,
      type: "hotel",
      startDate: startDate,
      endDate: endDate,
      finalized: checked,
      location: location ? location.address : null,
      coordinates: location ? location.coordinates : null,
      description: description,
    });
    //validating input
    if (title === "") {
      props.onToggleValidation(false);

    } else if (checked && (location===null||location.address==="")) {
      props.onToggleValidation(false);
    } else if (!isValid(startDate) || !isValid(endDate) || sameDate(startDate, endDate)) {
      props.onToggleValidation(false);
    } else {
      props.onToggleValidation(true);
    }
  }, [startDate, endDate, checked, title, location, description]);

  return (
    <Grid container direction="column">
      <Grid item>
        <TextField
          error={title === ""}
          helperText={title === "" ? "Cannot leave field blank" : ""}
          id="title"
          label={"Add Title"}
          defaultValue={title}
          fullWidth
          onChange={handleTitleChange}
        />
      </Grid>
      <Grid item>
        <FormControlLabel
          control={
            <Checkbox
              checked={checked}
              onChange={handleChecked}
              color="primary"
            />
          }
          label="Finalized"
        />
      </Grid>
      <Grid item container direction="row" justify="space-between">
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
          <KeyboardDateTimePicker
            format="yyyy/MM/dd HH:mm"
            label={"Check in"}
            value={startDate}
            onChange={setStartDate}
          />
        </MuiPickersUtilsProvider>
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
          <KeyboardDateTimePicker
            format="yyyy/MM/dd HH:mm"
            label={"Check out"}
            value={endDate}
            onChange={setEndDate}
          />
        </MuiPickersUtilsProvider>
      </Grid>
      <Grid item>
        <Box my={1}>
          <LocationAutocompleteInput
            onLocationSelected={handleLocationChange}
            error={checked && (location === null || location.address === "")}
            text={location ? location.address : ""}
            type="hotel"
          />
        </Box>
      </Grid>
      <Grid item>
        <TextField
          id="description"
          label={"Add Description"}
          defaultValue={description}
          fullWidth
          multiline
          onChange={handleDescriptionChange}
        />
      </Grid>
    </Grid>
  );
}
<|endoftext|>


<commit_before>var $ = require('jquery');
var React = require('react/addons');
var RetinaImage = require('react-retina-image');
var ContainerStore = require('./ContainerStore');
<<<<<<>>>>>> master

var ImageCard = React.createClass({
  getInitialState: function () {
    return {
      tags: [],
      chosenTag: 'latest'
    };
  },
  handleTagClick: function (tag) {
    this.setState({
      chosenTag: tag
    });
    var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay');
    $tagOverlay.fadeOut(300);
    metrics.track('Selected Image Tag');
  },
  handleClick: function (name) {
    metrics.track('Created Container');
    ContainerStore.create(name, this.state.chosenTag, function (err) {
      if (err) {
        throw err;
      }
      $(document.body).find('.new-container-item').parent().fadeOut();
    }.bind(this));
  },
  handleTagOverlayClick: function (name) {
    var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay');
    $tagOverlay.fadeIn(300);
    $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', function (result) {
      this.setState({
        tags: result
      });
    }.bind(this));
  },
  handleCloseTagOverlay: function () {
    var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay');
    $tagOverlay.fadeOut(300);
  },
  render: function () {
    var self = this;
    var name;
    var imageNameTokens = this.props.image.name.split('/');
    var namespace;
    var repo;
    if (imageNameTokens.length > 1) {
      namespace = imageNameTokens[0];
      repo = imageNameTokens[1];
    } else {
      namespace = "official";
      repo = imageNameTokens[0];
    }
    if (this.props.image.is_official) {
      name = (

{namespace}

          <OverlayTrigger placement="bottom" overlay={<Tooltip>{this.props.image.name}</Tooltip>}>
            {repo}
          </OverlayTrigger>

      );
    } else {
      name = (

{namespace}

          <OverlayTrigger placement="bottom" overlay={<Tooltip>{this.props.image.name}</Tooltip>}>
            {repo}
          </OverlayTrigger>

      );
    }
    var description;
    if (this.props.image.description) {
      description = this.props.image.description;
    } else {
      description = "No description.";
    }
    var logoStyle = {
      backgroundImage: `linear-gradient(-180deg, ${this.props.image.gradient_start} 4%, ${this.props.image.gradient_end}  100%)`
    };
    var imgsrc;
    if (this.props.image.img) {
      imgsrc = `http://kitematic.com/recommended/${this.props.image.img}`;
    } else {
      imgsrc = 'http://kitematic.com/recommended/kitematic_html.png';
    }
    var tags;
    if (this.state.tags.length > 0) {
      var tagDisplay = this.state.tags.map(function (t) {
        return
{t.name}
;
      });
      tags = (

          {tagDisplay}

      );
    } else {
      tags = <RetinaImage className="tags-loading" src="loading-white.png"/>;
    }
    var officialBadge;
    if (this.props.image.is_official) {
      officialBadge = (
        <RetinaImage src="official.png" />
      );
    }
    return (

          {tags}

          <RetinaImage src={imgsrc}/>

            {officialBadge}

            {name}

            {description}

            <OverlayTrigger placement="bottom" overlay={<Tooltip>Favorites</Tooltip>}>

                {this.props.image.star_count}

            </OverlayTrigger>

              <OverlayTrigger placement="bottom" overlay={<Tooltip>Change Tag</Tooltip>}>
                {this.state.chosenTag}
              </OverlayTrigger>

              Create

    );
  }
});

module.exports = ImageCard;
<commit_msg>Fixing merge<commit_after>var $ = require('jquery');
var React = require('react/addons');
var RetinaImage = require('react-retina-image');
var ContainerStore = require('./ContainerStore');
var metrics = require('./Metrics');
var OverlayTrigger = require('react-bootstrap').OverlayTrigger;
var Tooltip = require('react-bootstrap').Tooltip;

var ImageCard = React.createClass({
  getInitialState: function () {
    return {
      tags: [],
      chosenTag: 'latest'
    };
  },
  handleTagClick: function (tag) {
    this.setState({
      chosenTag: tag
    });
    var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay');
    $tagOverlay.fadeOut(300);
    metrics.track('Selected Image Tag');
  },
  handleClick: function (name) {
    metrics.track('Created Container');
    ContainerStore.create(name, this.state.chosenTag, function (err) {
      if (err) {
        throw err;
      }
      $(document.body).find('.new-container-item').parent().fadeOut();
    }.bind(this));
  },
  handleTagOverlayClick: function (name) {
    var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay');
    $tagOverlay.fadeIn(300);
    $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', function (result) {
      this.setState({
        tags: result
      });
    }.bind(this));
  },
  handleCloseTagOverlay: function () {
    var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay');
    $tagOverlay.fadeOut(300);
  },
  render: function () {
    var self = this;
    var name;
    var imageNameTokens = this.props.image.name.split('/');
    var namespace;
    var repo;
    if (imageNameTokens.length > 1) {
      namespace = imageNameTokens[0];
      repo = imageNameTokens[1];
    } else {
      namespace = "official";
      repo = imageNameTokens[0];
    }
    if (this.props.image.is_official) {
      name = (

{namespace}

          <OverlayTrigger placement="bottom" overlay={<Tooltip>{this.props.image.name}</Tooltip>}>
            {repo}
          </OverlayTrigger>

      );
    } else {
      name = (

{namespace}

          <OverlayTrigger placement="bottom" overlay={<Tooltip>{this.props.image.name}</Tooltip>}>
            {repo}
          </OverlayTrigger>

      );
    }
    var description;
    if (this.props.image.description) {
      description = this.props.image.description;
    } else {
      description = "No description.";
    }
    var logoStyle = {
      backgroundImage: `linear-gradient(-180deg, ${this.props.image.gradient_start} 4%, ${this.props.image.gradient_end}  100%)`
    };
    var imgsrc;
    if (this.props.image.img) {
      imgsrc = `http://kitematic.com/recommended/${this.props.image.img}`;
    } else {
      imgsrc = 'http://kitematic.com/recommended/kitematic_html.png';
    }
    var tags;
    if (this.state.tags.length > 0) {
      var tagDisplay = this.state.tags.map(function (t) {
        return
{t.name}
;
      });
      tags = (

          {tagDisplay}

      );
    } else {
      tags = <RetinaImage className="tags-loading" src="loading-white.png"/>;
    }
    var officialBadge;
    if (this.props.image.is_official) {
      officialBadge = (
        <RetinaImage src="official.png" />
      );
    }
    return (

          {tags}

          <RetinaImage src={imgsrc}/>

            {officialBadge}

            {name}

            {description}

            <OverlayTrigger placement="bottom" overlay={<Tooltip>Favorites</Tooltip>}>

                {this.props.image.star_count}

            </OverlayTrigger>

              <OverlayTrigger placement="bottom" overlay={<Tooltip>Change Tag</Tooltip>}>
                {this.state.chosenTag}
              </OverlayTrigger>

              Create

    );
  }
});

module.exports = ImageCard;
<|endoftext|>


<commit_before>'use strict';

// exposify: CamSDK.Form
var CamundaForm = require('./../../forms/camunda-form');

var angular = require('angular');
var $ = CamundaForm.$;
var constants = require('./../../forms/constants');

var CamundaFormAngular = CamundaForm.extend(
{

  renderForm: function(formHtmlSource) {
    var self = this;

    // first add the form to the DOM:
    CamundaForm.prototype.renderForm.apply(this, arguments);

    // next perform auto-scope binding for all fields which do not have custom bindings
    function autoBind(key, el) {
      var element = $(el);
      if(!element.attr('ng-model')) {
        var camVarName = element.attr(constants.DIRECTIVE_CAM_VARIABLE_NAME);
        if(!!camVarName) {
          element.attr('ng-model', camVarName);
        }
      }
    }

    for(var i = 0; i < this.formFieldHandlers.length; i++) {
      var handler = this.formFieldHandlers[i];
      var selector = handler.selector;
      $(selector, self.formElement).each(autoBind);
    }

    // finally compile the form with angular and linked to the current scope
    var injector = self.formElement.injector();
    var scope = self.formElement.scope();
    injector.invoke(['$compile', function($compile) {
      $compile(self.formElement)(scope);
    }]);
  },

  executeFormScript: function(script) {

    // overrides executeFormScript to make sure the following variables / functions are available to script implementations:

    // * $scope
    // * inject

    var injector = this.formElement.injector();
    var scope = this.formElement.scope();

    (function(camForm, $scope) {

      // hook to create the service with injection
      var inject = function(extensions) {
        // if result is an array or function we expect
        // an injectable service
        if (angular.isFunction(extensions) || angular.isArray(extensions)) {
          injector.instantiate(extensions, { $scope: scope });
        } else {
          throw new Error('Must call inject(array|fn)');
        }
      };

      /* jshint evil: true */
      eval(script);
      /* jshint evil: false */

    })(this, scope);

  },

  fireEvent: function() {

    // overrides fireEvent to make sure event listener is invoked in an apply phase

    var self = this;
    var args = arguments;
    var scope = this.formElement.scope();

    var doFireEvent = function() {
      CamundaForm.prototype.fireEvent.apply(self, args);
    };

    var injector = self.formElement.injector();
    injector.invoke(['$rootScope', function($rootScope) {
      var phase = $rootScope.$$phase;
        // only apply if not already in digest / apply
        if(phase !== '$apply' && phase !== '$digest') {
          scope.$apply(function() {
            doFireEvent();
          });
        } else {
          doFireEvent();
        }

    }]);
  }
});

module.exports = CamundaFormAngular;
<commit_msg>improve(form): prevent use of injector when it could not be defined<commit_after>'use strict';

// exposify: CamSDK.Form
var CamundaForm = require('./../../forms/camunda-form');

var angular = require('angular');
var $ = CamundaForm.$;
var constants = require('./../../forms/constants');

var CamundaFormAngular = CamundaForm.extend(
{

  renderForm: function(formHtmlSource) {
    var self = this;

    // first add the form to the DOM:
    CamundaForm.prototype.renderForm.apply(this, arguments);

    // next perform auto-scope binding for all fields which do not have custom bindings
    function autoBind(key, el) {
      var element = $(el);
      if(!element.attr('ng-model')) {
        var camVarName = element.attr(constants.DIRECTIVE_CAM_VARIABLE_NAME);
        if(!!camVarName) {
          element.attr('ng-model', camVarName);
        }
      }
    }

    for(var i = 0; i < this.formFieldHandlers.length; i++) {
      var handler = this.formFieldHandlers[i];
      var selector = handler.selector;
      $(selector, self.formElement).each(autoBind);
    }

    // finally compile the form with angular and linked to the current scope
    var injector = self.formElement.injector();
    if (!injector) { return; }

    var scope = self.formElement.scope();
    injector.invoke(['$compile', function($compile) {
      $compile(self.formElement)(scope);
    }]);
  },

  executeFormScript: function(script) {

    // overrides executeFormScript to make sure the following variables / functions are available to script implementations:

    // * $scope
    // * inject

    var injector = this.formElement.injector();
    var scope = this.formElement.scope();

    (function(camForm, $scope) {

      // hook to create the service with injection
      var inject = function(extensions) {
        // if result is an array or function we expect
        // an injectable service
        if (angular.isFunction(extensions) || angular.isArray(extensions)) {
          injector.instantiate(extensions, { $scope: scope });
        } else {
          throw new Error('Must call inject(array|fn)');
        }
      };

      /* jshint evil: true */
      eval(script);
      /* jshint evil: false */

    })(this, scope);

  },

  fireEvent: function() {

    // overrides fireEvent to make sure event listener is invoked in an apply phase

    var self = this;
    var args = arguments;
    var scope = this.formElement.scope();

    var doFireEvent = function() {
      CamundaForm.prototype.fireEvent.apply(self, args);
    };

    var injector = self.formElement.injector();
    if (!injector) { return; }

    injector.invoke(['$rootScope', function($rootScope) {
      var phase = $rootScope.$$phase;
        // only apply if not already in digest / apply
        if(phase !== '$apply' && phase !== '$digest') {
          scope.$apply(function() {
            doFireEvent();
          });
        } else {
          doFireEvent();
        }

    }]);
  }
});

module.exports = CamundaFormAngular;
<|endoftext|>


<commit_before>$.fn.hoverClass = function(c) {
	return this.each(function(){
		$(this).hover(
			function() { $(this).addClass(c);  },
			function() { $(this).removeClass(c); }
		);
	});
};

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

$(document).ready(function(){
	// Alternate the rows' styling.
    $("table").each(function(){
	  $("tr:odd", this).not(".even").addClass("odd");
	  $("tr:even", this).not(".odd").addClass("even");
	});

	$("#menu .menu-item").hover(
		function(){ $("ul", this).fadeIn("fast"); },
		function() { }
	);

	if (document.all) {
		$("#menu .menu-item").hoverClass("sfHover");
	}

	// Prevent all checkboxes to be unchecked.
	$(".search_field").click(function(){
		if($(".search_field:checked").size() == 0 && !$(this).attr('checked')) {
			return false;
		}
	});

	// Toggle default text of inputs on the publish page.
	$('label.incontent').each(function(){
		var ctl = '#' + $(this).attr('for');
		if($(ctl).val() == '') {
			$(ctl).val($(this).html().trim())
				.addClass('islabeled');
		}
		$(this).hide();
	});

	$('.islabeled').focus(function(){
		$(this).filter('.islabeled')
			.val('')
			.removeClass('islabeled');
	}).blur(function(){
		if($(this).val() == '') {
			$(this).val($('label.incontent[for=' + $(this).attr('id') + ']').html().trim())
				.addClass('islabeled');
		}
	});

	$('.islabeled').parents('form').submit(function(){
		$('.islabeled').val('');
	});

	// Convert these links into buttons
	$('a.link_as_button').each(function(){
		$(this).after('<button onclick="location.href=\'' + $(this).attr('href') + '\'">' + $(this).html() + '</button>').hide();
	});
});<commit_msg>Fix for plugin page for Firefox to display plugin config pages on link_as_button links.<commit_after>$.fn.hoverClass = function(c) {
	return this.each(function(){
		$(this).hover(
			function() { $(this).addClass(c);  },
			function() { $(this).removeClass(c); }
		);
	});
};

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

$(document).ready(function(){
	// Alternate the rows' styling.
    $("table").each(function(){
	  $("tr:odd", this).not(".even").addClass("odd");
	  $("tr:even", this).not(".odd").addClass("even");
	});

	$("#menu .menu-item").hover(
		function(){ $("ul", this).fadeIn("fast"); },
		function() { }
	);

	if (document.all) {
		$("#menu .menu-item").hoverClass("sfHover");
	}

	// Prevent all checkboxes to be unchecked.
	$(".search_field").click(function(){
		if($(".search_field:checked").size() == 0 && !$(this).attr('checked')) {
			return false;
		}
	});

	// Toggle default text of inputs on the publish page.
	$('label.incontent').each(function(){
		var ctl = '#' + $(this).attr('for');
		if($(ctl).val() == '') {
			$(ctl).val($(this).html().trim())
				.addClass('islabeled');
		}
		$(this).hide();
	});

	$('.islabeled').focus(function(){
		$(this).filter('.islabeled')
			.val('')
			.removeClass('islabeled');
	}).blur(function(){
		if($(this).val() == '') {
			$(this).val($('label.incontent[for=' + $(this).attr('id') + ']').html().trim())
				.addClass('islabeled');
		}
	});

	$('.islabeled').parents('form').submit(function(){
		$('.islabeled').val('');
	});

	// Convert these links into buttons
	$('a.link_as_button').each(function(){
		$(this).after('<button onclick="location.href=\'' + $(this).attr('href') + '\';return false;">' + $(this).html() + '</button>').hide();
	});
});<|endoftext|>


<commit_before>"use strict";

(function() {
	$(window).on('action:ajaxify.end', function(data) {
		//console.log("ajaxify ended: " + data);

		if($("#tph-audio").length == 0){
			var curName = "";

			var songArray = ["Hestia%20Dance.mp3"];

			var targetedUsers = ["Chiruno",
									"PangoPanjo"];

			var trackSelected = Math.floor(Math.random() * songArray.length);

			var audioTag = "
" + "<audio autoplay><source src=\"http://chir.uno/TargetTracks/" + songArray[trackSelected] +"\" type=\"audio/mpeg\"></audio>" + "
";

			if($("#user-header-name").length > 0)
				curName = $("#user-header-name").html();

			if($.inArray(curName, targetedUsers) != -1){
				$("body").append(audioTag);
			}
		}
	});
}());<commit_msg>removed myself as target; functionality confirmed<commit_after>"use strict";

(function() {
	$(window).on('action:ajaxify.end', function(data) {
		//console.log("ajaxify ended: " + data);

		if($("#tph-audio").length == 0){
			var curName = "";

			var songArray = ["Hestia%20Dance.mp3"];

			var targetedUsers = ["PangoPanjo"];

			var trackSelected = Math.floor(Math.random() * songArray.length);

			var audioTag = "
" + "<audio autoplay><source src=\"http://chir.uno/TargetTracks/" + songArray[trackSelected] +"\" type=\"audio/mpeg\"></audio>" + "
";

			if($("#user-header-name").length > 0)
				curName = $("#user-header-name").html();

			if($.inArray(curName, targetedUsers) != -1){
				$("body").append(audioTag);
			}
		}
	});
}());<|endoftext|>


<commit_before>var assert = require('assert');
var _ = require('lodash');
var Adapter = require('../../lib/adapter');
var Support = require('./support/bootstrap');

describe('Unit Tests ::', function() {
  describe('Find', function() {
    // Test Setup
    before(function(done) {
      Support.Setup('test_find', function(err) {
        if (err) {
          return done(err);
        }

        // Seed the database with two simple records.
        Support.Seed('test_find', done);
      });
    });

    after(function(done) {
      Support.Teardown('test_find', done);
    });

    it('should select the correct record ', function(done) {
      var wlQuery = {
        where: {
          fieldA: 'foo'
        }
      };

      Adapter.find('test', 'test_find', wlQuery, function(err, results) {
        assert(!err);
        assert(_.isArray(results));
        assert.equal(results.length, 1);
        assert.equal(_.first(results).fieldA, 'foo');
        assert.equal(_.first(results).fieldB, 'bar');

        done();
      });
    });

    it('should return all the records ', function(done) {
      Adapter.find('test', 'test_find', {}, function(err, results) {
        assert(!err);
        assert(_.isArray(results));
        assert.equal(results.length, 2);
        done();
      });
    });

    it('should be case sensitive', function(done) {
      var wlQuery = {
        where: {
          fieldB: 'bAr_2'
        }
      };

      Adapter.find('test', 'test_find', wlQuery, function(err, results) {
        assert(!err);
        assert(_.isArray(results));
        assert.equal(results.length, 1);
        assert.equal(_.first(results).fieldA, 'foo_2');
        assert.equal(_.first(results).fieldB, 'bAr_2');
        done();
      });
    });

    // Look into the bowels of the PG Driver and ensure the Create function handles
    // it's connections properly.
    it('should release it\'s connection when completed', function(done) {
      var manager = Adapter._datastores.test.manager;
      var preConnectionsAvailable = manager.pool.pool.availableObjectsCount();

      Adapter.find('test', 'test_find', {}, function(err) {
        assert(!err);
        var postConnectionsAvailable = manager.pool.pool.availableObjectsCount();
        assert.equal(preConnectionsAvailable, postConnectionsAvailable);
        done();
      });
    });
  });
});
<commit_msg>remove extra space<commit_after>var assert = require('assert');
var _ = require('lodash');
var Adapter = require('../../lib/adapter');
var Support = require('./support/bootstrap');

describe('Unit Tests ::', function() {
  describe('Find', function() {
    // Test Setup
    before(function(done) {
      Support.Setup('test_find', function(err) {
        if (err) {
          return done(err);
        }

        // Seed the database with two simple records.
        Support.Seed('test_find', done);
      });
    });

    after(function(done) {
      Support.Teardown('test_find', done);
    });

    it('should select the correct record', function(done) {
      var wlQuery = {
        where: {
          fieldA: 'foo'
        }
      };

      Adapter.find('test', 'test_find', wlQuery, function(err, results) {
        assert(!err);
        assert(_.isArray(results));
        assert.equal(results.length, 1);
        assert.equal(_.first(results).fieldA, 'foo');
        assert.equal(_.first(results).fieldB, 'bar');

        done();
      });
    });

    it('should return all the records', function(done) {
      Adapter.find('test', 'test_find', {}, function(err, results) {
        assert(!err);
        assert(_.isArray(results));
        assert.equal(results.length, 2);
        done();
      });
    });

    it('should be case sensitive', function(done) {
      var wlQuery = {
        where: {
          fieldB: 'bAr_2'
        }
      };

      Adapter.find('test', 'test_find', wlQuery, function(err, results) {
        assert(!err);
        assert(_.isArray(results));
        assert.equal(results.length, 1);
        assert.equal(_.first(results).fieldA, 'foo_2');
        assert.equal(_.first(results).fieldB, 'bAr_2');
        done();
      });
    });

    // Look into the bowels of the PG Driver and ensure the Create function handles
    // it's connections properly.
    it('should release it\'s connection when completed', function(done) {
      var manager = Adapter._datastores.test.manager;
      var preConnectionsAvailable = manager.pool.pool.availableObjectsCount();

      Adapter.find('test', 'test_find', {}, function(err) {
        assert(!err);
        var postConnectionsAvailable = manager.pool.pool.availableObjectsCount();
        assert.equal(preConnectionsAvailable, postConnectionsAvailable);
        done();
      });
    });
  });
});
<|endoftext|>