<commit_before>import Ember from 'ember';
import SplitChild from './split-child';
import layout from 'ember-split-view/templates/components/split-view';

var computed = Ember.computed;
var observer = Ember.observer;

/**
 * This class represents a view that is split either vertically or horizontally.
 * The split view is composed of three child views: a left or top view, a sash
 * view, and a right or bottom view.  The sash may be dragged to change the
 * relative width or height of the child views.
 *
 * Vertical SplitView example:
 *
 * ```handlebars
 * {{#split-view isVertical=true}}
 *   {{#split-child}}
 *     Content of the left view here.
 *   {{/split-child}}
 *   {{split-sash"}}
 *   {{#split-child}}
 *     Content of the right view here.
 *   {{/split-child}}
 * {{/split-view}}
 * ```
 *
 * Horizontal SplitView example:
 *
 * ```handlebars
 * {{#split-view isVertical=false}}
 *   {{#split-child}}
 *     Content of the top view here.
 *   {{/split-child}}
 *   {{split-sash"}}
 *   {{#split-child}}
 *     Content of the bottom view here.
 *   {{/split-child}}
 * {{/split-view}}
 * ```
 *
 * @cLass SplitViewComponent
 * @extends Ember.Component
 */
export default Ember.Component.extend({
  layout: layout,
  /**
   * @property {boolean} isVertical - the orientation of the split: true = vertical, false = horizontal
   * @default true
   */
  isVertical: true,

  /**
   * @property {Number} splitPosition - the position of the split in pixels
   * @default 50
   */
  splitPosition: 250,

  splits: null,
  isDragging: false,
  isRoot: false,
  classNames: ['split-view'],
  classNameBindings: ['isDragging:dragging', 'isVertical:vertical:horizontal'],

  init: function() {
    this._super();
    this.set('splits', Ember.A());
  },

  didInsertElement: function() {
    this._super.apply(this, arguments);

    var parentView = this.get('parentView');
    var isRoot = !(parentView instanceof SplitChild);

    // run next to avoid changing the component during a render iteration
    Ember.run.next(this, function() {
      this.set('isRoot', isRoot);
      var resizeService = this.get('resizeService');
      if(!isRoot) {
        parentView.set('childSplitView', this);
        if (resizeService)
        {
          resizeService.off('didResize', this, this.didResize);
        }
      }
      else
      {
        // only need width and height on root split-view
        // split-child passes it down the tree for nested ones
        if (resizeService)
        {
          resizeService.on('didResize', this, this.didResize);
        }
      }
      Ember.run.next(this, function() {
        this._setStyle();
      });
      Ember.run.scheduleOnce('afterRender', this, function() {
        // must do this in afterRender so that the parent has calculated its width and height
        var element = this.$();
        this.set('width', element.width());
        this.set('height', element.height());
      });
    });
  },

  willDestroyElement: function() {
    var resizeService = this.get('resizeService');
    if (resizeService) {
      resizeService.off('didResize', this, this.didResize);
    }
  },

  didResize: function() {
    var element = this.$();
    this.set('width', element.width());
    this.set('height', element.height());
    this.constrainSplit();
  },

  _setStyle: function() {
    var style = this.get('element').style;
    if (this.get('isRoot')) {
      // let the DOM know our minimum size
      var isVertical = this.get('isVertical');
      var size = this.get('minSize')+'px';
      if (isVertical) {
        style.minWidth = size;
        style.minHeight = null;
      }
      else {
        style.minWidth = null;
        style.minHeight = size;
      }
    }
    else {
      style.minWidth = null;
      style.minHeight = null;
    }
  },

  styleChanged: observer('isVertical', 'minSize', 'isRoot', function() {
    this._setStyle();
  }),

  addSplit: function(split) {
    var splits = this.get('splits');
    splits.addObject(split);

    if(splits.length === 2) {
      this.updateOrientation();
    }
  },

  removeSplit: function(split) {
    this.get('splits').removeObject(split);
  },

  updateOrientation: observer('isVertical', function() {
    var splits = this.get('splits');
    var leftOrTop = splits.objectAt(0);
    var rightOrBottom = splits.objectAt(1);

    if(this.get('isVertical')) {
      leftOrTop.set('anchorSide', 'right');
      rightOrBottom.set('anchorSide', 'left');
    } else {
      leftOrTop.set('anchorSide', 'bottom');
      rightOrBottom.set('anchorSide', 'top');
    }
  }),

  constrainSplit: observer('sash.width', 'width', 'height', 'isVertical', function() {
    var splits = this.get('splits');
    var leftOrTop = splits.objectAt(0);
    var rightOrBottom = splits.objectAt(1);

    if(leftOrTop) {
      var minLeftOrTopPosition = leftOrTop.get('minSize');

      if(this.get('splitPosition') < minLeftOrTopPosition) {
        this.set('splitPosition', minLeftOrTopPosition);
      }
    }

    var size = this.get('isVertical') ? this.get('width') : this.get('height');
    if (rightOrBottom) {
      var minRightOrBottomPosition = size - rightOrBottom.get('minSize');

      if(this.get('splitPosition') > minRightOrBottomPosition) {
        this.set('splitPosition', minRightOrBottomPosition);
      }
    }
  }),

  minSize: computed('splits.@each.minSize', 'sash.width', function() {
    var result = 0;
    var children = this.get('splits');
    for(var i=0; i < children.length; i++)
    {
      result += children[i].get('minSize');
    }
    result += (children.length-1) * this.get('sash.width');
    return result;
  }),

  mouseUp: function() {
    this.set('isDragging', false);
  },

  mouseLeave: function() {
    this.set('isDragging', false);
  },

  mouseMove: function(event) {
    if(!this.get('isDragging')) {
      return;
    }

    var position;

    var offset = this.$().offset();
    if(this.get('isVertical')) {
      position = event.pageX - offset.left;
    } else {
      position = event.pageY - offset.top;
    }

    this.set('splitPosition', position);
    this.constrainSplit();
  }

});
<commit_msg>adjust split-view<commit_after>/* eslint max-len: 0 */
/* eslint new-cap: ["error", { "capIsNew": false }]*/
import Ember from 'ember';
import SplitChild from './split-child';
import splitViewLayout from 'ember-split-view/templates/components/split-view';

const { computed, observer } = Ember;

/**
 * This class represents a view that is split either vertically or horizontally.
 * The split view is composed of three child views: a left or top view, a sash
 * view, and a right or bottom view.  The sash may be dragged to change the
 * relative width or height of the child views.
 *
 * Vertical SplitView example:
 *
 * ```handlebars
 * {{#split-view isVertical=true}}
 *   {{#split-child}}
 *     Content of the left view here.
 *   {{/split-child}}
 *   {{split-sash"}}
 *   {{#split-child}}
 *     Content of the right view here.
 *   {{/split-child}}
 * {{/split-view}}
 * ```
 *
 * Horizontal SplitView example:
 *
 * ```handlebars
 * {{#split-view isVertical=false}}
 *   {{#split-child}}
 *     Content of the top view here.
 *   {{/split-child}}
 *   {{split-sash"}}
 *   {{#split-child}}
 *     Content of the bottom view here.
 *   {{/split-child}}
 * {{/split-view}}
 * ```
 *
 * @cLass SplitViewComponent
 * @extends Ember.Component
 */
