<commit_before>import React, {PropTypes} from 'react'
import Page from 'components/Page'
import {Modal, Alert, Button, Popover, Overlay} from 'react-bootstrap'
import autobind from 'autobind-decorator'
import moment from 'moment'

import Fieldset from 'components/Fieldset'
import Breadcrumbs from 'components/Breadcrumbs'
import ReportCollection from 'components/ReportCollection'
import CalendarButton from 'components/CalendarButton'
import ButtonToggleGroup from 'components/ButtonToggleGroup'
import Form from 'components/Form'
import History from 'components/History'
import Messages from 'components/Messages'

import API from 'api'

var d3 = null/* required later */

const barColors = {
	cancelled: '#e39394',
	verified: '#9CBDA4',
	unverified: '#F5D98C',
	incoming: '#DA9795',
}

const calendarButtonCss = {
	marginLeft: '20px',
	marginTop: '-8px',
}

const legendCss = {
	width: '14px',
	height: '14px',
	display: 'inline-block',
}

export default class RollupShow extends Page {
	static propTypes = {
		date: React.PropTypes.object,
	}

	static contextTypes = {
		app: PropTypes.object.isRequired,
	}

	get dateStr() { return this.state.date.format('DD MMM YYYY') }
	get dateLongStr() { return this.state.date.format('DD MMMM YYYY') }
	get rollupStart() { return moment(this.state.date).subtract(1, 'days').startOf('day').hour(19) } //7pm yesterday
	get rollupEnd() { return moment(this.state.date).endOf('day').hour(18) } // 6:59:59pm today.

	constructor(props) {
		super(props)

		this.state = {
			date: moment(+props.date || +props.location.query.date || undefined),
			reports: {list: []},
			reportsPageNum: 0,
			graphData: [],
			showEmailModal: false,
			email: {},
			maxReportAge: null,
			hoveredBar: {org: {}},
			orgType: "ADVISOR_ORG",
		}
	}

	componentWillReceiveProps(newProps, newContext) {
		let newDate = moment(+newProps.location.query.date || undefined)
		if (!this.state.date.isSame(newDate)) {
			this.setState({date: newDate}, () => this.loadData(newProps, newContext))
		} else {
			super.componentWillReceiveProps(newProps, newContext)
		}
	}

	componentDidMount() {
		super.componentDidMount()

		if (d3) {
			return
		}

		require.ensure([], () => {
			d3 = require('d3')
			this.forceUpdate()
		})
	}

	fetchData(props, context) {
		let settings = context.app.state.settings
		let maxReportAge = settings.DAILY_ROLLUP_MAX_REPORT_AGE_DAYS
		if (!maxReportAge) {
			//don't run the query unless we've loaded the rollup settings.
			return
		}

		const rollupQuery = {
			state: ['RELEASED'], //Specifically excluding cancelled engagements.
			releasedAtStart: this.rollupStart.valueOf(),
			releasedAtEnd: this.rollupEnd.valueOf(),
			engagementDateStart: moment(this.rollupStart).subtract(maxReportAge, 'days').valueOf(),
			sortBy: "ENGAGEMENT_DATE",
			sortOrder: "DESC",
			pageNum: this.state.reportsPageNum,
		}

		let graphQueryUrl = `/api/reports/rollupGraph?startDate=${rollupQuery.releasedAtStart}&endDate=${rollupQuery.releasedAtEnd}`
		if (this.state.focusedOrg) {
			if (this.state.orgType === 'PRINCIPAL_ORG') {
				rollupQuery.principalOrgId = this.state.focusedOrg.id
				rollupQuery.includePrincipalOrgChildren = true
				graphQueryUrl += `&principalOrganizationId=${this.state.focusedOrg.id}`
			} else {
				rollupQuery.advisorOrgId = this.state.focusedOrg.id
				rollupQuery.includeAdvisorOrgChildren = true
				graphQueryUrl += `&advisorOrganizationId=${this.state.focusedOrg.id}`
			}
		} else if (this.state.orgType) {
			graphQueryUrl += `&orgType=${this.state.orgType}`
		}

		let graphQuery = API.fetch(graphQueryUrl)

		let reportQuery = API.query(/* GraphQL */`
			reportList(f:search, query:$rollupQuery) {
				pageNum, pageSize, totalCount, list {
					${ReportCollection.GQL_REPORT_FIELDS}
				}
			}
		`, {rollupQuery}, '($rollupQuery: ReportSearchQuery)')

		Promise.all([reportQuery, graphQuery]).then(values => {
			this.setState({
				reports: values[0].reportList,
				graphData: values[1]
					.map(d => {d.org = d.org || {id: -1, shortName: "Other"}; return d})
					.sort((a, b) => a.org.shortName - b.org.shortName)
			})
		})
	}

	componentDidUpdate() {
		this.renderGraph()
	}

	render() {
		return (

				<Breadcrumbs items={[[`Rollup for ${this.dateStr}`, 'rollup/']]} />
				<Messages error={this.state.error} success={this.state.success} />

				<Fieldset title={

						Daily Rollup - {this.dateLongStr}
						<CalendarButton onChange={this.changeRollupDate} value={this.state.date.toISOString()} style={calendarButtonCss} />

				} action={

						<Button href={this.emailPreviewUrl()} target="rollup">Print</Button>
						<Button onClick={this.toggleEmailModal} bsStyle="primary">Email rollup</Button>

				}>

Number of reports released today per organization

					<svg ref={el => this.graph = el} style={{width: '100%'}} />

					<Overlay
						show={!!this.state.graphPopover}
						placement="top"
						container={document.body}
						animation={false}
						target={() => this.state.graphPopover}
					>
						<Popover id="graph-popover" title={this.state.hoveredBar.org.shortName}>

Released: {this.state.hoveredBar.released}

Cancelled: {this.state.hoveredBar.cancelled}

Click to drill down

						</Popover>
					</Overlay>

 Released reports:
						{this.state.graphData.reduce((acc, org) => acc + org.released, 0)}

 Cancelled engagements:
						{this.state.graphData.reduce((acc, org) => acc + org.cancelled, 0)}

				</Fieldset>

				<Fieldset
					title={`Reports ${this.state.focusedOrg ? `for ${this.state.focusedOrg.shortName}` : ''}`}
					action={!this.state.focusedOrg
						? <ButtonToggleGroup value={this.state.orgType} onChange={this.changeOrgType}>
							<Button value="ADVISOR_ORG">Advisor organizations</Button>
							<Button value="PRINCIPAL_ORG">Principal organizations</Button>
						</ButtonToggleGroup>
						: <Button onClick={() => this.goToOrg()}>All organizations</Button>
					}
				>
					<ReportCollection paginatedReports={this.state.reports} goToPage={this.goToReportsPage} />
				</Fieldset>

				{this.renderEmailModal()}

		)
	}

	renderGraph() {
		let graphData = this.state.graphData
		if (!graphData || !d3) {
			return
		}

		if (graphData === this.renderedGraph) {
			return
		}

		this.renderedGraph = graphData

		const BAR_HEIGHT = 24
		const BAR_PADDING = 8
		const MARGIN = {top: 0, right: 10, bottom: 20, left: 150}
		let width = this.graph.clientWidth - MARGIN.left - MARGIN.right
		let height = (BAR_HEIGHT + BAR_PADDING) * graphData.length - BAR_PADDING

		let maxNumberOfReports = Math.max.apply(Math, graphData.map(d => d.released + d.cancelled))

		let xScale = d3.scaleLinear()
						.domain([0, maxNumberOfReports])
						.range([0, width])

		let yScale = d3.scaleBand()
						.domain(graphData.map(d => d.org.shortName))
						.range([0, height])

		let graph = d3.select(this.graph)
		graph.selectAll('*').remove()

		graph = graph.attr('width', width + MARGIN.left + MARGIN.right)
					 .attr('height', height + MARGIN.top + MARGIN.bottom)
					 .append('g')
						.attr('transform', `translate(${MARGIN.left}, ${MARGIN.top})`)

		let xAxis = d3.axisBottom(xScale).ticks(Math.min(maxNumberOfReports, 10), 'd')
		let yAxis = d3.axisLeft(yScale)

		graph.append('g').call(yAxis)
		graph.append('g')
				.attr('transform', `translate(0, ${height})`)
				.call(xAxis)

		let bar = graph.selectAll('.bar')
			.data(graphData)
			.enter().append('g')
				.attr('transform', (d, i) => `translate(2, ${i * (BAR_HEIGHT + BAR_PADDING) - 1})`)
				.classed('bar', true)
				.on('click', d => this.goToOrg(d.org))
				.on('mouseenter', d => this.setState({graphPopover: d3.event.target, hoveredBar: d}))
				.on('mouseleave', d =>this.setState({graphPopover: null}))

		bar.append('rect')
				.attr('width', d => d.released && xScale(d.released) - 2)
				.attr('height', BAR_HEIGHT)
				.attr('fill', barColors.verified)

		bar.append('text')
				.attr('x', d => xScale(d.released) - 6)
				.attr('y', BAR_HEIGHT / 2)
				.attr('dy', '.35em')
				.style('text-anchor', 'end')
				.text(d => d.released || '')

		bar.append('rect')
				.attr('x', d => d.released && xScale(d.released) - 2)
				.attr('width', d => d.cancelled && (xScale(d.cancelled) - (d.released ? 0 : 2)))
				.attr('height', BAR_HEIGHT)
				.attr('fill', barColors.cancelled)

		bar.append('text')
				.attr('x', d => xScale(d.released) + xScale(d.cancelled) - 6)
				.attr('y', BAR_HEIGHT / 2)
				.attr('dy', '.35em')
				.style('text-anchor', 'end')
				.text(d => d.cancelled || '')
	}

	@autobind
	goToReportsPage(newPageNum) {
		this.state.reportsPageNum = newPageNum
		this.loadData()
	}

	@autobind
	goToOrg(org) {
		this.setState({reportsPageNum: 0, focusedOrg: org, graphPopover: null}, () => this.loadData())
	}

	@autobind
	changeOrgType(orgType) {
		this.setState({orgType}, () => this.loadData())
	}

	@autobind
	changeRollupDate(newDate) {
		let date = moment(newDate)
		History.replace({pathname: 'rollup', query: {date: date.valueOf()}})
	}

	@autobind
	renderEmailModal() {
		let email = this.state.email
		return <Modal show={this.state.showEmailModal} onHide={this.toggleEmailModal}>
			<Form formFor={email} onChange={this.onChange} submitText={false} >
				<Modal.Header closeButton>
					<Modal.Title>Email rollup - {this.dateStr}</Modal.Title>
				</Modal.Header>

				<Modal.Body>

						{this.state.focusedOrg ?
							`Reports for ${this.state.focusedOrg.shortName}` :
							`All reports by ${this.state.orgType.replace('_', ' ').toLowerCase()}`
						}

					{email.errors &&
						<Alert bsStyle="danger">{email.errors}</Alert>
					}

					<Form.Field id="to" />
					<Form.Field componentClass="textarea" id="comment" />
				</Modal.Body>

				<Modal.Footer>
					Preview
					<Button bsStyle="primary" onClick={this.emailRollup}>Send email</Button>
				</Modal.Footer>
			</Form>
		</Modal>
	}

	@autobind
	toggleEmailModal() {
		this.setState({showEmailModal: !this.state.showEmailModal})
	}

	emailPreviewUrl() {
		return `/api/reports/rollup?startDate=${this.rollupStart.valueOf()}&endDate=${this.rollupEnd.valueOf()}`
	}

	@autobind
	emailRollup() {
		let email = this.state.email
		if (!email.to) {
			email.errors = 'You must select a person to send this to'
			this.setState({email})
			return
		}

		email = {
			toAddresses: email.to.replace(/\s/g, '').split(/[,;]/),
			comment: email.comment
		}

		API.send(`/api/reports/rollup/email?startDate=${this.rollupStart.valueOf()}&endDate=${this.rollupEnd.valueOf()}`, email).then (() =>
			this.setState({
				success: 'Email successfully sent',
				showEmailModal: false,
				email: {}
			})
		)
	}
}
<commit_msg>Change colors on daily rollup.<commit_after>import React, {PropTypes} from 'react'
import Page from 'components/Page'
import {Modal, Alert, Button, Popover, Overlay} from 'react-bootstrap'
import autobind from 'autobind-decorator'
import moment from 'moment'

import Fieldset from 'components/Fieldset'
import Breadcrumbs from 'components/Breadcrumbs'
import ReportCollection from 'components/ReportCollection'
import CalendarButton from 'components/CalendarButton'
import ButtonToggleGroup from 'components/ButtonToggleGroup'
import Form from 'components/Form'
import History from 'components/History'
import Messages from 'components/Messages'

import API from 'api'

var d3 = null/* required later */

const barColors = {
	cancelled: '#EC971F',
	verified: '#337AB7',
}

const calendarButtonCss = {
	marginLeft: '20px',
	marginTop: '-8px',
}

const legendCss = {
	width: '14px',
	height: '14px',
	display: 'inline-block',
}

export default class RollupShow extends Page {
	static propTypes = {
		date: React.PropTypes.object,
	}

	static contextTypes = {
		app: PropTypes.object.isRequired,
	}

	get dateStr() { return this.state.date.format('DD MMM YYYY') }
	get dateLongStr() { return this.state.date.format('DD MMMM YYYY') }
	get rollupStart() { return moment(this.state.date).subtract(1, 'days').startOf('day').hour(19) } //7pm yesterday
	get rollupEnd() { return moment(this.state.date).endOf('day').hour(18) } // 6:59:59pm today.

	constructor(props) {
		super(props)

		this.state = {
			date: moment(+props.date || +props.location.query.date || undefined),
			reports: {list: []},
			reportsPageNum: 0,
			graphData: [],
			showEmailModal: false,
			email: {},
			maxReportAge: null,
			hoveredBar: {org: {}},
			orgType: "ADVISOR_ORG",
		}
	}

	componentWillReceiveProps(newProps, newContext) {
		let newDate = moment(+newProps.location.query.date || undefined)
		if (!this.state.date.isSame(newDate)) {
			this.setState({date: newDate}, () => this.loadData(newProps, newContext))
		} else {
			super.componentWillReceiveProps(newProps, newContext)
		}
	}

	componentDidMount() {
		super.componentDidMount()

		if (d3) {
			return
		}

		require.ensure([], () => {
			d3 = require('d3')
			this.forceUpdate()
		})
	}

	fetchData(props, context) {
		let settings = context.app.state.settings
		let maxReportAge = settings.DAILY_ROLLUP_MAX_REPORT_AGE_DAYS
		if (!maxReportAge) {
			//don't run the query unless we've loaded the rollup settings.
			return
		}

		const rollupQuery = {
			state: ['RELEASED'], //Specifically excluding cancelled engagements.
			releasedAtStart: this.rollupStart.valueOf(),
			releasedAtEnd: this.rollupEnd.valueOf(),
			engagementDateStart: moment(this.rollupStart).subtract(maxReportAge, 'days').valueOf(),
			sortBy: "ENGAGEMENT_DATE",
			sortOrder: "DESC",
			pageNum: this.state.reportsPageNum,
		}

		let graphQueryUrl = `/api/reports/rollupGraph?startDate=${rollupQuery.releasedAtStart}&endDate=${rollupQuery.releasedAtEnd}`
		if (this.state.focusedOrg) {
			if (this.state.orgType === 'PRINCIPAL_ORG') {
				rollupQuery.principalOrgId = this.state.focusedOrg.id
				rollupQuery.includePrincipalOrgChildren = true
				graphQueryUrl += `&principalOrganizationId=${this.state.focusedOrg.id}`
			} else {
				rollupQuery.advisorOrgId = this.state.focusedOrg.id
				rollupQuery.includeAdvisorOrgChildren = true
				graphQueryUrl += `&advisorOrganizationId=${this.state.focusedOrg.id}`
			}
		} else if (this.state.orgType) {
			graphQueryUrl += `&orgType=${this.state.orgType}`
		}

		let graphQuery = API.fetch(graphQueryUrl)

		let reportQuery = API.query(/* GraphQL */`
			reportList(f:search, query:$rollupQuery) {
				pageNum, pageSize, totalCount, list {
					${ReportCollection.GQL_REPORT_FIELDS}
				}
			}
		`, {rollupQuery}, '($rollupQuery: ReportSearchQuery)')

		Promise.all([reportQuery, graphQuery]).then(values => {
			this.setState({
				reports: values[0].reportList,
				graphData: values[1]
					.map(d => {d.org = d.org || {id: -1, shortName: "Other"}; return d})
					.sort((a, b) => a.org.shortName - b.org.shortName)
			})
		})
	}

	componentDidUpdate() {
		this.renderGraph()
	}

	render() {
		return (

				<Breadcrumbs items={[[`Rollup for ${this.dateStr}`, 'rollup/']]} />
				<Messages error={this.state.error} success={this.state.success} />

				<Fieldset title={

						Daily Rollup - {this.dateLongStr}
						<CalendarButton onChange={this.changeRollupDate} value={this.state.date.toISOString()} style={calendarButtonCss} />

				} action={

						<Button href={this.emailPreviewUrl()} target="rollup">Print</Button>
						<Button onClick={this.toggleEmailModal} bsStyle="primary">Email rollup</Button>

				}>

Number of reports released today per organization

					<svg ref={el => this.graph = el} style={{width: '100%'}} />

					<Overlay
						show={!!this.state.graphPopover}
						placement="top"
						container={document.body}
						animation={false}
						target={() => this.state.graphPopover}
					>
						<Popover id="graph-popover" title={this.state.hoveredBar.org.shortName}>

Released: {this.state.hoveredBar.released}

Cancelled: {this.state.hoveredBar.cancelled}

Click to drill down

						</Popover>
					</Overlay>

 Released reports:
						{this.state.graphData.reduce((acc, org) => acc + org.released, 0)}

 Cancelled engagements:
						{this.state.graphData.reduce((acc, org) => acc + org.cancelled, 0)}

				</Fieldset>

				<Fieldset
					title={`Reports ${this.state.focusedOrg ? `for ${this.state.focusedOrg.shortName}` : ''}`}
					action={!this.state.focusedOrg
						? <ButtonToggleGroup value={this.state.orgType} onChange={this.changeOrgType}>
							<Button value="ADVISOR_ORG">Advisor organizations</Button>
							<Button value="PRINCIPAL_ORG">Principal organizations</Button>
						</ButtonToggleGroup>
						: <Button onClick={() => this.goToOrg()}>All organizations</Button>
					}
				>
					<ReportCollection paginatedReports={this.state.reports} goToPage={this.goToReportsPage} />
				</Fieldset>

				{this.renderEmailModal()}

		)
	}