export default Ember.Component.extend({
  layout: splitViewLayout,
  /**
   * @property {boolean} isVertical - the orientation of the split: true = vertical, false = horizontal
   * @default true
   */
  isVertical: true,

  /**
   * @property {Number} splitPosition - the position of the split in pixels
   * @default 50
   */
  splitPosition: 250,

  splits: null,
  isDragging: false,
  isRoot: false,
  classNames: ['split-view'],
  classNameBindings: ['isDragging:dragging', 'isVertical:vertical:horizontal'],

  init() {
    this._super();
    this.set('splits', Ember.A());
  },

  didInsertElement(...args) {
    this._super(...args);

    const parentView = this.get('parentView');
    const isRoot = !(parentView instanceof SplitChild);

    // run next to avoid changing the component during a render iteration
    Ember.run.next(this, () => {
      this.set('isRoot', isRoot);
      const resizeService = this.get('resizeService');

      if (!isRoot) {
        parentView.set('childSplitView', this);
        if (resizeService) {
          resizeService.off('didResize', this, this.didResize);
        }
      } else {
        // only need width and height on root split-view
        // split-child passes it down the tree for nested ones
        if (resizeService) {
          resizeService.on('didResize', this, this.didResize);
        }
      }
      Ember.run.next(this, () => {
        this._setStyle();
      });
      Ember.run.scheduleOnce('afterRender', this, () => {
        // must do this in afterRender so that the parent has calculated its width and height
        const element = this.$();
        this.set('width', element.width());
        this.set('height', element.height());
      });
    });
  },

  willDestroyElement() {
    this._super();
    const resizeService = this.get('resizeService');
    if (resizeService) {
      resizeService.off('didResize', this, this.didResize);
    }
  },

  didResize() {
    const element = this.$();
    this.set('width', element.width());
    this.set('height', element.height());
    this.constrainSplit();
  },

  _setStyle() {
    const style = this.get('element').style;
    if (this.get('isRoot')) {
      // let the DOM know our minimum size
      const isVertical = this.get('isVertical');
      const size = `${this.get('minSize')}px`;
      if (isVertical) {
        style.minWidth = size;
        style.minHeight = null;
      } else {
        style.minWidth = null;
        style.minHeight = size;
      }
    } else {
      style.minWidth = null;
      style.minHeight = null;
    }
  },

  styleChanged: observer('isVertical', 'minSize', 'isRoot',
    function () {
      this._setStyle();
    }
  ),

  addSplit(split) {
    const splits = this.get('splits');
    splits.addObject(split);

    if (splits.length === 2) {
      this.updateOrientation();
    }
  },

  removeSplit(split) {
    this.get('splits').removeObject(split);
  },

  updateOrientation: observer('isVertical',
    function () {
      const splits = this.get('splits');
      const leftOrTop = splits.objectAt(0);
      const rightOrBottom = splits.objectAt(1);

      if (this.get('isVertical')) {
        leftOrTop.set('anchorSide', 'right');
        rightOrBottom.set('anchorSide', 'left');
      } else {
        leftOrTop.set('anchorSide', 'bottom');
        rightOrBottom.set('anchorSide', 'top');
      }
    }
  ),

  constrainSplit: observer('sash.width', 'width', 'height', 'isVertical',
    function () {
      const splits = this.get('splits');
      const leftOrTop = splits.objectAt(0);
      const rightOrBottom = splits.objectAt(1);

      if (leftOrTop) {
        const minLeftOrTopPosition = leftOrTop.get('minSize');

        if (this.get('splitPosition') < minLeftOrTopPosition) {
          this.set('splitPosition', minLeftOrTopPosition);
        }
      }

      const size = this.get('isVertical') ? this.get('width') : this.get('height');
      if (rightOrBottom) {
        const minRightOrBottomPosition = size - rightOrBottom.get('minSize');

        if (this.get('splitPosition') > minRightOrBottomPosition) {
          this.set('splitPosition', minRightOrBottomPosition);
        }
      }
    }
  ),

  minSize: computed('splits.@each.minSize', 'sash.width',
    function () {
      let result = 0;
      const children = this.get('splits');
      for (let i = 0; i < children.length; i += 1) {
        result += children[i].get('minSize');
      }
      result += (children.length - 1) * this.get('sash.width');
      return result;
    }
  ),

  mouseUp() {
    this.set('isDragging', false);
  },

  mouseLeave() {
    this.set('isDragging', false);
  },

  mouseMove(event) {
    if (!this.get('isDragging')) {
      return;
    }

    let position = 0;

    const offset = this.$().offset();
    if (this.get('isVertical')) {
      position = event.pageX - offset.left;
    } else {
      position = event.pageY - offset.top;
    }

    this.set('splitPosition', position);
    this.constrainSplit();
  },

});
<|endoftext|>


<commit_before>let React = require('react');
let DropTarget = require('react-dnd').DropTarget;
let DragSource = require('react-dnd').DragSource;
let findDOMNode = require('react-dom').findDOMNode;
let flow = require('lodash.flow');

let reactstrap = require('reactstrap');
let Modal = reactstrap.Modal;
let ModalHeader = reactstrap.ModalHeader;
let ModalBody = reactstrap.ModalBody;
let ModalFooter = reactstrap.ModalFooter;

import { Creatable } from "react-select";
import { compose, createStore } from "redux";
import { connect, Provider } from "react-redux";
import { combineForms, Form, Control } from "react-redux-form";
import MultiSelect from './multiselect';
import PrefCourseList from './editlistmodule';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const initialUser = {};
const store = createStore(
    combineForms({
        user: initialUser
    })
);

class WillCourseList extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            preLoadOption: this.props.tutorCourse,
            tutorId: this.props.tutorId
        };
    }

    handleSubmit(e){
        console.log(e);
    };

    render() {
        return (

                <Form model="user" onSubmit={this.handleSubmit}>
                    <MultiSelect model="user.category" options={this.state.preLoadOption}
                                 tutorId={this.state.tutorId} isWilling={true}
                                 setCoursesAssigned={this.props.setWillCoursesAssigned.bind(this)}/>
                </Form>

        );
    }
}

const style = {
    border: '3px dashed gray',
    padding: 10,
    margin: '.5rem',
    backgroundColor: 'black',
    cursor: 'move'
};

class Card extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            modal : false,
            saveMessageModal: false,
            card : this.props.card,
            day : this.props.day,
            willCoursesAssigned : [],
            preferCoursesAssigned : [],
        };
    this.toggleMessageModal = this.toggleMessageModal.bind(this);
    this.toggleGridModal = this.toggleGridModal.bind(this);
    this.setPreferCoursesAssigned = this.setPreferCoursesAssigned.bind(this);
    this.setWillCoursesAssigned = this.setWillCoursesAssigned.bind(this);
    this.savePopUp = this.savePopUp.bind(this);
}

    setTutorCourse() {
        console.log("in setTutorCourse");
        let tutorCourse = this.state.preferCoursesAssigned.concat(this.state.willCoursesAssigned);
        console.log("tutorCourse");
        console.log(tutorCourse);
        if (tutorCourse.length > 0) {
            let card = this.state.card;
            card.tutorCourse = tutorCourse;
            console.log("card");
            console.log(card);
            this.props.setCard(this.props.index, card);
            this.toggleMessageModal();
        }
    }

    setWillCoursesAssigned(courses) {
        console.log("in setWillCoursesAssigned");
        console.log("this.state.willCoursesAssigned before");
        console.log(this.state.willCoursesAssigned);
        console.log("courses");
        console.log(courses);
        this.setState({
            willCoursesAssigned: courses
        });
        console.log("this.state.willCoursesAssigned after");
        console.log(this.state.willCoursesAssigned);
    }

    setPreferCoursesAssigned(courses) {
        console.log("in setPreferCoursesAssigned");
        console.log("this.state.preferCoursesAssigned before");
        console.log(this.state.preferCoursesAssigned);
        console.log("courses");
        console.log(courses);
        this.setState({
            preferCoursesAssigned: courses
        });
        console.log("this.state.preferCoursesAssigned after");
        console.log(this.state.preferCoursesAssigned);
    }

    savePopUp() {
        console.log("in save pop up");
        console.log(this.state.preferCoursesAssigned);
        console.log(this.state.willCoursesAssigned);
        this.setTutorCourse();
    }

    toggleGridModal() {
        this.setState({
            modal : ! this.state.modal
        })
    }

    toggleMessageModal() {
        this.setState({
            saveMessageModal: ! this.state.saveMessageModal
        })
    }

	render() {
        const card = this.state.card;
		const { isDragging, connectDragSource, connectDropTarget } = this.props;
		const opacity = isDragging ? 0 : 1;

		let course = [];
		let tutorName = card.tutor.firstName + " " + card.tutor.lastName;
		if (card.tutorCourse.length == 1) {
		    course.push(

                        {card.tutorCourse[0].name}

            );
        }
        else if (card.tutorCourse.length == 2) {
            course.push(

                        {card.tutorCourse[0].name + ", " + card.tutorCourse[1].name}

            );
        }
        else {
		    let tooltip = card.tutorCourse[0].name;
		    for (let index=1; index<card.tutorCourse.length; index++) {
                tooltip = tooltip + ", " + card.tutorCourse[index].name;
            }
		    course.push(

                        {card.tutorCourse[0].name + "...."}

            );
        }

		return connectDragSource(connectDropTarget(

                                {tutorName}

                        {course}

                <Modal isOpen={this.state.modal} toggle={this.toggleGridModal}>
                    <ModalHeader toggle={this.toggleGridModal} >

Shift {this.state.day} of {tutorName}

                    </ModalHeader>
                    <ModalBody>
                        <Provider store={store}>

Add/Delete

Prefer Course List of {tutorName}

                                <PrefCourseList tutorCourse={card.tutorCourse} tutorId={card.tutor.id}
                                                setPreferCoursesAssigned={this.setPreferCoursesAssigned}/>

Willing Course List of {tutorName}

                                <WillCourseList tutorCourse={card.tutorCourse} tutorId={card.tutor.id}
                                                setWillCoursesAssigned={this.setWillCoursesAssigned}/>

                        </Provider>
                    </ModalBody>
                    <ModalFooter>
                        <button type="button" className="btn btn-success btn-block" onClick={this.savePopUp}
                                style={{"textAlign": "center"}} > Save </button>
                    </ModalFooter>

                    <Modal isOpen={this.state.saveMessageModal} toggle={this.toggleMessageModal}>
                        <ModalHeader toggle={this.toggleMessageModal} >

                                Shift {this.state.day} of {tutorName}

                        </ModalHeader>
                        <ModalBody>

 Succesfully Modified

                        </ModalBody>
                    </Modal>
                </Modal>

		));
	}
}

const cardSource = {

	beginDrag(props) {
		return {
			index: props.index,
			listId: props.listId,
			card: props.card
		};
	},

	endDrag(props, monitor) {
		const item = monitor.getItem();
		const dropResult = monitor.getDropResult();

		if ( dropResult && dropResult.listId !== item.listId ) {
			props.removeCard(item.index);
		}
	}
};