	renderGraph() {
		let graphData = this.state.graphData
		if (!graphData || !d3) {
			return
		}

		if (graphData === this.renderedGraph) {
			return
		}

		this.renderedGraph = graphData

		const BAR_HEIGHT = 24
		const BAR_PADDING = 8
		const MARGIN = {top: 0, right: 10, bottom: 20, left: 150}
		let width = this.graph.clientWidth - MARGIN.left - MARGIN.right
		let height = (BAR_HEIGHT + BAR_PADDING) * graphData.length - BAR_PADDING

		let maxNumberOfReports = Math.max.apply(Math, graphData.map(d => d.released + d.cancelled))

		let xScale = d3.scaleLinear()
						.domain([0, maxNumberOfReports])
						.range([0, width])

		let yScale = d3.scaleBand()
						.domain(graphData.map(d => d.org.shortName))
						.range([0, height])

		let graph = d3.select(this.graph)
		graph.selectAll('*').remove()

		graph = graph.attr('width', width + MARGIN.left + MARGIN.right)
					 .attr('height', height + MARGIN.top + MARGIN.bottom)
					 .append('g')
						.attr('transform', `translate(${MARGIN.left}, ${MARGIN.top})`)

		let xAxis = d3.axisBottom(xScale).ticks(Math.min(maxNumberOfReports, 10), 'd')
		let yAxis = d3.axisLeft(yScale)

		graph.append('g').call(yAxis)
		graph.append('g')
				.attr('transform', `translate(0, ${height})`)
				.call(xAxis)

		let bar = graph.selectAll('.bar')
			.data(graphData)
			.enter().append('g')
				.attr('transform', (d, i) => `translate(2, ${i * (BAR_HEIGHT + BAR_PADDING) - 1})`)
				.classed('bar', true)
				.on('click', d => this.goToOrg(d.org))
				.on('mouseenter', d => this.setState({graphPopover: d3.event.target, hoveredBar: d}))
				.on('mouseleave', d =>this.setState({graphPopover: null}))

		bar.append('rect')
				.attr('width', d => d.released && xScale(d.released) - 2)
				.attr('height', BAR_HEIGHT)
				.attr('fill', barColors.verified)

		bar.append('text')
				.attr('x', d => xScale(d.released) - 6)
				.attr('y', BAR_HEIGHT / 2)
				.attr('dy', '.35em')
				.style('text-anchor', 'end')
				.text(d => d.released || '')

		bar.append('rect')
				.attr('x', d => d.released && xScale(d.released) - 2)
				.attr('width', d => d.cancelled && (xScale(d.cancelled) - (d.released ? 0 : 2)))
				.attr('height', BAR_HEIGHT)
				.attr('fill', barColors.cancelled)

		bar.append('text')
				.attr('x', d => xScale(d.released) + xScale(d.cancelled) - 6)
				.attr('y', BAR_HEIGHT / 2)
				.attr('dy', '.35em')
				.style('text-anchor', 'end')
				.text(d => d.cancelled || '')
	}

	@autobind
	goToReportsPage(newPageNum) {
		this.state.reportsPageNum = newPageNum
		this.loadData()
	}

	@autobind
	goToOrg(org) {
		this.setState({reportsPageNum: 0, focusedOrg: org, graphPopover: null}, () => this.loadData())
	}

	@autobind
	changeOrgType(orgType) {
		this.setState({orgType}, () => this.loadData())
	}

	@autobind
	changeRollupDate(newDate) {
		let date = moment(newDate)
		History.replace({pathname: 'rollup', query: {date: date.valueOf()}})
	}

	@autobind
	renderEmailModal() {
		let email = this.state.email
		return <Modal show={this.state.showEmailModal} onHide={this.toggleEmailModal}>
			<Form formFor={email} onChange={this.onChange} submitText={false} >
				<Modal.Header closeButton>
					<Modal.Title>Email rollup - {this.dateStr}</Modal.Title>
				</Modal.Header>

				<Modal.Body>

						{this.state.focusedOrg ?
							`Reports for ${this.state.focusedOrg.shortName}` :
							`All reports by ${this.state.orgType.replace('_', ' ').toLowerCase()}`
						}

					{email.errors &&
						<Alert bsStyle="danger">{email.errors}</Alert>
					}

					<Form.Field id="to" />
					<Form.Field componentClass="textarea" id="comment" />
				</Modal.Body>

				<Modal.Footer>
					Preview
					<Button bsStyle="primary" onClick={this.emailRollup}>Send email</Button>
				</Modal.Footer>
			</Form>
		</Modal>
	}

	@autobind
	toggleEmailModal() {
		this.setState({showEmailModal: !this.state.showEmailModal})
	}

	emailPreviewUrl() {
		return `/api/reports/rollup?startDate=${this.rollupStart.valueOf()}&endDate=${this.rollupEnd.valueOf()}`
	}

	@autobind
	emailRollup() {
		let email = this.state.email
		if (!email.to) {
			email.errors = 'You must select a person to send this to'
			this.setState({email})
			return
		}

		email = {
			toAddresses: email.to.replace(/\s/g, '').split(/[,;]/),
			comment: email.comment
		}

		API.send(`/api/reports/rollup/email?startDate=${this.rollupStart.valueOf()}&endDate=${this.rollupEnd.valueOf()}`, email).then (() =>
			this.setState({
				success: 'Email successfully sent',
				showEmailModal: false,
				email: {}
			})
		)
	}
}
<|endoftext|>


<commit_before>App.Router = Ember.Router.extend({
  location: 'hash',

  root: Em.Route.extend({
    contacts: Em.Route.extend({
      route: '/',

      showContact: function(router, event) {
        router.transitionTo('contacts.contact.index', event.context);
      },

      showNewContact: function(router) {
        router.transitionTo('contacts.newContact', {});
      },

      connectOutlets: function(router) {
        router.get('applicationController').connectOutlet('contacts');
      },

      index: Em.Route.extend({
        route: '/',

        connectOutlets: function(router) {
          router.get('applicationController').connectOutlet('contacts');
        }
      }),

      newContact: Em.Route.extend({
        route: '/contacts/new',

        cancelEdit: function(router) {
          router.transitionTo('contacts.index');
        },

        connectOutlets: function(router) {
          router.get('contactsController').connectOutlet('editContact', {});
          router.get('editContactController').enterEditing();
        },

        exit: function(router) {
          router.get('editContactController').exitEditing();
        }
      }),

      contact: Em.Route.extend({
        route: '/contacts/:id',

        connectOutlets: function(router, context) {
          router.get('contactsController').connectOutlet('contact', context);
        },

        serialize: function(router, context){
          return {id: context.get('id')};
        },

        deserialize: function(router, params){
          return App.store.find(App.Contact, params.id);
        },

        index: Em.Route.extend({
          route: '/',

          showEdit: function(router) {
            router.transitionTo('contacts.contact.edit');
          },

          connectOutlets: function(router, context) {
            router.get('contactController').connectOutlet('showContact');
          }
        }),

        edit: Em.Route.extend({
          route: 'edit',

          cancelEdit: function(router) {
            router.transitionTo('contacts.contact.index');
          },

          connectOutlets: function(router) {
            var contactController = router.get('contactController');
            contactController.connectOutlet('editContact', contactController.get('content'));
            router.get('editContactController').enterEditing();
          },

          exit: function(router) {
            router.get('editContactController').exitEditing();
          }
        })
      })
    })
  })
});<commit_msg>serialize / deserialize not needed when the route specifies :contact_id param<commit_after>App.Router = Ember.Router.extend({
  location: 'hash',

  root: Em.Route.extend({
    contacts: Em.Route.extend({
      route: '/',

      showContact: function(router, event) {
        router.transitionTo('contacts.contact.index', event.context);
      },

      showNewContact: function(router) {
        router.transitionTo('contacts.newContact', {});
      },

      connectOutlets: function(router) {
        router.get('applicationController').connectOutlet('contacts');
      },

      index: Em.Route.extend({
        route: '/',

        connectOutlets: function(router) {
          router.get('applicationController').connectOutlet('contacts');
        }
      }),

      newContact: Em.Route.extend({
        route: '/contacts/new',

        cancelEdit: function(router) {
          router.transitionTo('contacts.index');
        },

        connectOutlets: function(router) {
          router.get('contactsController').connectOutlet('editContact', {});
          router.get('editContactController').enterEditing();
        },

        exit: function(router) {
          router.get('editContactController').exitEditing();
        }
      }),

      contact: Em.Route.extend({
        route: '/contacts/:contact_id',

        connectOutlets: function(router, context) {
          router.get('contactsController').connectOutlet('contact', context);
        },

        index: Em.Route.extend({
          route: '/',

          showEdit: function(router) {
            router.transitionTo('contacts.contact.edit');
          },

          connectOutlets: function(router, context) {
            router.get('contactController').connectOutlet('showContact');
          }
        }),

        edit: Em.Route.extend({
          route: 'edit',

          cancelEdit: function(router) {
            router.transitionTo('contacts.contact.index');
          },

          connectOutlets: function(router) {
            var contactController = router.get('contactController');
            contactController.connectOutlet('editContact', contactController.get('content'));
            router.get('editContactController').enterEditing();
          },

          exit: function(router) {
            router.get('editContactController').exitEditing();
          }
        })
      })
    })
  })
});<|endoftext|>