const cardTarget = {

	hover(props, monitor, component) {
		const dragIndex = monitor.getItem().index;
		const hoverIndex = props.index;
		const sourceListId = monitor.getItem().listId;

		// Don't replace items with themselves
		if (dragIndex === hoverIndex) {
			return;
		}

		// Determine rectangle on screen
		const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();

		// Get vertical middle
		const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;

		// Determine mouse position
		const clientOffset = monitor.getClientOffset();

		// Get pixels to the top
		const hoverClientY = clientOffset.y - hoverBoundingRect.top;

		// Only perform the move when the mouse has crossed half of the items height
		// When dragging downwards, only move when the cursor is below 50%
		// When dragging upwards, only move when the cursor is above 50%

		// Dragging downwards
		if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
			return;
		}

		// Dragging upwards
		if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
			return;
		}

		// Time to actually perform the action
		if ( props.listId === sourceListId ) {
			props.moveCard(dragIndex, hoverIndex);

			// Note: we're mutating the monitor item here!
			// Generally it's better to avoid mutations,
			// but it's good here for the sake of performance
			// to avoid expensive index searches.
			monitor.getItem().index = hoverIndex;
		}
	}
};

module.exports = flow(
    DropTarget("CARD", cardTarget, connect => ({
        connectDropTarget: connect.dropTarget()
    })),
    DragSource("CARD", cardSource, (connect, monitor) => ({
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging()
    }))
)(Card);
<commit_msg>make edit pop-up disappear upon saving<commit_after>let React = require('react');
let DropTarget = require('react-dnd').DropTarget;
let DragSource = require('react-dnd').DragSource;
let findDOMNode = require('react-dom').findDOMNode;
let flow = require('lodash.flow');

let reactstrap = require('reactstrap');
let Modal = reactstrap.Modal;
let ModalHeader = reactstrap.ModalHeader;
let ModalBody = reactstrap.ModalBody;
let ModalFooter = reactstrap.ModalFooter;

import { Creatable } from "react-select";
import { compose, createStore } from "redux";
import { connect, Provider } from "react-redux";
import { combineForms, Form, Control } from "react-redux-form";
import MultiSelect from './multiselect';
import PrefCourseList from './editlistmodule';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const initialUser = {};
const store = createStore(
    combineForms({
        user: initialUser
    })
);

class WillCourseList extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            preLoadOption: this.props.tutorCourse,
            tutorId: this.props.tutorId
        };
    }

    handleSubmit(e){
        console.log(e);
    };

    render() {
        return (

                <Form model="user" onSubmit={this.handleSubmit}>
                    <MultiSelect model="user.category" options={this.state.preLoadOption}
                                 tutorId={this.state.tutorId} isWilling={true}
                                 setCoursesAssigned={this.props.setWillCoursesAssigned.bind(this)}/>
                </Form>

        );
    }
}

const style = {
    border: '3px dashed gray',
    padding: 10,
    margin: '.5rem',
    backgroundColor: 'black',
    cursor: 'move'
};

class Card extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            modal : false,
            saveMessageModal: false,
            card : this.props.card,
            day : this.props.day,
            willCoursesAssigned : [],
            preferCoursesAssigned : [],
        };
    this.toggleMessageModal = this.toggleMessageModal.bind(this);
    this.toggleGridModal = this.toggleGridModal.bind(this);
    this.setPreferCoursesAssigned = this.setPreferCoursesAssigned.bind(this);
    this.setWillCoursesAssigned = this.setWillCoursesAssigned.bind(this);
    this.savePopUp = this.savePopUp.bind(this);
}

    setTutorCourse() {
        console.log("in setTutorCourse");
        let tutorCourse = this.state.preferCoursesAssigned.concat(this.state.willCoursesAssigned);
        console.log("tutorCourse");
        console.log(tutorCourse);
        if (tutorCourse.length > 0) {
            let card = this.state.card;
            card.tutorCourse = tutorCourse;
            console.log("card");
            console.log(card);
            this.props.setCard(this.props.index, card);
            this.toggleMessageModal();
            this.toggleGridModal();
        }
    }

    setWillCoursesAssigned(courses) {
        console.log("in setWillCoursesAssigned");
        console.log("this.state.willCoursesAssigned before");
        console.log(this.state.willCoursesAssigned);
        console.log("courses");
        console.log(courses);
        this.setState({
            willCoursesAssigned: courses
        });
        console.log("this.state.willCoursesAssigned after");
        console.log(this.state.willCoursesAssigned);
    }

    setPreferCoursesAssigned(courses) {
        console.log("in setPreferCoursesAssigned");
        console.log("this.state.preferCoursesAssigned before");
        console.log(this.state.preferCoursesAssigned);
        console.log("courses");
        console.log(courses);
        this.setState({
            preferCoursesAssigned: courses
        });
        console.log("this.state.preferCoursesAssigned after");
        console.log(this.state.preferCoursesAssigned);
    }

    savePopUp() {
        console.log("in save pop up");
        console.log(this.state.preferCoursesAssigned);
        console.log(this.state.willCoursesAssigned);
        this.setTutorCourse();
    }

    toggleGridModal() {
        this.setState({
            modal : ! this.state.modal
        })
    }

    toggleMessageModal() {
        this.setState({
            saveMessageModal: ! this.state.saveMessageModal
        })
    }

	render() {
        const card = this.state.card;
		const { isDragging, connectDragSource, connectDropTarget } = this.props;
		const opacity = isDragging ? 0 : 1;

		let course = [];
		let tutorName = card.tutor.firstName + " " + card.tutor.lastName;
		if (card.tutorCourse.length == 1) {
		    course.push(

                        {card.tutorCourse[0].name}

            );
        }
        else if (card.tutorCourse.length == 2) {
            course.push(

                        {card.tutorCourse[0].name + ", " + card.tutorCourse[1].name}

            );
        }
        else {
		    let tooltip = card.tutorCourse[0].name;
		    for (let index=1; index<card.tutorCourse.length; index++) {
                tooltip = tooltip + ", " + card.tutorCourse[index].name;
            }
		    course.push(

                        {card.tutorCourse[0].name + "...."}

            );
        }

		return connectDragSource(connectDropTarget(

                                {tutorName}

                        {course}

                <Modal isOpen={this.state.modal} toggle={this.toggleGridModal}>
                    <ModalHeader toggle={this.toggleGridModal} >

Shift {this.state.day} of {tutorName}

                    </ModalHeader>
                    <ModalBody>
                        <Provider store={store}>

Add/Delete

Prefer Course List of {tutorName}

                                <PrefCourseList tutorCourse={card.tutorCourse} tutorId={card.tutor.id}
                                                setPreferCoursesAssigned={this.setPreferCoursesAssigned}/>

Willing Course List of {tutorName}

                                <WillCourseList tutorCourse={card.tutorCourse} tutorId={card.tutor.id}
                                                setWillCoursesAssigned={this.setWillCoursesAssigned}/>

                        </Provider>
                    </ModalBody>
                    <ModalFooter>
                        <button type="button" className="btn btn-success btn-block" onClick={this.savePopUp}
                                style={{"textAlign": "center"}} > Save </button>
                    </ModalFooter>
                </Modal>

                <Modal isOpen={this.state.saveMessageModal} toggle={this.toggleMessageModal}>
                    <ModalHeader toggle={this.toggleMessageModal} >

                            Shift {this.state.day} of {tutorName}

                    </ModalHeader>
                    <ModalBody>

 Succesfully Modified

                    </ModalBody>
                </Modal>

		));
	}
}

const cardSource = {

	beginDrag(props) {
		return {
			index: props.index,
			listId: props.listId,
			card: props.card
		};
	},

	endDrag(props, monitor) {
		const item = monitor.getItem();
		const dropResult = monitor.getDropResult();

		if ( dropResult && dropResult.listId !== item.listId ) {
			props.removeCard(item.index);
		}
	}
};

const cardTarget = {

	hover(props, monitor, component) {
		const dragIndex = monitor.getItem().index;
		const hoverIndex = props.index;
		const sourceListId = monitor.getItem().listId;

		// Don't replace items with themselves
		if (dragIndex === hoverIndex) {
			return;
		}

		// Determine rectangle on screen
		const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();

		// Get vertical middle
		const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;

		// Determine mouse position
		const clientOffset = monitor.getClientOffset();

		// Get pixels to the top
		const hoverClientY = clientOffset.y - hoverBoundingRect.top;

		// Only perform the move when the mouse has crossed half of the items height
		// When dragging downwards, only move when the cursor is below 50%
		// When dragging upwards, only move when the cursor is above 50%

		// Dragging downwards
		if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
			return;
		}

		// Dragging upwards
		if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
			return;
		}

		// Time to actually perform the action
		if ( props.listId === sourceListId ) {
			props.moveCard(dragIndex, hoverIndex);

			// Note: we're mutating the monitor item here!
			// Generally it's better to avoid mutations,
			// but it's good here for the sake of performance
			// to avoid expensive index searches.
			monitor.getItem().index = hoverIndex;
		}
	}
};

module.exports = flow(
    DropTarget("CARD", cardTarget, connect => ({
        connectDropTarget: connect.dropTarget()
    })),
    DragSource("CARD", cardSource, (connect, monitor) => ({
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging()
    }))
)(Card);
<|endoftext|>


<commit_before>/*jslint indent: 2*/
/*global require: true, module: true*/
(function () {
  'use strict';

  module.exports = function (rolledDice, value) {
    var result = [],
      sorted = rolledDice.sort(function (a, b) {
        return a - b;
      }),
      i;
    for (i = 0; i < sorted.length && i < (value / 1); i = i + 1) {
      result.push(sorted[i]);
    }
    return result;
  };

}());