<commit_before>$(document).ready(function () {

    const conn = new WebSocket('ws://localhost:8080');
    let localPlayerName;

    const reorderBoardCardZIndex = function () {
        const $cards = $('#board').find('.card');
        $cards.each(function () {
            const $card = $(this);
            $card.css('z-index', parseInt($card.css('left')) + 1000);
        });
    };

    const dragStop = function (event, ui) {
        const $card = ui.draggable;
        const $parent = $card.parent();

        if ($parent.attr('id') != 'board') {
            return;
        }

        const left = ((parseInt($card.css('left')) + 50) / $parent[0].clientWidth) * 100;
        const top = ((parseInt($card.css('top')) + 70) / $parent[0].clientHeight) * 100;
        conn.send('move;' + $card.data('id') + ';' + left + ';' + top);

        reorderBoardCardZIndex();
    };

    const refreshMovable = function () {
        $(".movable").draggable({
            start: function() {
                $(this).css('z-index', 5000);
            },
            stop: function (event, ui) {
                $.extend(ui, {draggable: $(this)});
                dragStop(event, ui);
            }
        });
    };

    const tabCardAccordingToAttribute = function ($card) {
        if ($card.data('tabbed')) {
            $card.css('transform', 'rotate(90deg)');
        } else {
            $card.css('transform', 'rotate(0deg)');
        }
    };

    const refreshCommonCardEvents = function () {
        $('.commoncard').dblclick(function () {
            const $card = $(this);
            if ($card.data('tabbed')) {
                $card.data('tabbed', false);
            } else {
                $card.data('tabbed', true);
            }
            tabCardAccordingToAttribute($card);
            conn.send('tab;' + $card.data('id'));
        });
    };

    const addCardToBoard = function (code, id, type) {
        const $board = $('#board');
        const $newCard = $('');
        $newCard.attr('id', 'card-' + id);
        $newCard.data('id', id);
        $newCard.data('tabbed', false);
        $newCard.appendTo($board);
        refreshCommonCardEvents();
        refreshMovable();
        reorderBoardCardZIndex();

        return $newCard;
    };

    const putCardOnDiscardPile = function ($card) {
        // Cards on discard pile can never be own cards
        if ($card.hasClass('owncard')) {
            $card.removeClass('owncard');
            $card.addClass('commoncard');
        }
        // Disable handling
        $card.removeClass('movable');
        $card.draggable('disable');
        $card.unbind('dblclick');
        // Visuals
        $card.appendTo('#discardPile');
        $card.css('left', '30px');
        $card.css('top', '10px');

        reorderBoardCardZIndex();
    };

    const askForName = function() {
        const name = prompt('name?');
        if (name) {
            return name;
        }
        return askForName();
    };

    conn.onopen = function () {
        console.log("Connection established!");

        localPlayerName = askForName();
        conn.send('name;' + localPlayerName);
    };

    conn.onmessage = function (e) {
        console.log('message received: ' + e.data);
        let payload = e.data.split(';');
        const command = payload[0];
        payload.splice(0, 1);

        const $opposingHand = $('#opposingHand');

        switch (command) {
            case 'lobby': {
                const $playerList = $('#playerList');
                $playerList.html('');
                for (let name of payload) {
                    name = $('
').html(name);
                    name.appendTo($playerList);
                }
                if (payload.length == 2) {
                    $('#startButton').show();
                }
                break;
            }
            case 'game': {
                if (payload == 'start') {
                    $('#lobby').hide();
                    $('#game').show();
                }
                if (payload == 'end') {
                    alert('The game has ended. You will now be redirected to the lobby.');
                    window.location.href = '/';
                }
                break;
            }
            case 'show': {
                $opposingHand.find('.opposingcard')[0].remove();
                addCardToBoard(payload[1], payload[0], 'commoncard');
                break;
            }
            case 'move': {
                const $cardToMove = $('#card-' + payload[0]);
                $cardToMove.css('left', 'calc(' + payload[1] + '% - 50px)');
                $cardToMove.css('top', 'calc(' + payload[2] + '% - 70px)');
                reorderBoardCardZIndex();
                break;
            }
            case 'tab': {
                const $cardToTab = $('#card-' + payload[0]);
                $cardToTab.data('tabbed', payload[1] == true);
                tabCardAccordingToAttribute($cardToTab);
                break;
            }
            case 'packsize': {
                if (payload[0] == 0) {
                    $('#pile').hide();
                }
                break;
            }
            case 'discardsize': {
                $('#discardCounter').text(payload[0]);
                break;
            }
            case 'clearDiscardPile': {
                $('#discardCounter').text(0);
                $('#discardPile').find('.card').remove();
                break;
            }
            case 'draw': {
                if (payload[0] == 'opposing') {
                    const $opposingCard = $('');
                    $opposingCard.appendTo($opposingHand);
                    break;
                }
                const $ownHand = $('#ownHand');
                const $newCard = addCardToBoard(payload[1], payload[0], 'owncard');
                $newCard.css('top', $ownHand.position().top + 'px');

                const $ownCards = $('.owncard');
                if ($ownCards.length > 1) {
                    let mostRight;
                    $ownCards.each(function (index, card) {
                        const $card = $(card);
                        if (mostRight == null || $card.position().left > mostRight.position().left) {
                            mostRight = $card;
                        }
                    });

                    $newCard.css('left', (mostRight.position().left + 50) + 'px');
                }

                refreshMovable();
                reorderBoardCardZIndex();
                break;
            }
            case 'discard': {
                //noinspection JSJQueryEfficiency
                let $cardToDiscard = $('#card-' + payload[0]);
                // Card was on board and was not discarded directly from hand
                if ($cardToDiscard.length > 0) {
                    putCardOnDiscardPile($cardToDiscard);
                } else {
                    addCardToBoard(payload[1], payload[0], 'commoncard');
                    $cardToDiscard = $('#card-' + payload[0]);
                    putCardOnDiscardPile($cardToDiscard);
                    $opposingHand.find('.opposingcard')[0].remove();
                }
                break;
            }
            case 'chat': {
                let now = new Date();
                let prefix = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds() + ' ';
                $('

').text(prefix + payload.join(';')).appendTo('#messages');
                let $messages = $('#messages');
                $messages.scrollTop($messages[0].scrollHeight);
                break;
            }
            case 'currentPlayer': {
                let $status = $('#status');
                let $content = $('');
                if (payload[0] == localPlayerName) {
                    $content.text('Your turn, ' + localPlayerName + '! ');
                    $('').text('Done').click(function() {
                        conn.send('endTurn');
                    }).appendTo($content);
                    $status.addClass('ownTurn');
                    $status.removeClass('opposingTurn');
                } else {
                    $content.text(payload[0] + 's turn. ');
                    $status.addClass('opposingTurn');
                    $status.removeClass('ownTurn');
                }
                $status.html('');
                $content.appendTo($status);
                break;
            }
        }
    };

    $('#startButton').click(function () {
        conn.send('start');
    });

    $('#pile').click(function () {
        conn.send('draw');
    });

    $('#table').droppable({
        drop: function (event, ui) {

            const $card = ui.draggable;

            if ($card.hasClass('owncard')) {
                $card.removeClass('owncard');
                $card.addClass('commoncard');

                conn.send('show;' + $card.data('id'));
                dragStop(event, ui);
                refreshCommonCardEvents();
            }
        }
    });

    $('#discardPile').droppable({
        greedy: true,
        drop: function (event, ui) {
            let $card = ui.draggable;
            putCardOnDiscardPile($card);
            conn.send('discard;' + $card.data('id'));
        }
    });

    $('#grabDiscardPileButton').click(function () {
        conn.send('pickupDiscardPile');
    });

    $('#chatInput').keydown(function(event) {
        if (event.which == 13) {
            let inputText = $(this).val();
            if (inputText) {
                conn.send('chat;' + $(this).val());
                $(this).val('');
            }
        }
    });

});<commit_msg>Added animation for moving cards about the table.<commit_after>$(document).ready(function () {

    const conn = new WebSocket('ws://localhost:8080');
    let localPlayerName;

    const reorderBoardCardZIndex = function () {
        const $cards = $('#board').find('.card');
        $cards.each(function () {
            const $card = $(this);
            $card.css('z-index', parseInt($card.css('left')) + 1000);
        });
    };

    const dragStop = function (event, ui) {
        const $card = ui.draggable;
        const $parent = $card.parent();

        if ($parent.attr('id') != 'board') {
            return;
        }

        const left = (parseInt($card.css('left')) / $parent[0].clientWidth) * 100;
        const top = ((parseInt($card.css('top')) + 140) / $parent[0].clientHeight) * 100;
        conn.send('move;' + $card.data('id') + ';' + left + ';' + top);

        reorderBoardCardZIndex();
    };

    const refreshMovable = function () {
        $(".movable").draggable({
            start: function() {
                $(this).css('z-index', 5000);
            },
            stop: function (event, ui) {
                $.extend(ui, {draggable: $(this)});
                dragStop(event, ui);
            }
        });
    };

    const tabCardAccordingToAttribute = function ($card) {
        if ($card.data('tabbed')) {
            $card.css('transform', 'rotate(90deg)');
        } else {
            $card.css('transform', 'rotate(0deg)');
        }
    };

    const refreshCommonCardEvents = function () {
        $('.commoncard').dblclick(function () {
            const $card = $(this);
            if ($card.data('tabbed')) {
                $card.data('tabbed', false);
            } else {
                $card.data('tabbed', true);
            }
            tabCardAccordingToAttribute($card);
            conn.send('tab;' + $card.data('id'));
        });
    };

    const addCardToBoard = function (code, id, type) {
        const $board = $('#board');
        const $newCard = $('');
        $newCard.attr('id', 'card-' + id);
        $newCard.data('id', id);
        $newCard.data('tabbed', false);
        $newCard.appendTo($board);
        refreshCommonCardEvents();
        refreshMovable();
        reorderBoardCardZIndex();

        return $newCard;
    };

    const putCardOnDiscardPile = function ($card) {
        // Cards on discard pile can never be own cards
        if ($card.hasClass('owncard')) {
            $card.removeClass('owncard');
            $card.addClass('commoncard');
        }
        // Disable handling
        $card.removeClass('movable');
        $card.draggable('disable');
        $card.unbind('dblclick');
        // Visuals
        $card.appendTo('#discardPile');
        $card.css('left', '30px');
        $card.css('top', '10px');

        reorderBoardCardZIndex();
    };

    const askForName = function() {
        const name = prompt('name?');
        if (name) {
            return name;
        }
        return askForName();
    };

    conn.onopen = function () {
        console.log("Connection established!");

        localPlayerName = askForName();
        conn.send('name;' + localPlayerName);
    };

    conn.onmessage = function (e) {
        console.log('message received: ' + e.data);
        let payload = e.data.split(';');
        const command = payload[0];
        payload.splice(0, 1);

        const $opposingHand = $('#opposingHand');

        switch (command) {
            case 'lobby': {
                const $playerList = $('#playerList');
                $playerList.html('');
                for (let name of payload) {
                    name = $('
').html(name);
                    name.appendTo($playerList);
                }
                if (payload.length == 2) {
                    $('#startButton').show();
                }
                break;
            }
            case 'game': {
                if (payload == 'start') {
                    $('#lobby').hide();
                    $('#game').show();
                }
                if (payload == 'end') {
                    alert('The game has ended. You will now be redirected to the lobby.');
                    window.location.href = '/';
                }
                break;
            }
            case 'show': {
                $opposingHand.find('.opposingcard')[0].remove();
                addCardToBoard(payload[1], payload[0], 'commoncard');
                break;
            }
            case 'move': {
                const $cardToMove = $('#card-' + payload[0]);
                $cardToMove.animate({
                    left: payload[1] + '%',
                    top: payload[2] + '%'
                }, {
                    complete: reorderBoardCardZIndex
                });
                break;
            }
            case 'tab': {
                const $cardToTab = $('#card-' + payload[0]);
                $cardToTab.data('tabbed', payload[1] == true);
                tabCardAccordingToAttribute($cardToTab);
                break;
            }
            case 'packsize': {
                if (payload[0] == 0) {
                    $('#pile').hide();
                }
                break;
            }
            case 'discardsize': {
                $('#discardCounter').text(payload[0]);
                break;
            }
            case 'clearDiscardPile': {
                $('#discardCounter').text(0);
                $('#discardPile').find('.card').remove();
                break;
            }
            case 'draw': {
                if (payload[0] == 'opposing') {
                    const $opposingCard = $('');
                    $opposingCard.appendTo($opposingHand);
                    break;
                }
                const $ownHand = $('#ownHand');
                const $newCard = addCardToBoard(payload[1], payload[0], 'owncard');
                $newCard.css('top', $ownHand.position().top + 'px');

                const $ownCards = $('.owncard');
                if ($ownCards.length > 1) {
                    let mostRight;
                    $ownCards.each(function (index, card) {
                        const $card = $(card);
                        if (mostRight == null || $card.position().left > mostRight.position().left) {
                            mostRight = $card;
                        }
                    });

                    $newCard.css('left', (mostRight.position().left + 50) + 'px');
                }

                refreshMovable();
                reorderBoardCardZIndex();
                break;
            }
            case 'discard': {
                //noinspection JSJQueryEfficiency
                let $cardToDiscard = $('#card-' + payload[0]);
                // Card was on board and was not discarded directly from hand
                if ($cardToDiscard.length > 0) {
                    putCardOnDiscardPile($cardToDiscard);
                } else {
                    addCardToBoard(payload[1], payload[0], 'commoncard');
                    $cardToDiscard = $('#card-' + payload[0]);
                    putCardOnDiscardPile($cardToDiscard);
                    $opposingHand.find('.opposingcard')[0].remove();
                }
                break;
            }
            case 'chat': {
                let now = new Date();
                let prefix = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds() + ' ';
                $('

').text(prefix + payload.join(';')).appendTo('#messages');
                let $messages = $('#messages');
                $messages.scrollTop($messages[0].scrollHeight);
                break;
            }
            case 'currentPlayer': {
                let $status = $('#status');
                let $content = $('');
                if (payload[0] == localPlayerName) {
                    $content.text('Your turn, ' + localPlayerName + '! ');
                    $('').text('Done').click(function() {
                        conn.send('endTurn');
                    }).appendTo($content);
                    $status.addClass('ownTurn');
                    $status.removeClass('opposingTurn');
                } else {
                    $content.text(payload[0] + 's turn. ');
                    $status.addClass('opposingTurn');
                    $status.removeClass('ownTurn');
                }
                $status.html('');
                $content.appendTo($status);
                break;
            }
        }
    };

    $('#startButton').click(function () {
        conn.send('start');
    });

    $('#pile').click(function () {
        conn.send('draw');
    });

    $('#table').droppable({
        drop: function (event, ui) {

            const $card = ui.draggable;

            if ($card.hasClass('owncard')) {
                $card.removeClass('owncard');
                $card.addClass('commoncard');

                conn.send('show;' + $card.data('id'));
                dragStop(event, ui);
                refreshCommonCardEvents();
            }
        }
    });

    $('#discardPile').droppable({
        greedy: true,
        drop: function (event, ui) {
            let $card = ui.draggable;
            putCardOnDiscardPile($card);
            conn.send('discard;' + $card.data('id'));
        }
    });

    $('#grabDiscardPileButton').click(function () {
        conn.send('pickupDiscardPile');
    });

    $('#chatInput').keydown(function(event) {
        if (event.which == 13) {
            let inputText = $(this).val();
            if (inputText) {
                conn.send('chat;' + $(this).val());
                $(this).val('');
            }
        }
    });

});<|endoftext|>


<commit_before>const webpack = require("webpack");
const config = require("./webpack.base.config");

config.module.rules.push(
    {
        enforce: "pre",
        test: /\.jsx?$/,
        use: ["eslint-loader"],
        exclude: /node_modules/
    },
    {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
        include: /node_modules/
    },
    {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
        include: /node_modules/
    },
    {
        test: /\.less$/,
        use: [
            "style-loader",
            {
                loader: "css-loader",
                options: {
                    modules: true,
                    sourceMap: true,
                    localIdentName: "[name]-[local]"
                }
            },
            "less-loader"
        ],
        exclude: /node_modules/
    }
);

config.plugins.push(
    new webpack.SourceMapDevToolPlugin({
        filename: "[file].map",
        exclude: ["vendor.js"]
    })
);

// HMR.
for (const key of Object.keys(config.entry))
{
    config.entry[key].unshift(
        "react-hot-loader/patch",
        "webpack-hot-middleware/client"
    );
}
config.plugins.push(
    new webpack.HotModuleReplacementPlugin()
);

module.exports = config;
<commit_msg>add noInfo<commit_after>const webpack = require("webpack");
const config = require("./webpack.base.config");

config.module.rules.push(
    {
        enforce: "pre",
        test: /\.jsx?$/,
        use: ["eslint-loader"],
        exclude: /node_modules/
    },
    {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
        include: /node_modules/
    },
    {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
        include: /node_modules/
    },
    {
        test: /\.less$/,
        use: [
            "style-loader",
            {
                loader: "css-loader",
                options: {
                    modules: true,
                    sourceMap: true,
                    localIdentName: "[name]-[local]"
                }
            },
            "less-loader"
        ],
        exclude: /node_modules/
    }
);

config.plugins.push(
    new webpack.SourceMapDevToolPlugin({
        filename: "[file].map",
        exclude: ["vendor.js"]
    })
);

// HMR.
for (const key of Object.keys(config.entry))
{
    config.entry[key].unshift(
        "react-hot-loader/patch",
        "webpack-hot-middleware/client?noInfo=true"
    );
}
config.plugins.push(
    new webpack.HotModuleReplacementPlugin()
);

module.exports = config;
<|endoftext|>


<commit_before>/**
 * Players list
 */
/*global Modernizr*/
Template.PagePlayers.helpers({
	players: function() {
		var players = [];
		var player = {} ;
		var currPlayer = {};	// current player

		var playersList = Meteor.users.find({});
		var playersObj = playersList.fetch();
		var index = 1;
		var userlist = [];
		var fl = null;
		var currF = null;

		userlist = playersObj;
		// check facebook friends
		if (Session.get('friendsList')) {
			fl = Session.get('friendsList');

			if (fl && fl.length > 0) {
				for (var j = 0; j < fl.length; j++) {
					// get user in friends list in users collection
					currF = playersObj.filter(function(item, index) {
						var userId = item.services.facebook ? item.services.facebook.id.toString() : '';
						var FBUserId = fl[j].id.toString();

						if (userId.toLowerCase() === FBUserId.toLowerCase()) {
							var a = userlist.splice(index, 1);

							return a;
						}
					});

					if (currF[0]) {
						player = setPlayerIndex(currF[0], index++, true);
						if (player) {
							players.push(player);
						}
					}
				}
			}
		}

		for (var i = 0; i < userlist.length; i++) {
			currPlayer = userlist[i];

			player = setPlayerIndex(currPlayer, index++);
			if (player) {
				players.push(player);
			}
		}

		return players;
	}
});

Template.PagePlayers.rendered = function() {
	Meteor.users.getUserFriendsList();
};

/**
 * format date to ''dd/mm/yyy'
 */
function formatDate(date) {
	date = date || new Date();
	var dd = date.getDate();
	var mm = date.getMonth() + 1;	// month [0 - 11]
	var yyyy = date.getFullYear();

	return [dd, mm, yyyy].join('/');
}

/**
 *
 */
function setPlayerIndex(currPlayer, index, getProfilePic) {
	// get levels
	var gameScores = [];
	var player = {};

	gameScores = currPlayer.gameScores;

	if (gameScores !== undefined) {
		player = getPlayerInfo(currPlayer, getProfilePic);
		player.index = index;

		return player;
	}
}

/**
 * get information of player
 * @param  {[type]} currPlayer [description]
 * @return {[type]}            [description]
 */
function getPlayerInfo(currPlayer, getProfilePic) {
	var player = {};
	var lastAccess = null;
	var levels = '';

	// get extra information of user
	if (currPlayer.services.facebook && getProfilePic) {
		player = getPlayerInfoFacebook(currPlayer);
	}

	player.name = currPlayer.profile ? currPlayer.profile.name : '';
	lastAccess = currPlayer.lastAccess ? new Date(currPlayer.lastAccess) : new Date();

	lastAccess = formatDate(lastAccess);

	for (var j = 0; j < currPlayer.gameScores.length; j++) {
		if (j === currPlayer.gameScores.length - 1) {
			levels += currPlayer.gameScores[j].mapIndex;
		} else {
			levels += currPlayer.gameScores[j].mapIndex + ', ';
		}
	}

	player.lastAccess = lastAccess; //	player.facebook = true;
	player.levels = levels;

	return player;
}

/**
 * get url for avatar
 */
function getPlayerInfoFacebook(currPlayer) {
	var player = {};
	var type = 'square';

	// check for retina
	if (Modernizr.mq('(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)')) {
		type = 'large';
	}

	player.isFacebook = true;
	player.url = 'https://graph.facebook.com/' + currPlayer.services.facebook.id + '/picture?type=' + type;

	return player;
}
<commit_msg>add current user to top of players list<commit_after>/**
 * Players list
 */
/*global Modernizr*/
Template.PagePlayers.helpers({
	players: function() {
		var players = [];
		var player = {} ;
		var currPlayer = {};	// current player

		var playersList = Meteor.users.find({});
		var playersObj = playersList.fetch();
		var index = 1;
		var userlist = [];
		var fl = null;
		var currF = null;

		userlist = playersObj;

		// add this user to first of players list
		var loginUser = setPlayerIndex(Meteor.user(), index++, true);
		if (loginUser) {
			players.push(loginUser);
		}

		// check facebook friends
		if (Session.get('friendsList')) {
			fl = Session.get('friendsList');

			if (fl && fl.length > 0) {
				for (var j = 0; j < fl.length; j++) {
					// get user in friends list in users collection
					currF = playersObj.filter(function(item, index) {
						var userId = item.services.facebook ? item.services.facebook.id.toString() : '';
						var FBUserId = fl[j].id.toString();

						if (userId.toLowerCase() === FBUserId.toLowerCase()) {
							var a = userlist.splice(index, 1);

							return a;
						}
					});

					if (currF[0]) {
						player = setPlayerIndex(currF[0], index++, true);
						if (player) {
							players.push(player);
						}
					}
				}
			}
		}

		for (var i = 0; i < userlist.length; i++) {
			currPlayer = userlist[i];

			player = setPlayerIndex(currPlayer, index++);
			if (player) {
				players.push(player);
			}
		}

		return players;
	}
});

Template.PagePlayers.rendered = function() {
	Meteor.users.getUserFriendsList();
};

/**
 * format date to ''dd/mm/yyy'
 */
function formatDate(date) {
	date = date || new Date();
	var dd = date.getDate();
	var mm = date.getMonth() + 1;	// month [0 - 11]
	var yyyy = date.getFullYear();

	return [dd, mm, yyyy].join('/');
}

/**
 *
 */
function setPlayerIndex(currPlayer, index, getProfilePic) {
	// get levels
	var gameScores = [];
	var player = {};

	gameScores = currPlayer.gameScores;

	if (gameScores !== undefined) {
		player = getPlayerInfo(currPlayer, getProfilePic);
		player.index = index;

		return player;
	}
}

/**
 * get information of player
 * @param  {[type]} currPlayer [description]
 * @return {[type]}            [description]
 */
function getPlayerInfo(currPlayer, getProfilePic) {
	var player = {};
	var lastAccess = null;
	var levels = '';

	// get extra information of user
	if (currPlayer.services.facebook && getProfilePic) {
		player = getPlayerInfoFacebook(currPlayer);
	}

	player.name = currPlayer.profile ? currPlayer.profile.name : '';
	lastAccess = currPlayer.lastAccess ? new Date(currPlayer.lastAccess) : new Date();

	lastAccess = formatDate(lastAccess);

	for (var j = 0; j < currPlayer.gameScores.length; j++) {
		if (j === currPlayer.gameScores.length - 1) {
			levels += currPlayer.gameScores[j].mapIndex;
		} else {
			levels += currPlayer.gameScores[j].mapIndex + ', ';
		}
	}

	player.lastAccess = lastAccess; //	player.facebook = true;
	player.levels = levels;

	return player;
}

/**
 * get url for avatar
 */
function getPlayerInfoFacebook(currPlayer) {
	var player = {};
	var type = 'square';

	// check for retina
	if (Modernizr.mq('(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)')) {
		type = 'large';
	}

	player.isFacebook = true;
	player.url = 'https://graph.facebook.com/' + currPlayer.services.facebook.id + '/picture?type=' + type;

	return player;
}
<|endoftext|>


<commit_before>$(document).ready(function () {
  mapSetup();
  populateMap();

  (function() {
    var e = document.createElement('script'); e.async = true;
    e.src = document.location.protocol +
      '//connect.facebook.net/en_US/all.js';
    document.getElementById('fb-root').appendChild(e);
  }());

});

window.fbAsyncInit = function() {
FB.init({appId: 'your app id', status: true, cookie: true,
         xfbml: true});
};

var origin = null;
var destination = null;
var waypoints = [];
var map = null;
var bounds = null;

function mapSetup() {
    var myLatlng = new GLatLng(54, -4);
    bounds = new GLatLngBounds();
    map = new GMap2(document.getElementById("map_canvas"));
    map.addControl(new GMapTypeControl());
    map.enableScrollWheelZoom();
    map.addControl(new GLargeMapControl3D());
    map.addControl(new GOverviewMapControl());
    map.addMapType(G_NORMAL_MAP);
    map.addMapType(G_PHYSICAL_MAP);
    map.setMapType(G_PHYSICAL_MAP);
    map.setCenter(myLatlng, 5);
}

function populateMap(date) {
  if (typeof(date)=='undefined') {
    date = '2010-05-29';
  }
  $.getJSON('/route.json?date=' + date, function (data) {
    $.each(data.points, function(i,point){
      addWaypoint(point, i, data.points.length);
    });

    map.setZoom(map.getBoundsZoomLevel(bounds));
    map.setCenter(bounds.getCenter());
    if (waypoints.length > 0) {
      polyline = new GPolyline(waypoints);
      map.addOverlay(polyline);
    }
  })

}

function addWaypoint(point, i, length) {
  latlng = new GLatLng(point.latitude, point.longitude);
  bounds.extend(latlng);
  waypoints.push(latlng);

  var icon= new GIcon();

  var date = new Date(parseInt(point.timestamp) * 1000);
  var description = '

Device Name:	' + point.device_label + '

Date:	' + date.getDayName() + ', ' + date.getMonthName() + ' ' + date.getDate() + ', ' + date.getFullYear() + '

Time:	' + date.get12HourTime() + ':' + pad(date.getMinutes(), 2) + ':' +  pad(date.getSeconds(), 2) + ' ' + date.get12HourTimeSuffix() + ' ET

Speed:	' + point.speed + ' MPH

Latitude:	' + point.latitude + '

Longitude:	' + point.longitude + '

Distance:	' + point.distance + ' miles

Heading:	' + point.heading + ' degrees

Altitude:	' + point.altitude + ' feet

';

  if(i==0) {
    icon.image = "images/red-dot.png";
    icon.iconAnchor = new GPoint(16, 32);
    icon.iconSize = new GSize(30, 30);
    icon.infoWindowAnchor = new GPoint(16, 0);
  } else if(i == length-1) {
    icon.image = "images/green-dot.png";
    icon.iconAnchor = new GPoint(16, 32);
    icon.iconSize = new GSize(30, 30);
    icon.infoWindowAnchor = new GPoint(16, 0);
  } else {
    icon.image = "images/arrowno.png";
    icon.iconAnchor = new GPoint(8, 8);
    icon.iconSize = new GSize(15, 15);
    icon.infoWindowAnchor = new GPoint(8, 0);
  }

  icon.shadow = "";
  var marker = new GMarker(latlng, { icon:icon });
  marker.bindInfoWindowHtml(description);
  map.addOverlay(marker);

}

function pad(number, length) {
  var str = '' + number;
  while (str.length < length) {
      str = '0' + str;
  }
  return str;
}

Date.prototype.getMonthName = function() {
  var m = ['January','February','March','April','May','June','July','August','September','October','November','December'];
  return m[this.getMonth()];
}
Date.prototype.getDayName = function() {
  var d = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  return d[this.getDay()];
}
Date.prototype.get12HourTime = function() {
  return this.getHours()>12 ? this.getHours() - 12 : this.getHours();
}
Date.prototype.get12HourTimeSuffix = function() {
  return this.getHours()>12 ? 'pm' : 'am';
}<commit_msg>route data reloads, dup data detected and skipped<commit_after>$(document).ready(function () {
  mapSetup();
  populateMap();

  (function() {
    var e = document.createElement('script'); e.async = true;
    e.src = document.location.protocol +
      '//connect.facebook.net/en_US/all.js';
    document.getElementById('fb-root').appendChild(e);
  }());

});

window.fbAsyncInit = function() {
FB.init({appId: 'your app id', status: true, cookie: true,
         xfbml: true});
};

var waypoints = [];
var map = null;
var bounds = null;
var end_point_time = null;

function mapSetup() {
    var myLatlng = new GLatLng(54, -4);
    bounds = new GLatLngBounds();
    map = new GMap2(document.getElementById("map_canvas"));
    map.addControl(new GMapTypeControl());
    map.enableScrollWheelZoom();
    map.addControl(new GLargeMapControl3D());
    map.addControl(new GOverviewMapControl());
    map.addMapType(G_NORMAL_MAP);
    map.addMapType(G_PHYSICAL_MAP);
    map.setMapType(G_PHYSICAL_MAP);
    map.setCenter(myLatlng, 5);
}

function populateMap(date) {
  if (typeof(date)=='undefined') {
    date = '2010-05-29';
  }
  $.getJSON('/route.json?date=' + date, function (data) {
    if (data.points[data.points.length-1].timestamp == end_point_time) {
      return;
    }
    map.clearOverlays();
    $.each(data.points, function(i,point){
      addWaypoint(point, i, data.points.length);
    });

    map.setZoom(map.getBoundsZoomLevel(bounds));
    map.setCenter(bounds.getCenter());
    if (waypoints.length > 0) {
      polyline = new GPolyline(waypoints);
      map.addOverlay(polyline);
    }
    end_point_time = data.points[data.points.length-1].timestamp;
  });
  setTimeout('populateMap()', 300000);
}

function addWaypoint(point, i, length) {
  latlng = new GLatLng(point.latitude, point.longitude);
  bounds.extend(latlng);
  waypoints.push(latlng);

  var icon= new GIcon();

  var date = new Date(parseInt(point.timestamp) * 1000);
  var description = '

Device Name:	' + point.device_label + '

Date:	' + date.getDayName() + ', ' + date.getMonthName() + ' ' + date.getDate() + ', ' + date.getFullYear() + '

Time:	' + date.get12HourTime() + ':' + pad(date.getMinutes(), 2) + ':' +  pad(date.getSeconds(), 2) + ' ' + date.get12HourTimeSuffix() + ' ET

Speed:	' + point.speed + ' MPH

Latitude:	' + point.latitude + '

Longitude:	' + point.longitude + '

Distance:	' + point.distance + ' miles

Heading:	' + point.heading + ' degrees

Altitude:	' + point.altitude + ' feet

';

  if(i==0) {
    icon.image = "images/red-dot.png";
    icon.iconAnchor = new GPoint(16, 32);
    icon.iconSize = new GSize(30, 30);
    icon.infoWindowAnchor = new GPoint(16, 0);
  } else if(i == length-1) {
    icon.image = "images/green-dot.png";
    icon.iconAnchor = new GPoint(16, 32);
    icon.iconSize = new GSize(30, 30);
    icon.infoWindowAnchor = new GPoint(16, 0);
  } else {
    icon.image = "images/arrowno.png";
    icon.iconAnchor = new GPoint(8, 8);
    icon.iconSize = new GSize(15, 15);
    icon.infoWindowAnchor = new GPoint(8, 0);
  }

  icon.shadow = "";
  var marker = new GMarker(latlng, { icon:icon });
  marker.bindInfoWindowHtml(description);
  map.addOverlay(marker);

}

function pad(number, length) {
  var str = '' + number;
  while (str.length < length) {
      str = '0' + str;
  }
  return str;
}

Date.prototype.getMonthName = function() {
  var m = ['January','February','March','April','May','June','July','August','September','October','November','December'];
  return m[this.getMonth()];
}
Date.prototype.getDayName = function() {
  var d = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  return d[this.getDay()];
}
Date.prototype.get12HourTime = function() {
  return this.getHours()>12 ? this.getHours() - 12 : this.getHours();
}
Date.prototype.get12HourTimeSuffix = function() {
  return this.getHours()>12 ? 'pm' : 'am';
}<|endoftext|>


<commit_before>ReactListView.listStore = Fluxxor.createStore({
  initialize: function(options) {
    this.list = options.list || [];
    this.itemsToSave = [];
    this.bindActions(
      ReactListView.constants.ITEM_UPDATE, this.onUpdateItem,
      ReactListView.constants.ITEM_UPDATE_SUCCESS, this.onUpdateItemSuccess,
      ReactListView.constants.ITEM_UPDATE_FAILURE, this.onUpdateItemFailure,
      ReactListView.constants.ITEM_ADD, this.onItemAdd,
      ReactListView.constants.ITEM_ADD_SUCCESS, this.onItemAddSuccess,
      ReactListView.constants.ITEM_ADD_FAILURE, this.onItemAddFailure,
      ReactListView.constants.ITEM_DELETE, this.onItemDelete,
      ReactListView.constants.ITEM_DELETE_SUCCESS, this.onItemDeleteSuccess,
      ReactListView.constants.ITEM_DELETE_FAILURE, this.onItemDeleteFailure
    );
  },

  getID: function() {
    return this.list.id;
  },

  getState: function() {
    return {
      list: this.list,
      itemsToSave: this.itemsToSave
    };
  },

  onUpdateItem: function(payload) {
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.id === payload.itemData.id) {
        list_items[i] = payload.newItemData;
        list_items[i].isSaving = true;
        break;
      }
    }
    this.emit('change');
  },

  onUpdateItemSuccess: function(payload) {
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.id === payload.list_item.id) {
        list_items[i].isSaving = false;
        break;
      }
    }
    this.emit('change');
  },

  onUpdateItemFailure: function(payload) {
    console.log(payload);
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.id === payload.itemData.id) {
        list_items[i] = payload.itemData;
        list_items[i].isSaving = false;
        alert("Error saving changes. Error message: " + payload.error);
        break;
      }
    }
    this.emit('change');
  },

  onItemAdd: function(payload) {
    this.list.list_items.push(payload);
    this.itemsToSave.push(payload.listItemID);
    this.emit('change');
  },

  onItemAddSuccess: function(savedItemData) {
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.listItemID === savedItemData.listItemID) {
        list_items[i] = savedItemData;
        break;
      }
    }
    this.itemsToSave.splice( $.inArray(savedItemData.listItemID, this.itemsToSave), 1 );
    this.emit('change');
  },

  onItemAddFailure: function(payload) {
    var _this = this;
    this.itemsToSave.splice( $.inArray(payload.listItemID, this.itemsToSave), 1 );
    this.list.list_items.forEach(function(listItem, index) {
      if(listItem.listItemID !== undefined && listItem.listItemID == payload.listItemID) {
        _this.list.list_items.splice(index, 1);
        alert("Error adding new list item. Error message: ", payload.error);
        return false;
      }
    });
    this.emit('change');
  },

  onItemDelete: function(itemId) {
    for(var i = 0; i < this.list.list_items.length; i++) {
      var listItem = this.list.list_items[i];
      if(listItem.id === itemId) {
        this.list.list_items.splice(i, 1);
        break;
      }
    }

    var path = '/list_items/' + itemId;
    $.ajax({
      url: path,
      method: 'DELETE',
      dataType: 'json',
      contentType: 'application/json',
      error: function(jqXHR, textStatus, errorThrown) {
        console.log('error', errorThrown);
      },
      success: function(data, textStatus, jqXHR) {
        console.log('success', data);
      }
    });
    this.emit('change');
  },

  onItemDeleteSuccess: function(payload) {
    console.log('Implement ListStore::onItemDeleteSuccess()', payload);
  },

  onItemDeleteFailure: function(payload) {
    console.log('Implement ListStore::onItemDeleteFailure()', payload);
  },
});<commit_msg>Rename app.<commit_after>App.listStore = Fluxxor.createStore({
  initialize: function(options) {
    this.list = options.list || [];
    this.itemsToSave = [];
    this.bindActions(
      App.constants.ITEM_UPDATE, this.onUpdateItem,
      App.constants.ITEM_UPDATE_SUCCESS, this.onUpdateItemSuccess,
      App.constants.ITEM_UPDATE_FAILURE, this.onUpdateItemFailure,
      App.constants.ITEM_ADD, this.onItemAdd,
      App.constants.ITEM_ADD_SUCCESS, this.onItemAddSuccess,
      App.constants.ITEM_ADD_FAILURE, this.onItemAddFailure,
      App.constants.ITEM_DELETE, this.onItemDelete,
      App.constants.ITEM_DELETE_SUCCESS, this.onItemDeleteSuccess,
      App.constants.ITEM_DELETE_FAILURE, this.onItemDeleteFailure
    );
  },

  getID: function() {
    return this.list.id;
  },

  getState: function() {
    return {
      list: this.list,
      itemsToSave: this.itemsToSave
    };
  },

  onUpdateItem: function(payload) {
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.id === payload.itemData.id) {
        list_items[i] = payload.newItemData;
        list_items[i].isSaving = true;
        break;
      }
    }
    this.emit('change');
  },

  onUpdateItemSuccess: function(payload) {
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.id === payload.list_item.id) {
        list_items[i].isSaving = false;
        break;
      }
    }
    this.emit('change');
  },

  onUpdateItemFailure: function(payload) {
    console.log(payload);
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.id === payload.itemData.id) {
        list_items[i] = payload.itemData;
        list_items[i].isSaving = false;
        alert("Error saving changes. Error message: " + payload.error);
        break;
      }
    }
    this.emit('change');
  },

  onItemAdd: function(payload) {
    this.list.list_items.push(payload);
    this.itemsToSave.push(payload.listItemID);
    this.emit('change');
  },

  onItemAddSuccess: function(savedItemData) {
    var list_items = this.list.list_items;
    for(var i = 0; i < list_items.length; i++) {
      var listItem = list_items[i];
      if(listItem.listItemID === savedItemData.listItemID) {
        list_items[i] = savedItemData;
        break;
      }
    }
    this.itemsToSave.splice( $.inArray(savedItemData.listItemID, this.itemsToSave), 1 );
    this.emit('change');
  },

  onItemAddFailure: function(payload) {
    var _this = this;
    this.itemsToSave.splice( $.inArray(payload.listItemID, this.itemsToSave), 1 );
    this.list.list_items.forEach(function(listItem, index) {
      if(listItem.listItemID !== undefined && listItem.listItemID == payload.listItemID) {
        _this.list.list_items.splice(index, 1);
        alert("Error adding new list item. Error message: " + payload.error);
        return false;
      }
    });
    this.emit('change');
  },

  onItemDelete: function(itemId) {
    for(var i = 0; i < this.list.list_items.length; i++) {
      var listItem = this.list.list_items[i];
      if(listItem.id === itemId) {
        this.list.list_items.splice(i, 1);
        break;
      }
    }

    var path = '/list_items/' + itemId;
    $.ajax({
      url: path,
      method: 'DELETE',
      dataType: 'json',
      contentType: 'application/json',
      error: function(jqXHR, textStatus, errorThrown) {
        console.log('error', errorThrown);
      },
      success: function(data, textStatus, jqXHR) {
        console.log('success', data);
      }
    });
    this.emit('change');
  },

  onItemDeleteSuccess: function(payload) {
    console.log('Implement ListStore::onItemDeleteSuccess()', payload);
  },

  onItemDeleteFailure: function(payload) {
    console.log('Implement ListStore::onItemDeleteFailure()', payload);
  },
});<|endoftext|>