<commit_msg>Update worst-of.js<commit_after>/*jslint indent: 2*/
/*global require: true, module: true*/
(function () {
  'use strict';

  module.exports = function (rolledDice, value) {
    var result = [],
      sorted = rolledDice.sort(function (a, b) {
        return Number(a) - Number(b);
      }),
      i;
    for (i = 0; i < sorted.length && i < (value / 1); i = i + 1) {
      result.push(sorted[i]);
    }
    return result;
  };

}());

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import firebase, { reference, signIn } from '../firebase';
import { pick, map, extend } from 'lodash';
import SubmitMessage from './submit-message.js';
import ClearInput from './clear-input.js';
import LogInButton from './login-button.js';
import LogOutButton from './logout-button.js';
import moment from 'moment';

export default class Application extends Component {
  constructor() {
    super();
    this.state = {
      messages: [],
      newMessage: '',
      user: ''
    };

  } //end of constructor

  componentDidMount(){
    //set state of user here
  } //end of componentDidMount

  handleInputChange(e){
    this.setState({newMessage: e.target.value});
    let submitButton = document.querySelector('.submit-message-button');
    let clearButton = document.querySelector('.clear-message-button');
    if (this.state.newMessage !== '') {
      submitButton.removeAttribute('disabled');
      clearButton.removeAttribute('disabled');
    }

  } //end of handleInputChange

  initFirebase(){ //needs to be called on page load
    this.auth = firebase.auth();
    this.database = firebase.database();
    this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
  } // end of initFirebase

  loadMessages(){
    this.messagesRef = this.database.ref('messages');
    this.messagesRef.off();
  } //end of loadMessages

  onAuthStateChanged(user){ //we need to come back and complete this
    if (user) {
      // this.setState({user: user}); //freezes browser
      let profilePicUrl = user.photoURL;
      let userName = user.displayName;
      let userNameField = document.getElementById('user-name');
      let userPicField = document.getElementById('user-pic');
      let logInButton = document.querySelector('.login-button');
      let logOutButton = document.querySelector('.logout-button');
      userNameField.textContent = userName;
      userPicField.setAttribute('src', profilePicUrl);
      userNameField.removeAttribute('hidden');
      userPicField.removeAttribute('hidden');
      logOutButton.removeAttribute('hidden');
      logInButton.setAttribute('hidden', 'true');
      this.loadMessages();
    } //end of if user is signed in
    else {
      let userNameField = document.getElementById('user-name');
      let userPicField = document.getElementById('user-pic');
      let signOutButton = document.querySelector('.logout-button');
      userNameField.setAttribute('hidden', 'true');
      userPicField.setAttribute('hidden', 'true');
      signOutButton.setAttribute('hidden', 'true');
      //show the log in button of needed

    } //end of else user is signed out
  } //end of onAuthStateChanged

  isUserSignedIn(){
    if (this.auth.currentUser) {
    return true;
    }
  } //end of isUserSignedIn

  saveMessage(){
    // event.preventDefault();
    // let that = this;
    if (this.state.newMessage !== '' && this.isUserSignedIn()) {
      //user is signed in
      let currentUser = this.auth.currentUser;
      let body = this.state.newMessage;
      this.state.messages.push(body);
      this.database.ref('messages').push({
        user: currentUser.displayName,
        body: body,
        photo: currentUser.photoURL,
        time: moment().toString()
      });
      this.setState({newMessage: ''});

    } //end of if statement
  } //end of saveMessage

  signIn(){
    let provider = new firebase.auth.GoogleAuthProvider();
    this.auth.signInWithPopup(provider);
  } //end of signIn

  signOut(){
    this.auth.signOut();
  }

  render(){
    return (

        <LogInButton handleClick={()=>this.signIn()}/>
        <LogOutButton handleClick={()=>this.signOut()}/>
        <input id="message-entry-field" type="text" placeholder="Message" onChange={this.handleInputChange.bind(this)} value={this.state.newMessage}></input>

Count

        <SubmitMessage handleClick={()=>this.saveMessage()}/>
        <ClearInput  />
        <ChatMaster user={this.state.user} messages={this.state.messages}/>

    )
  }

} //end of Application

class ChatMaster extends React.Component {
  constructor(props) {
    super(props);

  } //end of constructor

  render () {
    return (

            {this.props.messages}

 //end of main div
    );
  }
} //end of ChatMaster

module.exports = Application;
<commit_msg>adds shorter reference to push into<commit_after>import React, { Component } from 'react';
import firebase, { reference, signIn } from '../firebase';
import { pick, map, extend } from 'lodash';
import SubmitMessage from './submit-message.js';
import ClearInput from './clear-input.js';
import LogInButton from './login-button.js';
import LogOutButton from './logout-button.js';
import moment from 'moment';

export default class Application extends Component {
  constructor() {
    super();
    this.state = {
      messages: [],
      newMessage: '',
      user: ''
    };

  } //end of constructor

  componentDidMount(){

  } //end of componentDidMount

  handleInputChange(e){
    this.setState({newMessage: e.target.value});
    let submitButton = document.querySelector('.submit-message-button');
    let clearButton = document.querySelector('.clear-message-button');
    if (this.state.newMessage !== '') {
      submitButton.removeAttribute('disabled');
      clearButton.removeAttribute('disabled');
    }

  } //end of handleInputChange

  initFirebase(){ //needs to be called on page load
    this.auth = firebase.auth();
    this.database = firebase.database();
    this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
  } // end of initFirebase

  loadMessages(){
    this.messagesRef = this.database.ref('messages');
    this.messagesRef.off();
  } //end of loadMessages

  onAuthStateChanged(user){ //we need to come back and complete this
    if (user) {
      // this.setState({user: user}); //freezes browser
      let profilePicUrl = user.photoURL;
      let userName = user.displayName;
      let userNameField = document.getElementById('user-name');
      let userPicField = document.getElementById('user-pic');
      let logInButton = document.querySelector('.login-button');
      let logOutButton = document.querySelector('.logout-button');
      userNameField.textContent = userName;
      userPicField.setAttribute('src', profilePicUrl);
      userNameField.removeAttribute('hidden');
      userPicField.removeAttribute('hidden');
      logOutButton.removeAttribute('hidden');
      logInButton.setAttribute('hidden', 'true');
      this.loadMessages();
    } //end of if user is signed in
    else {
      let userNameField = document.getElementById('user-name');
      let userPicField = document.getElementById('user-pic');
      let signOutButton = document.querySelector('.logout-button');
      userNameField.setAttribute('hidden', 'true');
      userPicField.setAttribute('hidden', 'true');
      signOutButton.setAttribute('hidden', 'true');
      //show the log in button of needed

    } //end of else user is signed out
  } //end of onAuthStateChanged

  isUserSignedIn(){
    if (this.auth.currentUser) {
    return true;
    }
  } //end of isUserSignedIn

  saveMessage(){
    // event.preventDefault();
    // let that = this;
    if (this.state.newMessage !== '' && this.isUserSignedIn()) {
      //user is signed in
      let currentUser = this.auth.currentUser;
      let body = this.state.newMessage;
      this.state.messages.push(body);
      reference.push({
        user: currentUser.displayName,
        body: body,
        photo: currentUser.photoURL,
        time: moment().toString()
      });
      this.setState({newMessage: ''});

    } //end of if statement
  } //end of saveMessage

  signIn(){
    let provider = new firebase.auth.GoogleAuthProvider();
    this.auth.signInWithPopup(provider);
  } //end of signIn

  signOut(){
    this.auth.signOut();
  }

  render(){
    return (

        <LogInButton handleClick={()=>this.signIn()}/>
        <LogOutButton handleClick={()=>this.signOut()}/>
        <input id="message-entry-field" type="text" placeholder="Message" onChange={this.handleInputChange.bind(this)} value={this.state.newMessage}></input>

Count

        <SubmitMessage handleClick={()=>this.saveMessage()}/>
        <ClearInput  />
        <ChatMaster user={this.state.user} messages={this.state.messages}/>

    )
  }

} //end of Application

class ChatMaster extends React.Component {
  constructor(props) {
    super(props);

  } //end of constructor

  render () {
    return (

            {this.props.messages}

 //end of main div
    );
  }
} //end of ChatMaster

module.exports = Application;
<|endoftext|>


<commit_before>import Ember from "ember";
import CacheableMixin from "../mixins/cacheable";

window.CachedViews = window.CachedViews || {};
var CachedViews = window.CachedViews;

/**!
 * Destroy the View/Element
 */
function teardownCachedView() {

  //allow view teardown
  this._bustcache = true;

  //remove from global cache
  delete CachedViews[this.elementId];

  //remove reference from controller
  if (this.__keyForId) {
    var viewCache = this.get('controller.__view');
    if (viewCache && viewCache.hasOwnProperty(this.__keyForId)) {
      delete viewCache[this.__keyForId];
    }
  } else {
    this.set('controller.__view', null);
  }

  //teardown the view
  this.destroy();

}

export default Ember.ContainerView.extend({

  tagName : 'cache-container',

  cacheExpires : 900000, //15min

  keyForView : null,

  willDestroy : function () {
    var instance = this.get('currentView');
    var expires = this.get('cacheExpires');

    CachedViews[instance.elementId] = instance;
    if (expires) {
      instance.set('__cacheTimeout', Ember.run.later(instance, teardownCachedView, expires));
    }
    this._super();
  },

  view : null,

  init : function () {

    var keyForView = this.keyForView;

    //get cached view
    var CachedView = this.get('controller.__view');
    if (keyForView && CachedView) {
      CachedView = CachedView[keyForView];
    }

    if (CachedView) {

      if (this.get('cacheExpires')) {
        Ember.run.cancel(CachedView.get('__cacheTimeout'));
      }
      this.set('currentView', CachedView);

      //create normal view
    } else {
      var instance = this.get('view')
        .extend({

          __keyForView : keyForView,

          //rehydrate view
          createElement: function() {
            if (this.__cachedElement) {
              this.element = this.__cachedElement;
              return this;
            }
            return this._super();
          },

          //prevent element teardown
          __cacheElement : function () {
            if (this._bustcache) { return; }
            var element = this.element;
            if (element) {
              element.parentNode.removeChild(element);
              this.__cachedElement = element;
              this.set('element', null);
            }
          }.on('willDestroyElement'),

          //prevent view destruction
          _bustcache : false,
          willDestroy : function () { if (this._bustcache) { this._super(); }},
          destroy : function () { if (this._bustcache) { this._super(); }}

        })
        .create({
          controller : this.get('controller')
        });

      if (this.keyForView) {
        var cache = this.get('controller.__view');
        if (!cache) {
          cache = {};
          this.set('controller.__view', cache);
        }
        cache[this.get(this.keyForView)] = instance;
      } else {
        this.set('controller.__view', instance);
      }
      this.set('currentView', instance);
    }

    return this._super();

  }

});
<commit_msg>fixes up cache-container<commit_after>import Ember from "ember";
import CacheableMixin from "../mixins/cacheable";

window.CachedViews = window.CachedViews || {};
var CachedViews = window.CachedViews;

/**!
 * Destroy the View/Element
 */
function teardownCachedView() {

  //allow view teardown
  this._bustcache = true;

  //remove from global cache
  delete CachedViews[this.elementId];

  //remove reference from controller
  if (this.__keyForId) {
    var viewCache = this.get('controller.__view');
    if (viewCache && viewCache.hasOwnProperty(this.__keyForId)) {
      delete viewCache[this.__keyForId];
    }
  } else {
    this.set('controller.__view', null);
  }

  //teardown the view
  this.destroy();

}

export default Ember.ContainerView.extend({

  tagName : 'cache-container',

  cacheExpires : 900000, //15min

  keyForId : null,

  willDestroy : function () {
    var instance = this.get('currentView');
    var expires = this.get('cacheExpires');

    CachedViews[instance.elementId] = instance;
    if (expires) {
      instance.set('__cacheTimeout', Ember.run.later(instance, teardownCachedView, expires));
    }
    this._super();
  },

  view : null,

  init : function () {

    var keyForId = this.keyForId;

    //get cached view
    var CachedView = this.get('controller.__view');
    if (keyForId && CachedView) {
      CachedView = CachedView[keyForId];
    }

    if (CachedView) {

      if (this.get('cacheExpires')) {
        Ember.run.cancel(CachedView.get('__cacheTimeout'));
      }
      this.set('currentView', CachedView);

      //create normal view
    } else {

      var instance = this.get('view')
        .extend(CacheableMixin)
        .create({
          controller : this.get('controller')
        });

      if (this.keyForId) {
        var cache = this.get('controller.__view');
        if (!cache) {
          cache = {};
          this.set('controller.__view', cache);
        }
        cache[this.get(this.keyForId)] = instance;
      } else {
        this.set('controller.__view', instance);
      }
      this.set('currentView', instance);
    }

    return this._super();

  }

});
<|endoftext|>


<commit_before>import { child, cmd, logicOf, procOf, delay } from "mangojuice-core";
import { runWithTracking } from "mangojuice-test";
import MounterCore from 'mangojuice-react-core';