<commit_before>var baseConfig = require('./webpackBaseConfig');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = Object.assign({}, baseConfig, {
    plugins: [
        new webpack.ProvidePlugin({
            Visibility: "visibilityjs",
            Cookies: "js-cookie",
            key: "keymaster",
            $: "jquery",
            jQuery: "jquery",
            "window.jQuery": "jquery",
            "moment": "moment",
            "Handlebars": "handlebars"
        }),
        new ExtractTextPlugin("[name].css"),
        new webpack.optimize.CommonsChunkPlugin({
            names: ["vendor", "public", "slide", "locale"],
            children: true,
            async: true,
            filename: '[name].js',
            minChunks: Infinity
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'index'],
            filename: path.join(__dirname, 'public/views/build/index-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'index'],
            filename: path.join(__dirname, 'public/views/build/index-scripts.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'locale'],
            filename: path.join(__dirname, 'public/views/build/cover-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'locale'],
            filename: path.join(__dirname, 'public/views/build/cover-scripts.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'public'],
            filename: path.join(__dirname, 'public/views/build/pretty-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'public'],
            filename: path.join(__dirname, 'public/views/build/pretty-scripts.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'slide'],
            filename: path.join(__dirname, 'public/views/build/slide-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'slide'],
            filename: path.join(__dirname, 'public/views/build/slide-scripts.ejs'),
            inject: false
        }),
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            mangle: false,
            sourceMap: false
        })
    ],

    output: {
        path: path.join(__dirname, 'public/build'),
        publicPath: '/build/',
        filename: '[id].[name].[hash].js'
    },
});
<commit_msg>Fix production webpack config for 7ebc84bec0bf8f6e1f28e5fb3e9e7449bd7a2347<commit_after>var baseConfig = require('./webpackBaseConfig');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = Object.assign({}, baseConfig, {
    plugins: [
        new webpack.ProvidePlugin({
            Visibility: "visibilityjs",
            Cookies: "js-cookie",
            key: "keymaster",
            $: "jquery",
            jQuery: "jquery",
            "window.jQuery": "jquery",
            "moment": "moment",
            "Handlebars": "handlebars"
        }),
        new ExtractTextPlugin("[name].css"),
        new webpack.optimize.CommonsChunkPlugin({
            names: ["cover", "index", "pretty", "slide", "vendor"],
            children: true,
            async: true,
            filename: '[name].js',
            minChunks: Infinity
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'index'],
            filename: path.join(__dirname, 'public/views/build/index-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'index'],
            filename: path.join(__dirname, 'public/views/build/index-scripts.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'cover'],
            filename: path.join(__dirname, 'public/views/build/cover-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'cover'],
            filename: path.join(__dirname, 'public/views/build/cover-scripts.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'pretty'],
            filename: path.join(__dirname, 'public/views/build/pretty-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'pretty'],
            filename: path.join(__dirname, 'public/views/build/pretty-scripts.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/header.ejs',
            chunks: ['vendor', 'slide'],
            filename: path.join(__dirname, 'public/views/build/slide-header.ejs'),
            inject: false
        }),
        new HtmlWebpackPlugin({
            template: 'public/views/includes/scripts.ejs',
            chunks: ['vendor', 'slide'],
            filename: path.join(__dirname, 'public/views/build/slide-scripts.ejs'),
            inject: false
        }),
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            mangle: false,
            sourceMap: false
        })
    ],

    output: {
        path: path.join(__dirname, 'public/build'),
        publicPath: '/build/',
        filename: '[id].[name].[hash].js'
    },
});
<|endoftext|>


<commit_before>Template.intro.rendered = function () {
    var slider = (function () {

        var $slideshow = $('#slideshow'),
            $items = $slideshow.children('li'),
            itemsCount = $items.length,
            $controls = $('#controls'),
            navigation = {
                $navPrev: $controls.find('span.prev'),
                $navNext: $controls.find('span.next')
            },
            current = 0,
            isSlideshowActive = true,
            slideshowtime,
            interval = 7500;

        function init() {
            TweenLite.set($items.filter(":gt(0)"), {
                autoAlpha: 0
            });
            initEvents();
            startSlideshow();
        }
//        Creates the events of the buttons, in this case they are click events
        function initEvents() {
            startSlideshow();

            navigation.$navPrev.on('click', function () {
                navigate('prev');
                if (isSlideshowActive) {
                    startSlideshow();
                }
            });

            navigation.$navNext.on('click', function () {
                navigate('next');
                if (isSlideshowActive) {
                    startSlideshow();
                }
            });
        }

        function navigate(direction) {

            var $oldItem = $items.eq(current);

            if (direction === 'next') {
                if (current !== 2) {
                    current = current < itemsCount - 1 ? ++current : 0;
                }

            } else if (direction === 'prev') {
                if (current !== 0) {
                    current = current > 0 ? --current : itemsCount - 1;
                }
            }

            var $newItem = $items.eq(current);

            TweenLite.to($oldItem, 1, {
                autoAlpha: 0
            });
            TweenLite.to($newItem, 1, {
                autoAlpha: 1
            });

        }

//        Starts the slideshow and runs based on a given interval
        function startSlideshow() {
            isSlideshowActive = true;
            clearTimeout(slideshowtime);
            slideshowtime = setTimeout(function () {
                navigate('next');
                startSlideshow();
            }, interval);
        }

        return {
            init: init
        };

    })();

//    Executes the slider function created above
    $(function () {
        slider.init();
    });
}
<commit_msg>add source form code<commit_after>Template.intro.rendered = function () {
    //code is from http://codepen.io/anon/pen/wBBqxB

    var slider = (function () {

        var $slideshow = $('#slideshow'),
            $items = $slideshow.children('li'),
            itemsCount = $items.length,
            $controls = $('#controls'),
            navigation = {
                $navPrev: $controls.find('span.prev'),
                $navNext: $controls.find('span.next')
            },
            current = 0,
            isSlideshowActive = true,
            slideshowtime,
            interval = 7500;

        function init() {
            TweenLite.set($items.filter(":gt(0)"), {
                autoAlpha: 0
            });
            initEvents();
            startSlideshow();
        }
//        Creates the events of the buttons, in this case they are click events
        function initEvents() {
            startSlideshow();

            navigation.$navPrev.on('click', function () {
                navigate('prev');
                if (isSlideshowActive) {
                    startSlideshow();
                }
            });

            navigation.$navNext.on('click', function () {
                navigate('next');
                if (isSlideshowActive) {
                    startSlideshow();
                }
            });
        }

        function navigate(direction) {

            var $oldItem = $items.eq(current);

            if (direction === 'next') {
                if (current !== 2) {
                    current = current < itemsCount - 1 ? ++current : 0;
                }

            } else if (direction === 'prev') {
                if (current !== 0) {
                    current = current > 0 ? --current : itemsCount - 1;
                }
            }

            var $newItem = $items.eq(current);

            TweenLite.to($oldItem, 1, {
                autoAlpha: 0
            });
            TweenLite.to($newItem, 1, {
                autoAlpha: 1
            });

        }

//        Starts the slideshow and runs based on a given interval
        function startSlideshow() {
            isSlideshowActive = true;
            clearTimeout(slideshowtime);
            slideshowtime = setTimeout(function () {
                navigate('next');
                startSlideshow();
            }, interval);
        }

        return {
            init: init
        };

    })();

//    Executes the slider function created above
    $(function () {
        slider.init();
    });
}
<|endoftext|>


<commit_before>if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

var camera, scene, renderer;

init();

function init() {

  scene = new THREE.Scene();

  scene.add( new THREE.AmbientLight( 0x999999 ) );

  camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );

  // Z is up for objects intended to be 3D printed.

  camera.up.set( 0, 0, 1 );
  camera.position.set( 0, -9, 6 );

  var light1 = new THREE.PointLight( 0xffffff, 1 );
  light1.position.set( 0, 0, -10);
  var light2 = new THREE.PointLight( 0xffffff, 1 );
  light2.position.set( 20, -25, 0);
  var light3 = new THREE.PointLight( 0xffffff, 1 );
  var light4 = new THREE.PointLight( 0xffffff, 1 );

  camera.add(light1);
  camera.add(light2);
  camera.add(light3);
  camera.add(light4);
  scene.add(camera);

  var grid = new THREE.GridHelper( 25, 50, 0x0f2045, 0x0f2045 );
  grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
  scene.add(grid);

  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setClearColor( 0xffffff );
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );

  var loader = new THREE.STLLoader();

  // Binary files

  var material = new THREE.MeshPhongMaterial( { color: 0x0f2045, specular: 0x111111, shininess: 200 } );
  loader.load( 'https://s3.amazonaws.com/limbforgestls/EbeArm/Ebe_forearm_L/forearm_L_C4-200_L1-230.stl', function ( geometry ) {
    var mesh = new THREE.Mesh( geometry, material );

    mesh.position.set( 0, 0, 0 );
    mesh.rotation.set( 0, 0, 0 );
    mesh.scale.set( .02, .02, .02 );

    mesh.castShadow = false;
    mesh.receiveShadow = false;

    render();
  });

  var controls = new THREE.OrbitControls( camera, renderer.domElement );
  controls.addEventListener( 'change', render );
  controls.target.set( 0, 1.2, 2 );
  controls.update();
  window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize( window.innerWidth, window.innerHeight );

  render();

}

function render() {

  renderer.render( scene, camera );

}

  $(document).on('turbolinks:load', function() {
    document.getElementById('display-hand').appendChild( renderer.domElement );
    render();
  });
<commit_msg>added global function for rendering the threejs scene<commit_after>if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

var camera, scene, renderer;

init();

function init() {

  scene = new THREE.Scene();

  scene.add( new THREE.AmbientLight( 0x999999 ) );

  camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );

  // Z is up for objects intended to be 3D printed.

  camera.up.set( 0, 0, 1 );
  camera.position.set( 0, -9, 6 );

  var light1 = new THREE.PointLight( 0xffffff, 1 );
  light1.position.set( 0, 0, -10);
  var light2 = new THREE.PointLight( 0xffffff, 1 );
  light2.position.set( 20, -25, 0);
  var light3 = new THREE.PointLight( 0xffffff, 1 );
  var light4 = new THREE.PointLight( 0xffffff, 1 );

  camera.add(light1);
  camera.add(light2);
  camera.add(light3);
  camera.add(light4);
  scene.add(camera);

  var grid = new THREE.GridHelper( 25, 50, 0x0f2045, 0x0f2045 );
  grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
  scene.add(grid);

  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setClearColor( 0xffffff );
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );

  var loader = new THREE.STLLoader();

  // Binary files

  var material = new THREE.MeshPhongMaterial( { color: 0x0f2045, specular: 0x111111, shininess: 200 } );
  loader.load( 'https://s3.amazonaws.com/limbforgestls/EbeArm/Ebe_forearm_L/forearm_L_C4-200_L1-230.stl', function ( geometry ) {
    var mesh = new THREE.Mesh( geometry, material );

    mesh.position.set( 0, 0, 0 );
    mesh.rotation.set( 0, 0, 0 );
    mesh.scale.set( .02, .02, .02 );

    mesh.castShadow = false;
    mesh.receiveShadow = false;

    render();
  });

  var controls = new THREE.OrbitControls( camera, renderer.domElement );
  controls.addEventListener( 'change', render );
  controls.target.set( 0, 1.2, 2 );
  controls.update();
  window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize( window.innerWidth, window.innerHeight );

  render();

}

function render() {

  renderer.render( scene, camera );

}

var renderThreeJS = render;

  $(document).on('turbolinks:load', function() {
    document.getElementById('display-hand').appendChild( renderer.domElement );
    render();
  });
<|endoftext|>