export default (React, MounterClass, implName) => {
  const AppBlockObj = {
    createModel: (props) => ({
      a: 'test',
      nested: null,
      ...props
    }),
    Logic: class AppBlock {
      children() {
        return { nested: child(AppBlockObj.Logic) };
      }
      @cmd TestAction() {}
      @cmd UpdateModel(name, val) {
        return { [name]: val };
      }
    }
  }

  describe(`React interface view renderer: ${implName}`, () => {
    let containerEl, mounter;
    beforeEach(() => {
      containerEl = document.createElement('div');
      containerEl.id = 'container';
      document.body.appendChild(containerEl);
      mounter = new MounterClass('#container');
    });
    afterEach(() => {
      containerEl.remove();
      mounter.unmount();
    });

    it('shuold render a stateless view of a block', async () => {
      const SimpleView = ({ model }, { Logic }) => (

          {model.a}

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should set name of wrapper stateless view same as org view name', async () => {
      const ChildView = ({ model, prop }, { Logic }) => (

          {model.a}{prop}

      );
      const SimpleView = ({ model }) => (

          <ChildView model={model} prop="test" />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      expect(ChildView.__wrapperFunc.name).toEqual('Logic(ChildView)');
    });

    it('shuold render a statefull view of a block', async () => {
      class SimpleView extends React.Component {
        render() {
          return (

              {this.props.model.a}

          );
        }
      }
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should propagate context to children components of same model', async () => {
      const ChildView = ({ model }, { Logic }) => (

          {model.a}

      );
      const SimpleView = ({ model }) => (

          <ChildView model={model} />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should pass other props with model', async () => {
      const ChildView = ({ model, prop }, { Logic }) => (

          {model.a}{prop}

      );
      const SimpleView = ({ model }) => (

          <ChildView model={model} prop="test" />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('testtest');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should keep context on statefull updated of same model', async () => {
      class ChildView extends React.Component {
        state = { test: '' };
        changeState = () => {
          this.setState({ test: 'state' });
        }
        render() {
          return (

              {this.props.model.a}

                {this.state.test}

          );
        }
      }
      const SimpleView = ({ model }) => (

          <ChildView model={model} prop="test" />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const parentElem = document.getElementById('parent');
      parentElem.click();
      const buttonElem = document.getElementById('button');
      buttonElem.click();

      // For react implementations with async update queue
      await delay(10);

      expect(buttonElem).toBeDefined();
      expect(document.getElementById('model').innerHTML).toEqual('test');
      expect(document.getElementById('button').innerHTML).toEqual('state');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('shuold update view when model changed for stateless', async () => {
      const SimpleView = ({ model }, { Logic }) => (

          {model.a}

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      let buttonElem = document.getElementById('button');
      expect(buttonElem.innerHTML).toEqual('test');
      buttonElem.click();
      await delay(0);

      expect(buttonElem).toBeDefined();
      expect(commandNames).toEqual([ 'AppBlock.UpdateModel' ]);
      expect(buttonElem.innerHTML).toEqual('updated');
    });

    it('shuold update view when model changed for statefull', async () => {
      class SimpleView extends React.Component {
        render() {
          return (

              {this.props.model.a}

          );
        }
      }
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      let buttonElem = document.getElementById('button');
      expect(buttonElem.innerHTML).toEqual('test');
      buttonElem.click();
      await delay(0);

      expect(buttonElem).toBeDefined();
      expect(commandNames).toEqual([ 'AppBlock.UpdateModel' ]);
      expect(buttonElem.innerHTML).toEqual('updated');
    });

    it('shuold provide exec in context for stateless', async () => {
      const SimpleView = ({ model }, { exec, Logic }) => (

          {model.a}

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('shuold provide exec in context for statefull', async () => {
      class SimpleView extends React.Component {
        render() {
          const { exec, Logic } = this.context;
          return (

              {this.props.model.a}

          );
        }
      }
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('shuold reset context even if error occured while re-rendering', async () => {
      const SimpleView = ({ model }, { Logic }) => {
        if (model.a === 'updated') {
          throw new Error('Ooops');
        }
        return (

            {model.a}

        );
      };
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj, expectErrors: true });
      const res = mounter.mount(app.proc, SimpleView);

      let buttonElem = document.getElementById('button');
      expect(buttonElem.innerHTML).toEqual('test');

      const oldContext = { a: 'b' };
      MounterCore.ViewRenderContext.setContext(oldContext);
      buttonElem.click();
      await delay(0);

      expect(buttonElem).toBeDefined();
      expect(commandNames).toEqual([ 'AppBlock.UpdateModel' ]);
      expect(MounterCore.ViewRenderContext.getContext()).toEqual(oldContext);
    });

    it('should render view for nested block', async () => {
      const NestedView = jest.fn(({ model }, { Logic }) => (

          {model.b}
          {model.c}

      ));
      const SimpleView = jest.fn(({ model }) => (

          {model.a}
          {model.nested && <NestedView model={model.nested} />}

      ));
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      await app.proc.exec(logicOf(app.model).UpdateModel('nested', AppBlockObj.createModel({ b: 'nested' })));
      const nestedElem = document.getElementById('nested');
      nestedElem.click();
      await delay(0);

      expect(nestedElem).toBeDefined();
      expect(nestedElem.innerHTML).toEqual('nestedblock');
      expect(commandNames).toEqual([
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel'
      ]);
    });

    it('should updated views of different models independently', async () => {
      const NestedView = jest.fn(({ model }, { Logic }) => (

          {model.b}
          {model.c}

      ));
      const SimpleView = jest.fn(({ model }) => (

          {model.a}
          {model.nested && <NestedView model={model.nested} />}

      ));
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      await app.proc.exec(logicOf(app.model).UpdateModel('nested', AppBlockObj.createModel({ b: 'nested' })));

      const nestedElem = document.getElementById('nested');
      const parentElem = document.getElementById('parent');
      nestedElem.click();

      await app.proc.exec(logicOf(app.model).UpdateModel('a', 'test2'));

      expect(nestedElem).toBeDefined();
      expect(nestedElem.innerHTML).toEqual('nestedblock');
      expect(parentElem.innerHTML).toEqual('test2');
      expect(commandNames).toEqual([
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel'
      ]);
      expect(SimpleView).toHaveBeenCalledTimes(3);
      expect(NestedView).toHaveBeenCalledTimes(2);
    });

    it('should cache command executors while rerendering', async () => {
      class NestedView extends React.Component {
        counter = 0;
        shouldComponentUpdate(nextProps) {
          return (
            nextProps.onClick !== this.props.onClick ||
            nextProps.onPing !== this.props.onPing
          );
        }
        render() {
          this.counter++;
          return {this.counter}
        }
      }
      const SimpleView = ({ model }, { Logic }) => (

          {model.a}
          <NestedView
            onClick={Logic.TestAction}
            onPing={Logic.TestAction('1', {})}
          />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      await app.proc.exec(logicOf(app.model).UpdateModel('a', 'test2'));
      await app.proc.exec(logicOf(app.model).UpdateModel('a', 'test3'));
      const parentElem = document.getElementById('parent');
      const counterElem = document.getElementById('counter');

      expect(parentElem.innerHTML).toEqual('test3');
      expect(counterElem.innerHTML).toEqual('1');
      expect(commandNames).toEqual([
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel'
      ]);
    });

    it('shuold not inject a logic if model prop not provided', async () => {
      const ExternalComponent = ({ children }, { Logic }) => (

{children}{`${Logic}`}

      );
      const OrgExternalComponent = ExternalComponent;
      const SimpleView = ({ model }, { Logic }) => (

          <ExternalComponent>{model.a}</ExternalComponent>

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('
testundefined
');
      expect(OrgExternalComponent).toEqual(ExternalComponent);
    });

    it('shuold provide a way to inject a logic manually', async () => {
      const ExternalComponent = React.injectLogic(({ children }, { Logic }) => (

{children}{typeof Logic.TestAction}

      ));
      const SimpleView = ({ model }, { Logic }) => (

          <ExternalComponent>{model.a}</ExternalComponent>

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('
testfunction
');
    });
  });
};
<commit_msg>fixed preact/inferno tests<commit_after>import { child, cmd, logicOf, procOf, delay } from "mangojuice-core";
import { runWithTracking } from "mangojuice-test";
import MounterCore from 'mangojuice-react-core';

export default (React, MounterClass, implName) => {
  const AppBlockObj = {
    createModel: (props) => ({
      a: 'test',
      nested: null,
      ...props
    }),
    Logic: class AppBlock {
      children() {
        return { nested: child(AppBlockObj.Logic) };
      }
      @cmd TestAction() {}
      @cmd UpdateModel(name, val) {
        return { [name]: val };
      }
    }
  }

  describe(`React interface view renderer: ${implName}`, () => {
    let containerEl, mounter;
    beforeEach(() => {
      containerEl = document.createElement('div');
      containerEl.id = 'container';
      document.body.appendChild(containerEl);
      mounter = new MounterClass('#container');
    });
    afterEach(() => {
      containerEl.remove();
      mounter.unmount();
    });

    it('shuold render a stateless view of a block', async () => {
      const SimpleView = ({ model }, { Logic }) => (

          {model.a}

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should set name of wrapper stateless view same as org view name', async () => {
      const ChildView = ({ model, prop }, { Logic }) => (

          {model.a}{prop}

      );
      const SimpleView = ({ model }) => (

          <ChildView model={model} prop="test" />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      expect(ChildView.__wrapperFunc.name).toEqual('Logic(ChildView)');
    });

    it('shuold render a statefull view of a block', async () => {
      class SimpleView extends React.Component {
        render() {
          return (

              {this.props.model.a}

          );
        }
      }
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should propagate context to children components of same model', async () => {
      const ChildView = ({ model }, { Logic }) => (

          {model.a}

      );
      const SimpleView = ({ model }) => (

          <ChildView model={model} />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should pass other props with model', async () => {
      const ChildView = ({ model, prop }, { Logic }) => (

          {model.a}{prop}

      );
      const SimpleView = ({ model }) => (

          <ChildView model={model} prop="test" />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('testtest');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('should keep context on statefull updated of same model', async () => {
      class ChildView extends React.Component {
        state = { test: '' };
        changeState = () => {
          this.setState({ test: 'state' });
        }
        render() {
          return (

              {this.props.model.a}

                {this.state.test}

          );
        }
      }
      const SimpleView = ({ model }) => (

          <ChildView model={model} prop="test" />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const parentElem = document.getElementById('parent');
      parentElem.click();
      const buttonElem = document.getElementById('button');
      buttonElem.click();

      // For react implementations with async update queue
      await delay(10);

      expect(buttonElem).toBeDefined();
      expect(document.getElementById('model').innerHTML).toEqual('test');
      expect(document.getElementById('button').innerHTML).toEqual('state');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('shuold update view when model changed for stateless', async () => {
      const SimpleView = ({ model }, { Logic }) => (

          {model.a}

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      let buttonElem = document.getElementById('button');
      expect(buttonElem.innerHTML).toEqual('test');
      buttonElem.click();
      await delay(0);

      expect(buttonElem).toBeDefined();
      expect(commandNames).toEqual([ 'AppBlock.UpdateModel' ]);
      expect(buttonElem.innerHTML).toEqual('updated');
    });

    it('shuold update view when model changed for statefull', async () => {
      class SimpleView extends React.Component {
        render() {
          return (

              {this.props.model.a}

          );
        }
      }
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      let buttonElem = document.getElementById('button');
      expect(buttonElem.innerHTML).toEqual('test');
      buttonElem.click();
      await delay(0);

      expect(buttonElem).toBeDefined();
      expect(commandNames).toEqual([ 'AppBlock.UpdateModel' ]);
      expect(buttonElem.innerHTML).toEqual('updated');
    });

    it('shuold provide exec in context for stateless', async () => {
      const SimpleView = ({ model }, { exec, Logic }) => (

          {model.a}

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('shuold provide exec in context for statefull', async () => {
      class SimpleView extends React.Component {
        render() {
          const { exec, Logic } = this.context;
          return (

              {this.props.model.a}

          );
        }
      }
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('test');
      expect(commandNames).toEqual([ 'AppBlock.TestAction' ]);
    });

    it('shuold reset context even if error occured while re-rendering', async () => {
      const SimpleView = ({ model }, { Logic }) => {
        if (model.a === 'updated') {
          throw new Error('Ooops');
        }
        return (

            {model.a}

        );
      };
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj, expectErrors: true });
      const res = mounter.mount(app.proc, SimpleView);

      let buttonElem = document.getElementById('button');
      expect(buttonElem.innerHTML).toEqual('test');

      const oldContext = { a: 'b' };
      MounterCore.ViewRenderContext.setContext(oldContext);
      buttonElem.click();
      await delay(0);

      expect(buttonElem).toBeDefined();
      expect(commandNames).toEqual([ 'AppBlock.UpdateModel' ]);
      expect(MounterCore.ViewRenderContext.getContext()).toEqual(oldContext);
    });

    it('should render view for nested block', async () => {
      const NestedView = jest.fn(({ model }, { Logic }) => (

          {model.b}
          {model.c}

      ));
      const SimpleView = jest.fn(({ model }) => (

          {model.a}
          {model.nested && <NestedView model={model.nested} />}

      ));
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      await app.proc.exec(logicOf(app.model).UpdateModel('nested', AppBlockObj.createModel({ b: 'nested' })));
      const nestedElem = document.getElementById('nested');
      nestedElem.click();
      await delay(0);

      expect(nestedElem).toBeDefined();
      expect(nestedElem.innerHTML).toEqual('nestedblock');
      expect(commandNames).toEqual([
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel'
      ]);
    });

    it('should updated views of different models independently', async () => {
      const NestedView = jest.fn(({ model }, { Logic }) => (

          {model.b}
          {model.c}

      ));
      const SimpleView = jest.fn(({ model }) => (

          {model.a}
          {model.nested && <NestedView model={model.nested} />}

      ));
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      await app.proc.exec(logicOf(app.model).UpdateModel('nested', AppBlockObj.createModel({ b: 'nested' })));

      const nestedElem = document.getElementById('nested');
      const parentElem = document.getElementById('parent');
      nestedElem.click();

      await app.proc.exec(logicOf(app.model).UpdateModel('a', 'test2'));

      expect(nestedElem).toBeDefined();
      expect(nestedElem.innerHTML).toEqual('nestedblock');
      expect(parentElem.innerHTML).toEqual('test2');
      expect(commandNames).toEqual([
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel'
      ]);
      expect(SimpleView).toHaveBeenCalledTimes(3);
      expect(NestedView).toHaveBeenCalledTimes(2);
    });

    it('should cache command executors while rerendering', async () => {
      class NestedView extends React.Component {
        counter = 0;
        shouldComponentUpdate(nextProps) {
          return (
            nextProps.onClick !== this.props.onClick ||
            nextProps.onPing !== this.props.onPing
          );
        }
        render() {
          this.counter++;
          return {this.counter}
        }
      }
      const SimpleView = ({ model }, { Logic }) => (

          {model.a}
          <NestedView
            onClick={Logic.TestAction}
            onPing={Logic.TestAction('1', {})}
          />

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      await app.proc.exec(logicOf(app.model).UpdateModel('a', 'test2'));
      await app.proc.exec(logicOf(app.model).UpdateModel('a', 'test3'));
      const parentElem = document.getElementById('parent');
      const counterElem = document.getElementById('counter');

      expect(parentElem.innerHTML).toEqual('test3');
      expect(counterElem.innerHTML).toEqual('1');
      expect(commandNames).toEqual([
        'AppBlock.UpdateModel',
        'AppBlock.UpdateModel'
      ]);
    });

    it('shuold not inject a logic if model prop not provided', async () => {
      const ExternalComponent = ({ children }, { Logic }) => (

{children}

      );
      const OrgExternalComponent = ExternalComponent;
      const SimpleView = ({ model }, { Logic }) => (

          <ExternalComponent>{model.a}</ExternalComponent>

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('
test
');
      expect(OrgExternalComponent).toEqual(ExternalComponent);
    });

    it('shuold provide a way to inject a logic manually', async () => {
      const ExternalComponent = React.injectLogic(({ children }, { Logic }) => (

{children}{typeof Logic.TestAction}

      ));
      const SimpleView = ({ model }, { Logic }) => (

          <ExternalComponent>{model.a}</ExternalComponent>

      );
      const { app, commandNames } = await runWithTracking({ app: AppBlockObj });
      const res = mounter.mount(app.proc, SimpleView);

      const buttonElem = document.getElementById('button');
      buttonElem.click();

      expect(buttonElem).toBeDefined();
      expect(buttonElem.innerHTML).toEqual('
testfunction
');
    });
  });
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import firebase, { reference, signIn} from '../firebase';
import { pick, map, extend, uniq, filter} from 'lodash';
import SubmitMessage from './submit-message.js';
import ClearInput from './clear-input.js';
import LogInButton from './login-button.js';
import LogOutButton from './logout-button.js';
import SortUp from './sort-up.js';
import SortDown from './sort-down.js';
import moment from 'moment';

export default class Application extends Component {
  constructor() {
    super();
    this.state = {
      messages: [],
      newMessage: '',
      newMessageLength: '',
      user: '',
      submitButtonDisabled: true,
      clearButtonDisabled: true,
      userFilter: ''
    };

  } //end of constructor

  componentDidMount(){
    this.loadMessages();
  } //end of componentDidMount

  clearInputField(){
    document.getElementById('message-entry-field').value = '';
    this.disableButtons();
    this.setState({newMessage: ''});
    this.setState({newMessageLength: ''});
  }

  detectFieldContent(e){
    if (e.target.value !== '') {
      this.enableButtons();
    }
    else {
      this.disableButtons();
      this.setState({newMessageLength: ''});
    }
  }

  disableButtons(){
    this.setState({submitButtonDisabled: true});
    this.setState({clearButtonDisabled: true});
  }

  enableButtons(){
    this.setState({submitButtonDisabled: false});
    this.setState({clearButtonDisabled: false});
  }

  handleInputChange(e){
    this.setState({newMessage: e.target.value});
    if (this.state.newMessage.length > 0) {
      this.setState({newMessageLength: this.state.newMessage.length});
    }
    let submitButton = document.querySelector('.submit-message-button');
    let clearButton = document.querySelector('.clear-message-button');

    if (this.state.newMessage !== '') {
      submitButton.removeAttribute('disabled');
      clearButton.removeAttribute('disabled');
    }

      if (this.state.newMessage.length >= 140) {
      submitButton.setAttribute('disabled', 'true');
    }

  } //end of handleInputChange

  initFirebase(){ //needs to be called on page load
    this.auth = firebase.auth();
    this.database = firebase.database();
    this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
  } // end of initFirebase

  loadMessages(){
    reference.limitToLast(25).on('value', (snapshot) =>  {
      var messagesReturned = this.returnArray(snapshot.val());
      this.setState({
        messages: messagesReturned,
      });
    }); //end of snapshot function
  } //end of loadMessages

  onAuthStateChanged(user){
    const labels = {
      charCountOutput: document.getElementById('character-counter-output'),
      clearMessageButton: document.querySelector('.clear-message-button'),
      email: user.email,
      footerBottomComponent: document.querySelector('.footer-bottom-component'),
      loggedInAs: document.querySelector('.logged-in-as'),
      logInButton: document.querySelector('.login-button'),
      logOutButton: document.querySelector('.logout-button'),
      messageEntryField: document.getElementById('message-entry-field'),
      submitMessageButton: document.querySelector('.submit-message-button'),
      userName: user.displayName
    };

    if (user) {
      //user is logged in
      labels.clearMessageButton.removeAttribute('hidden');
      labels.loggedInAs.textContent = "Logged in as " + labels.userName + " (" + labels.email + ")" + ".";
      labels.logInButton.setAttribute('hidden', 'true');
      labels.logOutButton.removeAttribute('hidden');
      labels.messageEntryField.removeAttribute('hidden');
      labels.submitMessageButton.removeAttribute('hidden');
    } //end of if user is signed in

    else {
    //user is not logged in
    labels.clearMessageButton.setAttribute('hidden', 'true');
    labels.logInButton.removeAttribute('hidden');
    labels.logOutButton.setAttribute('hidden', 'true');
    labels.messageEntryField.setAttribute('hidden', 'true');
    labels.submitMessageButton.setAttribute('hidden', 'true');
    } //end of else user is signed out

  } //end of onAuthStateChanged

  isUserSignedIn(){
    if (this.auth.currentUser) {
    return true;
    }
  } //end of isUserSignedIn

  resetNewMessageState(){
    this.setState({
      newMessage: '',
    });
  } //end of resetNewMessageState

  returnArray(snapshots){
    let array = [];
    if (snapshots) {
      var fullArray = Object.keys(snapshots).map((each)=>{
        var singleMessage = snapshots[each];
        // singleMessage['each'] = each;
        array.push(singleMessage);
      });
    }
    return array;
  } //end of returnArray

  saveMessage(){
    if (this.state.newMessage !== '' && this.isUserSignedIn()) {
      //user is signed in
      let currentUser = this.auth.currentUser;
      let body = this.state.newMessage;
      const newMsgObj = {
        user: currentUser.displayName,
        body: body,
        photo: currentUser.photoURL,
        email: currentUser.email,
        time: moment().format("MMMM D, h:mm a "),
        id: Date.now(),
      };
      reference.push(newMsgObj);
      this.resetNewMessageState();
      this.setStateToUser(currentUser);
      this.disableButtons();
      this.loadMessages();
      this.setState({newMessageLength: ''});
    } //end of if statement
  } //end of saveMessage

  setStateToUser(currentUser){
    this.setState({
      user: currentUser.displayName,
    });
  }

  signIn(){
    let provider = new firebase.auth.GoogleAuthProvider();
    this.auth.signInWithPopup(provider);
    this.setState({logOutButtonClass: 'logout-button'});
  } //end of signIn

  signOut(){
    const warning = confirm("Are you sure you want to log out?");
    if (warning) {
      this.auth.signOut();
      window.location.reload();
    }
  } //end of signOut

  sortDown(){ //most recent at bottom
    this.loadMessages();
    this.sortMostRecentAtBottom();
  } //sortUp

  sortMostRecentAtBottom(){
    this.state.messages.sort((a, b)=>{
      return a.id - b.id;
    });
  }

  sortUp(){ //most recent at top
    this.loadMessages();
    let array = this.state.messages;
    let reversed = array.reverse();
    this.setState({messages: reversed});
  }

  filterUserMessages(user){
    // let array = this.state.messages;
    // let filteredUserMessages =_.filter(array, function(message) {
    //     return message.user === this.state.filteredUser;
    //   });
    // modify this.state to add a filter to the messages array
    console.log(user);
    this.setState(filterUser: user);
    // Rendering messages needs to filter messages based on this.state.filterUser.
    // If this.state.filterUser is the empty string, show all messages. Otherwise,
    // show only the messages for the filtered user
    //find messages based on user that was clicked
    //assign those messages to a new variable
    //display the messages from the user
  }

  render(){
    return (

Shoot the Breeze

          <input id="filter-input-field" type="text" placeholder="Filter"></input>

            <SortUp className="sort-up-button" handleClick={()=>this.sortUp()}/>
            <SortDown className="sort-down-button" handleClick={()=>this.sortDown()}/>

          <ChatMaster messages={this.state.messages}/>

            <LogInButton handleClick={()=>this.signIn()}/>

            <LogOutButton handleClick={()=>this.signOut()}/>
            <input id="message-entry-field" type="text" placeholder="Message" onChange={this.handleInputChange.bind(this)} value={this.state.newMessage} onKeyPress={this.detectFieldContent.bind(this)} onBlur={this.detectFieldContent.bind(this)} hidden></input>

              {this.state.newMessageLength}

              <SubmitMessage handleClick={()=>this.saveMessage()} isDisabled={this.state.submitButtonDisabled}/>
              <ClearInput handleClick={()=>this.clearInputField()} isDisabled={this.state.clearButtonDisabled}/>

    )
  }

} //end of Application

class ChatMaster extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      filteredMssgs: []
    }

  } //end of constructor

  filterMessages(user){
    let newMssgs = this.props.messages.filter((message)=>{
      return message.user === user;
    });
    document.querySelector('.messages').textContent = '';
    this.setState({filteredMssgs: newMssgs});
  }

  showMessages(messages){ //the card for each message
    return(

{messages.time}{messages.user} ({messages.email})

{messages.body}

    )
  }

  render () {
    const { messages, filterUser } = this.props;
    const users = messages.map(message => message.user);
    const uniqueUsers = _.uniq(users);
    return (

{messages.map(this.showMessages)}

{this.state.filteredMssgs.map(this.showMessages)}

Users Present in the Chat Room:

            {uniqueUsers.map(user =>
              <button className="users-present-button" onClick={() => this.filterMessages(user)}>{user}</button>
            )}

 //end of main div
    );
  }
} //end of ChatMaster

module.exports = Application;
<commit_msg>fixes bug with submit<commit_after>import React, { Component } from 'react';
import firebase, { reference, signIn} from '../firebase';
import { pick, map, extend, uniq, filter} from 'lodash';
import SubmitMessage from './submit-message.js';
import ClearInput from './clear-input.js';
import LogInButton from './login-button.js';
import LogOutButton from './logout-button.js';
import SortUp from './sort-up.js';
import SortDown from './sort-down.js';
import moment from 'moment';

export default class Application extends Component {
  constructor() {
    super();
    this.state = {
      messages: [],
      newMessage: '',
      newMessageLength: '',
      user: '',
      submitButtonDisabled: true,
      clearButtonDisabled: true,
      userFilter: ''
    };

  } //end of constructor

  componentDidMount(){
    this.loadMessages();
  } //end of componentDidMount

  clearInputField(){
    document.getElementById('message-entry-field').value = '';
    this.disableButtons();
    this.setState({newMessage: ''});
    this.setState({newMessageLength: ''});
  }

  detectFieldContent(e){
    if (e.target.value !== '') {
      this.enableButtons();
    }
    else {
      this.disableButtons();
      this.setState({newMessageLength: ''});
    }
  }

  disableButtons(){
    this.setState({submitButtonDisabled: true});
    this.setState({clearButtonDisabled: true});
  }

  enableButtons(){
    this.setState({submitButtonDisabled: false});
    this.setState({clearButtonDisabled: false});
  }

  handleInputChange(e){
    this.setState({newMessage: e.target.value});
    if (this.state.newMessage.length > 0) {
      this.setState({newMessageLength: this.state.newMessage.length});
    }
    let submitButton = document.querySelector('.submit-message-button');
    let clearButton = document.querySelector('.clear-message-button');

    if (this.state.newMessage !== '') {
      submitButton.removeAttribute('disabled');
      clearButton.removeAttribute('disabled');
    }

      if (this.state.newMessage.length >= 140) {
      submitButton.setAttribute('disabled', 'true');
    }

  } //end of handleInputChange

  initFirebase(){ //needs to be called on page load
    this.auth = firebase.auth();
    this.database = firebase.database();
    this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
  } // end of initFirebase

  loadMessages(){
    reference.limitToLast(25).on('value', (snapshot) =>  {
      var messagesReturned = this.returnArray(snapshot.val());
      this.setState({
        messages: messagesReturned,
      });
    }); //end of snapshot function
  } //end of loadMessages

  onAuthStateChanged(user){
    const labels = {
      charCountOutput: document.getElementById('character-counter-output'),
      clearMessageButton: document.querySelector('.clear-message-button'),
      email: user.email,
      footerBottomComponent: document.querySelector('.footer-bottom-component'),
      loggedInAs: document.querySelector('.logged-in-as'),
      logInButton: document.querySelector('.login-button'),
      logOutButton: document.querySelector('.logout-button'),
      messageEntryField: document.getElementById('message-entry-field'),
      submitMessageButton: document.querySelector('.submit-message-button'),
      userName: user.displayName
    };

    if (user) {
      //user is logged in
      labels.clearMessageButton.removeAttribute('hidden');
      labels.loggedInAs.textContent = "Logged in as " + labels.userName + " (" + labels.email + ")" + ".";
      labels.logInButton.setAttribute('hidden', 'true');
      labels.logOutButton.removeAttribute('hidden');
      labels.messageEntryField.removeAttribute('hidden');
      labels.submitMessageButton.removeAttribute('hidden');
    } //end of if user is signed in

    else {
    //user is not logged in
    labels.clearMessageButton.setAttribute('hidden', 'true');
    labels.logInButton.removeAttribute('hidden');
    labels.logOutButton.setAttribute('hidden', 'true');
    labels.messageEntryField.setAttribute('hidden', 'true');
    labels.submitMessageButton.setAttribute('hidden', 'true');
    } //end of else user is signed out

  } //end of onAuthStateChanged

  isUserSignedIn(){
    if (this.auth.currentUser) {
    return true;
    }
  } //end of isUserSignedIn

  resetNewMessageState(){
    this.setState({
      newMessage: '',
    });
  } //end of resetNewMessageState

  returnArray(snapshots){
    let array = [];
    if (snapshots) {
      var fullArray = Object.keys(snapshots).map((each)=>{
        var singleMessage = snapshots[each];
        // singleMessage['each'] = each;
        array.push(singleMessage);
      });
    }
    return array;
  } //end of returnArray

  saveMessage(){
    if (this.state.newMessageLength > 0 && this.state.newMessageLength < 140  && this.isUserSignedIn()) {
      //user is signed in
      let currentUser = this.auth.currentUser;
      let body = this.state.newMessage;
      const newMsgObj = {
        user: currentUser.displayName,
        body: body,
        photo: currentUser.photoURL,
        email: currentUser.email,
        time: moment().format("MMMM D, h:mm a "),
        id: Date.now(),
      };
      reference.push(newMsgObj);
      this.resetNewMessageState();
      this.setStateToUser(currentUser);
      this.disableButtons();
      this.loadMessages();
      this.setState({newMessageLength: ''});
    } //end of if statement

  } //end of saveMessage

  setStateToUser(currentUser){
    this.setState({
      user: currentUser.displayName,
    });
  }

  signIn(){
    let provider = new firebase.auth.GoogleAuthProvider();
    this.auth.signInWithPopup(provider);
    this.setState({logOutButtonClass: 'logout-button'});
  } //end of signIn

  signOut(){
    const warning = confirm("Are you sure you want to log out?");
    if (warning) {
      this.auth.signOut();
      window.location.reload();
    }
  } //end of signOut

  sortDown(){ //most recent at bottom
    this.loadMessages();
    this.sortMostRecentAtBottom();
  } //sortUp

  sortMostRecentAtBottom(){
    this.state.messages.sort((a, b)=>{
      return a.id - b.id;
    });
  }

  sortUp(){ //most recent at top
    this.loadMessages();
    let array = this.state.messages;
    let reversed = array.reverse();
    this.setState({messages: reversed});
  }

  filterUserMessages(user){
    // let array = this.state.messages;
    // let filteredUserMessages =_.filter(array, function(message) {
    //     return message.user === this.state.filteredUser;
    //   });
    // modify this.state to add a filter to the messages array
    console.log(user);
    this.setState(filterUser: user);
    // Rendering messages needs to filter messages based on this.state.filterUser.
    // If this.state.filterUser is the empty string, show all messages. Otherwise,
    // show only the messages for the filtered user
    //find messages based on user that was clicked
    //assign those messages to a new variable
    //display the messages from the user
  }

  render(){
    return (

Shoot the Breeze

          <input id="filter-input-field" type="text" placeholder="Filter"></input>

            <SortUp className="sort-up-button" handleClick={()=>this.sortUp()}/>
            <SortDown className="sort-down-button" handleClick={()=>this.sortDown()}/>

          <ChatMaster messages={this.state.messages}/>

            <LogInButton handleClick={()=>this.signIn()}/>

            <LogOutButton handleClick={()=>this.signOut()}/>
            <input id="message-entry-field" type="text" placeholder="Message" onChange={this.handleInputChange.bind(this)} value={this.state.newMessage} onKeyPress={this.detectFieldContent.bind(this)} onBlur={this.detectFieldContent.bind(this)} hidden></input>

              {this.state.newMessageLength}

              <SubmitMessage handleClick={()=>this.saveMessage()} isDisabled={this.state.submitButtonDisabled}/>
              <ClearInput handleClick={()=>this.clearInputField()} isDisabled={this.state.clearButtonDisabled}/>

    )
  }

} //end of Application

class ChatMaster extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      filteredMssgs: []
    }

  } //end of constructor

  filterMessages(user){
    let newMssgs = this.props.messages.filter((message)=>{
      return message.user === user;
    });
    document.querySelector('.messages').textContent = '';
    this.setState({filteredMssgs: newMssgs});
  }

  showMessages(messages){ //the card for each message
    return(

{messages.time}{messages.user} ({messages.email})

{messages.body}

    )
  }

  render () {
    const { messages, filterUser } = this.props;
    const users = messages.map(message => message.user);
    const uniqueUsers = _.uniq(users);
    return (

{messages.map(this.showMessages)}

{this.state.filteredMssgs.map(this.showMessages)}

Users Present in the Chat Room:

            {uniqueUsers.map(user =>
              <button className="users-present-button" onClick={() => this.filterMessages(user)}>{user}</button>
            )}

 //end of main div
    );
  }
} //end of ChatMaster

module.exports = Application;
<|endoftext|>