<commit_before>import React from 'react'
import { browserHistory, withRouter } from 'react-router'
import PropTypes from 'prop-types'
import PanelShell, { renderItems } from '@components/PanelShell'
import { Email, Verify, Password, Username, Hooray } from './views'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { AccountActions } from '../account/store/account'
import { IdentityActions } from '../profiles/store/identity'
import { SettingsActions } from '../account/store/settings'
import { connectToGaiaHub } from '../account/utils/blockstack-inc'
import { RegistrationActions } from '../profiles/store/registration'
import { BLOCKSTACK_INC } from '../account/utils/index'
import { setCoreStorageConfig } from '@utils/api-utils'
import { hasNameBeenPreordered } from '@utils/name-utils'
import log4js from 'log4js'

const logger = log4js.getLogger('onboarding/index.js')

const VIEWS = {
  EMAIL: 0,
  EMAIL_VERIFY: 1,
  PASSWORD: 2,
  USERNAME: 3,
  HOORAY: 4
}

const HEROKU_URL = 'https://obscure-retreat-87934.herokuapp.com'

function mapStateToProps(state) {
  return {
    api: state.settings.api,
    updateApi: PropTypes.func.isRequired,
    promptedForEmail: state.account.promptedForEmail,
    encryptedBackupPhrase: state.account.encryptedBackupPhrase,
    localIdentities: state.profiles.identity.localIdentities,
    identityAddresses: state.account.identityAccount.addresses,
    identityKeypairs: state.account.identityAccount.keypairs,
    connectedStorageAtLeastOnce: state.account.connectedStorageAtLeastOnce,
    storageConnected: state.settings.api.storageConnected,
    email: state.account.email,
    registration: state.profiles.registration
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(Object.assign({},
    AccountActions, SettingsActions, IdentityActions, RegistrationActions),
    dispatch)
}

function sendRecovery(blockstackId, email, encryptedSeed) {
  const { protocol, hostname, port } = location
  const thisUrl = `${protocol}//${hostname}${port && `:${port}`}`
  const seedRecovery = `${thisUrl}/seed?encrypted=${encryptedSeed}`

  const options = {
    method: 'POST',
    body: JSON.stringify({
      email,
      seedRecovery,
      blockstackId
    }),
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json'
    }
  }

  return fetch(`${HEROKU_URL}/recovery`, options)
    .then(
      () => {
        console.log(`emailNotifications: sent ${email} recovery email`)
      },
      error => {
        console.log('emailNotifications: error', error)
      }
    )
    .catch(error => {
      console.log('emailNotifications: error', error)
    })
}

function sendRestore(blockstackId, email, encryptedSeed) {
  const { protocol, hostname, port } = location
  const thisUrl = `${protocol}//${hostname}${port && `:${port}`}`
  const restoreLink = `${thisUrl}/sign-in?seed=${encryptedSeed}`

  const options = {
    method: 'POST',
    body: JSON.stringify({
      email,
      restoreLink,
      blockstackId
    }),
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json'
    }
  }

  return fetch(`${HEROKU_URL}/restore`, options)
    .then(
      () => {
        console.log(`emailNotifications: sent ${email} restore email`)
      },
      error => {
        console.log('emailNotifications: error', error)
      }
    )
    .catch(error => {
      console.log('emailNotifications: error', error)
    })
}

class Onboarding extends React.Component {
  state = {
    email: '',
    password: '',
    username: '',
    seed: '',
    emailSubmitted: false,
    view: VIEWS.EMAIL,
    usernameRegistrationInProgress: false
  }

  componentWillMount() {
    const { location } = this.props
    if (location.query.verified) {
      this.setState({ email: location.query.verified })
      this.updateView(VIEWS.PASSWORD)
    }
  }

  componentWillReceiveProps(nextProps) {
    const { registration } = nextProps

    if (this.state.usernameRegistrationInProgress && registration.registrationSubmitted) {
      this.updateView(VIEWS.HOORAY)
    } else if (registration.error) {
      logger.error(`username registration error: ${registration.error}`)
      this.setState({
        usernameRegistrationInProgress: false
      })
    }
  }

  updateURL = view => {
    const historyChange = slug => {
      if (this.props.location.pathname !== `/sign-up/${slug}`) {
        return this.props.router.push(`/sign-up/${slug}`, this.state)
      } else {
        return null
      }
    }

    switch (view) {
      case VIEWS.EMAIL_VERIFY:
        return historyChange('verify')
      case VIEWS.PASSWORD:
        return historyChange('password')
      case VIEWS.USERNAME:
        return historyChange('username')
      case VIEWS.HOORAY:
        return historyChange('success')
      default:
        return null
    }
  }

  componentDidUpdate() {
    this.updateURL(this.state.view)
  }

  updateValue = (key, value) => {
    this.setState({ [key]: value })
  }

  updateView = view => this.setState({ view })

  verifyEmail(email) {
    this.setState({ emailSubmitted: true })

    const { protocol, hostname, port } = location
    const thisUrl = `${protocol}//${hostname}${port && `:${port}`}`
    const emailVerificationLink = `${thisUrl}/sign-up?verified=${email}`

    const options = {
      method: 'POST',
      body: JSON.stringify({
        email,
        emailVerificationLink
      }),
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      }
    }

    return fetch(`${HEROKU_URL}/verify`, options)
      .then(
        () => {
          console.log(`emailNotifications: sent ${email} an email verification`)
        },
        error => {
          this.setState({ emailSubmitted: false })
          console.log('emailNotifications: error', error)
        }
      )
      .catch(error => {
        console.log('emailNotifications: error', error)
        this.setState({ emailSubmitted: false })
      })
  }

  submitPassword = () => {
    const { username, email } = this.state
    if (username.length < 1) {
      this.setState({
        email
      })
    }

    logger.debug('creating account')
    this.createAccount(this.state.password)
      .then(() => this.connectStorage())
      .then(() => {
        this.updateView(VIEWS.USERNAME)
      })
  }

  createAccount(password) {
    const firstIdentityIndex = 0
    return this.props.initializeWallet(password, null)
    .then(() => {
      logger.debug('creating new identity')
      const ownerAddress = this.props.identityAddresses[firstIdentityIndex]
      return this.props.createNewIdentityWithOwnerAddress(firstIdentityIndex, ownerAddress)
    }).then(() => {
      return this.props.setDefaultIdentity(firstIdentityIndex)
    })
  }

  connectStorage() {
    const storageProvider = this.props.api.gaiaHubUrl
    const signer = this.props.identityKeypairs[0].key
    return connectToGaiaHub(storageProvider, signer).then(gaiaHubConfig => {
      const newApi = Object.assign({}, this.props.api, {
        gaiaHubConfig,
        hostedDataLocation: BLOCKSTACK_INC
      })
      this.props.updateApi(newApi)
      const identityIndex = 0
      const identity = this.props.localIdentities[identityIndex]
      const identityAddress = identity.ownerAddress
      const profileSigningKeypair = this.props.identityKeypairs[identityIndex]
      const profile = identity.profile
      setCoreStorageConfig(
        newApi,
        identityIndex,
        identityAddress,
        profile,
        profileSigningKeypair,
        identity
      ).then(indexUrl => {
        logger.debug('connectStorage: storage initialized')
        const newApi2 = Object.assign({}, newApi, { storageConnected: true })
        this.props.updateApi(newApi2)
        this.props.storageIsConnected()
        logger.debug('connectStorage: storage configured')
      })
    })
  }

  submitUsername = (username) => {
    const suffix = '.blockstack.id'
    username += suffix
    logger.trace('registerUsername')
    const nameHasBeenPreordered = hasNameBeenPreordered(username, this.props.localIdentities)
    if (nameHasBeenPreordered) {
      logger.error(`registerUsername: username '${username}' has already been preordered`)
    } else {
      this.setState({
        usernameRegistrationInProgress: true
      })
      logger.debug(`registerUsername: will try and register username: ${username}`)
      const address = this.props.identityAddresses[0]
      const identity = this.props.localIdentities[0]
      const keypair = this.props.identityKeypairs[0]
      this.props.registerName(this.props.api, username, identity,
        0, address, keypair)
    }
  }

  goToBackup = () => {
    browserHistory.push({
      pathname: '/seed',
      state: { seed: this.state.seed }
    })
  }

  submitEmailForVerification = () => {
    // Short-circuit email verification
    this.verifyEmail(this.state.email)
    .then(() => {
      this.updateView(VIEWS.PASSWORD)
    })

    // verifyEmail(this.state.email)
    // this.updateView(VIEWS.EMAIL_VERIFY)
  }

  render() {
    const { email, password, username, emailSubmitted, view } = this.state

    const views = [
      {
        show: VIEWS.EMAIL,
        Component: Email,
        props: {
          email,
          next: this.submitEmailForVerification,
          submitted: emailSubmitted,
          updateValue: this.updateValue
        }
      },
      {
        show: VIEWS.EMAIL_VERIFY,
        Component: Verify,
        props: {
          email,
          resend: this.submitEmailForVerification,
          next: () => this.updateView(VIEWS.PASSWORD)
        }
      },
      {
        show: VIEWS.PASSWORD,
        Component: Password,
        props: {
          password,
          next: this.submitPassword,
          updateValue: this.updateValue
        }
      },
      {
        show: VIEWS.USERNAME,
        Component: Username,
        props: {
          username,
          next: this.submitUsername,
          previous: () => this.updateView(VIEWS.PASSWORD),
          updateValue: this.updateValue,
          isProcessing: this.state.usernameRegistrationInProgress
        }
      },
      {
        show: VIEWS.HOORAY,
        Component: Hooray,
        props: {
          email,
          password,
          username,
          goToRecovery: this.goToBackup,
          goToApp: () => console.log('go to app!')
        }
      }
    ]

    return <PanelShell>{renderItems(views, view)}</PanelShell>
  }
}

Onboarding.propTypes = {
  api: PropTypes.object.isRequired,
  location: PropTypes.object,
  router: PropTypes.object,
  identityAddresses: PropTypes.array,
  createNewIdentityWithOwnerAddress: PropTypes.func.isRequired,
  setDefaultIdentity: PropTypes.func.isRequired,
  initializeWallet: PropTypes.func.isRequired,
  updateApi: PropTypes.func.isRequired,
  localIdentities: PropTypes.array.isRequired,
  identityKeypairs: PropTypes.array.isRequired,
  storageIsConnected: PropTypes.func.isRequired,
  registerName: PropTypes.func.isRequired
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Onboarding))
<commit_msg>Save authRequest and redirect after onbaording.<commit_after>import React from 'react'
import { browserHistory, withRouter } from 'react-router'
import PropTypes from 'prop-types'
import PanelShell, { renderItems } from '@components/PanelShell'
import { Email, Verify, Password, Username, Hooray } from './views'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { AccountActions } from '../account/store/account'
import { IdentityActions } from '../profiles/store/identity'
import { SettingsActions } from '../account/store/settings'
import { connectToGaiaHub } from '../account/utils/blockstack-inc'
import { RegistrationActions } from '../profiles/store/registration'
import { BLOCKSTACK_INC } from '../account/utils/index'
import { setCoreStorageConfig } from '@utils/api-utils'
import { hasNameBeenPreordered } from '@utils/name-utils'
import queryString from 'query-string'
import log4js from 'log4js'

const logger = log4js.getLogger('onboarding/index.js')

const VIEWS = {
  EMAIL: 0,
  EMAIL_VERIFY: 1,
  PASSWORD: 2,
  USERNAME: 3,
  HOORAY: 4
}

const HEROKU_URL = 'https://obscure-retreat-87934.herokuapp.com'

function mapStateToProps(state) {
  return {
    api: state.settings.api,
    updateApi: PropTypes.func.isRequired,
    promptedForEmail: state.account.promptedForEmail,
    encryptedBackupPhrase: state.account.encryptedBackupPhrase,
    localIdentities: state.profiles.identity.localIdentities,
    identityAddresses: state.account.identityAccount.addresses,
    identityKeypairs: state.account.identityAccount.keypairs,
    connectedStorageAtLeastOnce: state.account.connectedStorageAtLeastOnce,
    storageConnected: state.settings.api.storageConnected,
    email: state.account.email,
    registration: state.profiles.registration
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(Object.assign({},
    AccountActions, SettingsActions, IdentityActions, RegistrationActions),
    dispatch)
}

function sendRecovery(blockstackId, email, encryptedSeed) {
  const { protocol, hostname, port } = location
  const thisUrl = `${protocol}//${hostname}${port && `:${port}`}`
  const seedRecovery = `${thisUrl}/seed?encrypted=${encryptedSeed}`

  const options = {
    method: 'POST',
    body: JSON.stringify({
      email,
      seedRecovery,
      blockstackId
    }),
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json'
    }
  }

  return fetch(`${HEROKU_URL}/recovery`, options)
    .then(
      () => {
        console.log(`emailNotifications: sent ${email} recovery email`)
      },
      error => {
        console.log('emailNotifications: error', error)
      }
    )
    .catch(error => {
      console.log('emailNotifications: error', error)
    })
}

function sendRestore(blockstackId, email, encryptedSeed) {
  const { protocol, hostname, port } = location
  const thisUrl = `${protocol}//${hostname}${port && `:${port}`}`
  const restoreLink = `${thisUrl}/sign-in?seed=${encryptedSeed}`

  const options = {
    method: 'POST',
    body: JSON.stringify({
      email,
      restoreLink,
      blockstackId
    }),
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json'
    }
  }

  return fetch(`${HEROKU_URL}/restore`, options)
    .then(
      () => {
        console.log(`emailNotifications: sent ${email} restore email`)
      },
      error => {
        console.log('emailNotifications: error', error)
      }
    )
    .catch(error => {
      console.log('emailNotifications: error', error)
    })
}

class Onboarding extends React.Component {
  state = {
    authRequest: '',
    email: '',
    password: '',
    username: '',
    seed: '',
    emailSubmitted: false,
    view: VIEWS.EMAIL,
    usernameRegistrationInProgress: false
  }

  componentWillMount() {
    const { location } = this.props
    if (location.query.verified) {
      this.setState({ email: location.query.verified })
      this.updateView(VIEWS.PASSWORD)
    }
  }

  componentDidMount() {
    this.saveAuthRequest()
  }

  componentWillReceiveProps(nextProps) {
    const { registration } = nextProps

    if (this.state.usernameRegistrationInProgress && registration.registrationSubmitted) {
      this.updateView(VIEWS.HOORAY)
    } else if (registration.error) {
      logger.error(`username registration error: ${registration.error}`)
      this.setState({
        usernameRegistrationInProgress: false
      })
    }
  }

  updateURL = view => {
    const historyChange = slug => {
      if (this.props.location.pathname !== `/sign-up/${slug}`) {
        return this.props.router.push(`/sign-up/${slug}`, this.state)
      } else {
        return null
      }
    }

    switch (view) {
      case VIEWS.EMAIL_VERIFY:
        return historyChange('verify')
      case VIEWS.PASSWORD:
        return historyChange('password')
      case VIEWS.USERNAME:
        return historyChange('username')
      case VIEWS.HOORAY:
        return historyChange('success')
      default:
        return null
    }
  }

  componentDidUpdate() {
    this.updateURL(this.state.view)
  }

  saveAuthRequest() {
    const queryDict = queryString.parse(this.props.location.search)
    if (queryDict.redirect !== null && queryDict.redirect !== undefined) {
      const searchString = queryDict.redirect.replace('/auth', '')
      var redirectQueryDict = queryString.parse(searchString)
      if (redirectQueryDict.authRequest !== null && redirectQueryDict.authRequest !== undefined) {
        const authRequest = redirectQueryDict.authRequest
        this.setState({
          authRequest: authRequest
        })
      }
    }
  }

  updateValue = (key, value) => {
    this.setState({ [key]: value })
  }

  updateView = view => this.setState({ view })

  verifyEmail(email) {
    this.setState({ emailSubmitted: true })

    const { protocol, hostname, port } = location
    const thisUrl = `${protocol}//${hostname}${port && `:${port}`}`
    const emailVerificationLink = `${thisUrl}/sign-up?verified=${email}`

    const options = {
      method: 'POST',
      body: JSON.stringify({
        email,
        emailVerificationLink
      }),
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      }
    }

    return fetch(`${HEROKU_URL}/verify`, options)
      .then(
        () => {
          console.log(`emailNotifications: sent ${email} an email verification`)
        },
        error => {
          this.setState({ emailSubmitted: false })
          console.log('emailNotifications: error', error)
        }
      )
      .catch(error => {
        console.log('emailNotifications: error', error)
        this.setState({ emailSubmitted: false })
      })
  }

  submitPassword = () => {
    const { username, email } = this.state
    if (username.length < 1) {
      this.setState({
        email
      })
    }

    logger.debug('creating account')
    this.createAccount(this.state.password)
      .then(() => this.connectStorage())
      .then(() => {
        this.updateView(VIEWS.USERNAME)
      })
  }

  createAccount(password) {
    const firstIdentityIndex = 0
    return this.props.initializeWallet(password, null)
    .then(() => {
      logger.debug('creating new identity')
      const ownerAddress = this.props.identityAddresses[firstIdentityIndex]
      return this.props.createNewIdentityWithOwnerAddress(firstIdentityIndex, ownerAddress)
    }).then(() => {
      return this.props.setDefaultIdentity(firstIdentityIndex)
    })
  }

  connectStorage() {
    const storageProvider = this.props.api.gaiaHubUrl
    const signer = this.props.identityKeypairs[0].key
    return connectToGaiaHub(storageProvider, signer).then(gaiaHubConfig => {
      const newApi = Object.assign({}, this.props.api, {
        gaiaHubConfig,
        hostedDataLocation: BLOCKSTACK_INC
      })
      this.props.updateApi(newApi)
      const identityIndex = 0
      const identity = this.props.localIdentities[identityIndex]
      const identityAddress = identity.ownerAddress
      const profileSigningKeypair = this.props.identityKeypairs[identityIndex]
      const profile = identity.profile
      setCoreStorageConfig(
        newApi,
        identityIndex,
        identityAddress,
        profile,
        profileSigningKeypair,
        identity
      ).then(indexUrl => {
        logger.debug('connectStorage: storage initialized')
        const newApi2 = Object.assign({}, newApi, { storageConnected: true })
        this.props.updateApi(newApi2)
        this.props.storageIsConnected()
        logger.debug('connectStorage: storage configured')
      })
    })
  }

  submitUsername = (username) => {
    const suffix = '.blockstack.id'
    username += suffix
    logger.trace('registerUsername')
    const nameHasBeenPreordered = hasNameBeenPreordered(username, this.props.localIdentities)
    if (nameHasBeenPreordered) {
      logger.error(`registerUsername: username '${username}' has already been preordered`)
    } else {
      this.setState({
        usernameRegistrationInProgress: true
      })
      logger.debug(`registerUsername: will try and register username: ${username}`)
      const address = this.props.identityAddresses[0]
      const identity = this.props.localIdentities[0]
      const keypair = this.props.identityKeypairs[0]
      this.props.registerName(this.props.api, username, identity,
        0, address, keypair)
    }
  }

  redirectToAuth = () => {
    this.props.router.push(`/auth/?authRequest=${this.state.authRequest}`)
  }

  goToBackup = () => {
    browserHistory.push({
      pathname: '/seed',
      state: { seed: this.state.seed }
    })
  }

  submitEmailForVerification = () => {
    // Short-circuit email verification
    this.verifyEmail(this.state.email)
    .then(() => {
      this.updateView(VIEWS.PASSWORD)
    })

    // verifyEmail(this.state.email)
    // this.updateView(VIEWS.EMAIL_VERIFY)
  }

  render() {
    const { email, password, username, emailSubmitted, view } = this.state

    const views = [
      {
        show: VIEWS.EMAIL,
        Component: Email,
        props: {
          email,
          next: this.submitEmailForVerification,
          submitted: emailSubmitted,
          updateValue: this.updateValue
        }
      },
      {
        show: VIEWS.EMAIL_VERIFY,
        Component: Verify,
        props: {
          email,
          resend: this.submitEmailForVerification,
          next: () => this.updateView(VIEWS.PASSWORD)
        }
      },
      {
        show: VIEWS.PASSWORD,
        Component: Password,
        props: {
          password,
          next: this.submitPassword,
          updateValue: this.updateValue
        }
      },
      {
        show: VIEWS.USERNAME,
        Component: Username,
        props: {
          username,
          next: this.submitUsername,
          previous: () => this.updateView(VIEWS.PASSWORD),
          updateValue: this.updateValue,
          isProcessing: this.state.usernameRegistrationInProgress
        }
      },
      {
        show: VIEWS.HOORAY,
        Component: Hooray,
        props: {
          email,
          password,
          username,
          goToRecovery: this.goToBackup,
          goToApp: () => this.redirectToAuth
        }
      }
    ]

    return <PanelShell>{renderItems(views, view)}</PanelShell>
  }
}

Onboarding.propTypes = {
  api: PropTypes.object.isRequired,
  location: PropTypes.object,
  router: PropTypes.object,
  identityAddresses: PropTypes.array,
  createNewIdentityWithOwnerAddress: PropTypes.func.isRequired,
  setDefaultIdentity: PropTypes.func.isRequired,
  initializeWallet: PropTypes.func.isRequired,
  updateApi: PropTypes.func.isRequired,
  localIdentities: PropTypes.array.isRequired,
  identityKeypairs: PropTypes.array.isRequired,
  storageIsConnected: PropTypes.func.isRequired,
  registerName: PropTypes.func.isRequired
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Onboarding))
<|endoftext|>


<commit_before>/* FileSaver.js demo script
 * 2011-08-02
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See LICENSE.md
 */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/demo/demo.js */

(function(view) {
"use strict";
// The canvas drawing portion of the demo is based off the demo at
// http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/
var
	  document = view.document
	, $ = function(id) {
		return document.getElementById(id);
	}
	, session = view.sessionStorage
	// only get URL when necessary in case BlobBuilder.js hasn't defined it yet
	, get_blob_builder = function() {
		return view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder;
	}

	, canvas = $("canvas")
	, canvas_options_form = $("canvas-options")
	, canvas_filename = $("canvas-filename")
	, canvas_clear_button = $("canvas-clear")

	, text = $("text")
	, text_options_form = $("text-options")
	, text_filename = $("text-filename")

	, html = $("html")
	, html_options_form = $("html-options")
	, html_filename = $("html-filename")

	, ctx = canvas.getContext("2d")
	, drawing = false
	, x_points = session.x_points || []
	, y_points = session.y_points || []
	, drag_points = session.drag_points || []
	, add_point = function(x, y, dragging) {
		x_points.push(x);
		y_points.push(y);
		drag_points.push(dragging);
	}
	, draw = function(){
		canvas.width = canvas.width;
		ctx.lineWidth = 6;
		ctx.lineJoin = "round";
		ctx.strokeStyle = "#000000";
		var
			  i = 0
			, len = x_points.length
		;
		for(; i < len; i++) {
			ctx.beginPath();
			if (i && drag_points[i]) {
				ctx.moveTo(x_points[i-1], y_points[i-1]);
			} else {
				ctx.moveTo(x_points[i]-1, y_points[i]);
			}
			ctx.lineTo(x_points[i], y_points[i]);
			ctx.closePath();
			ctx.stroke();
		}
	}
	, stop_drawing = function() {
		drawing = false;
	}

	// Title guesser and document creator available at https://gist.github.com/1059648
	, guess_title = function(doc) {
		var
			  h = "h6 h5 h4 h3 h2 h1".split(" ")
			, i = h.length
			, headers
			, header_text
		;
		while (i--) {
			headers = doc.getElementsByTagName(h[i]);
			for (var j = 0, len = headers.length; j < len; j++) {
				header_text = headers[j].textContent.trim();
				if (header_text) {
					return header_text;
				}
			}
		}
	}
	, doc_impl = document.implementation
	, create_html_doc = function(html) {
		var
			  dt = doc_impl.createDocumentType('html', null, null)
			, doc = doc_impl.createDocument("http://www.w3.org/1999/xhtml", "html", dt)
			, doc_el = doc.documentElement
			, head = doc_el.appendChild(doc.createElement("head"))
			, charset_meta = head.appendChild(doc.createElement("meta"))
			, title = head.appendChild(doc.createElement("title"))
			, body = doc_el.appendChild(doc.createElement("body"))
			, i = 0
			, len = html.childNodes.length
		;
		charset_meta.setAttribute("charset", html.ownerDocument.characterSet);
		for (; i < len; i++) {
			body.appendChild(doc.importNode(html.childNodes.item(i), true));
		}
		var title_text = guess_title(doc);
		if (title_text) {
			title.appendChild(doc.createTextNode(title_text));
		}
		return doc;
	}
;
canvas.width = 500;
canvas.height = 300;

  if (typeof x_points === "string") {
	x_points = JSON.parse(x_points);
} if (typeof y_points === "string") {
	y_points = JSON.parse(y_points);
} if (typeof drag_points === "string") {
	drag_points = JSON.parse(drag_points);
} if (session.canvas_filename) {
	canvas_filename.value = session.canvas_filename;
} if (session.text) {
	text.value = session.text;
} if (session.text_filename) {
	text_filename.value = session.text_filename;
} if (session.html) {
	html.innerHTML = session.html;
} if (session.html_filename) {
	html_filename.value = session.html_filename;
}

drawing = true;
draw();
drawing = false;

canvas_clear_button.addEventListener("click", function() {
	canvas.width = canvas.width;
	x_points.length =
	y_points.length =
	drag_points.length =
		0;
}, false);
canvas.addEventListener("mousedown", function(event) {
	drawing = true;
	add_point(event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop, false);
	draw();
}, false);
canvas.addEventListener("mousemove", function(event) {
	if (drawing) {
		add_point(event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop, true);
		draw();
	}
}, false);
canvas.addEventListener("mouseup", stop_drawing, false);
canvas.addEventListener("mouseout", stop_drawing, false);

canvas_options_form.addEventListener("submit", function(event) {
	event.preventDefault();
	canvas.toBlob(function(blob) {
		saveAs(
			  blob
			, (canvas_filename.value || canvas_filename.placeholder) + ".png"
		);
	}, "image/png");
}, false);

text_options_form.addEventListener("submit", function(event) {
	event.preventDefault();
	var BB = get_blob_builder();
	var bb = new BB;
	bb.append(text.value || text.placeholder);
	saveAs(
		  bb.getBlob("text/plain;charset=" + document.characterSet)
		, (text_filename.value || text_filename.placeholder) + ".txt"
	);
}, false);

html_options_form.addEventListener("submit", function(event) {
	event.preventDefault();
	var
		  BB = get_blob_builder()
		, bb = new BB
		, xml_serializer = new XMLSerializer
		, doc = create_html_doc(html)
	;
	bb.append(xml_serializer.serializeToString(doc));
	saveAs(
		  bb.getBlob("application/xhtml+xml;charset=" + document.characterSet)
		, (html_filename.value || html_filename.placeholder) + ".xhtml"
	);
}, false);

view.addEventListener("unload", function() {
	session.x_points = JSON.stringify(x_points);
	session.y_points = JSON.stringify(y_points);
	session.drag_points = JSON.stringify(drag_points);
	session.canvas_filename = canvas_filename.value;

	session.text = text.value;
	session.text_filename = text_filename.value;

	session.html = html.innerHTML;
	session.html_filename = html_filename.value;
}, false);
}(self));<commit_msg>Updated demo to use new Blob API<commit_after>/* FileSaver.js demo script
 * 2012-01-23
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See LICENSE.md
 */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/demo/demo.js */

(function(view) {
"use strict";
// The canvas drawing portion of the demo is based off the demo at
// http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/
var
	  document = view.document
	, $ = function(id) {
		return document.getElementById(id);
	}
	, session = view.sessionStorage
	// only get URL when necessary in case Blob.js hasn't defined it yet
	, get_blob = function() {
		return view.Blob;
	}

	, canvas = $("canvas")
	, canvas_options_form = $("canvas-options")
	, canvas_filename = $("canvas-filename")
	, canvas_clear_button = $("canvas-clear")

	, text = $("text")
	, text_options_form = $("text-options")
	, text_filename = $("text-filename")

	, html = $("html")
	, html_options_form = $("html-options")
	, html_filename = $("html-filename")

	, ctx = canvas.getContext("2d")
	, drawing = false
	, x_points = session.x_points || []
	, y_points = session.y_points || []
	, drag_points = session.drag_points || []
	, add_point = function(x, y, dragging) {
		x_points.push(x);
		y_points.push(y);
		drag_points.push(dragging);
	}
	, draw = function(){
		canvas.width = canvas.width;
		ctx.lineWidth = 6;
		ctx.lineJoin = "round";
		ctx.strokeStyle = "#000000";
		var
			  i = 0
			, len = x_points.length
		;
		for(; i < len; i++) {
			ctx.beginPath();
			if (i && drag_points[i]) {
				ctx.moveTo(x_points[i-1], y_points[i-1]);
			} else {
				ctx.moveTo(x_points[i]-1, y_points[i]);
			}
			ctx.lineTo(x_points[i], y_points[i]);
			ctx.closePath();
			ctx.stroke();
		}
	}
	, stop_drawing = function() {
		drawing = false;
	}

	// Title guesser and document creator available at https://gist.github.com/1059648
	, guess_title = function(doc) {
		var
			  h = "h6 h5 h4 h3 h2 h1".split(" ")
			, i = h.length
			, headers
			, header_text
		;
		while (i--) {
			headers = doc.getElementsByTagName(h[i]);
			for (var j = 0, len = headers.length; j < len; j++) {
				header_text = headers[j].textContent.trim();
				if (header_text) {
					return header_text;
				}
			}
		}
	}
	, doc_impl = document.implementation
	, create_html_doc = function(html) {
		var
			  dt = doc_impl.createDocumentType('html', null, null)
			, doc = doc_impl.createDocument("http://www.w3.org/1999/xhtml", "html", dt)
			, doc_el = doc.documentElement
			, head = doc_el.appendChild(doc.createElement("head"))
			, charset_meta = head.appendChild(doc.createElement("meta"))
			, title = head.appendChild(doc.createElement("title"))
			, body = doc_el.appendChild(doc.createElement("body"))
			, i = 0
			, len = html.childNodes.length
		;
		charset_meta.setAttribute("charset", html.ownerDocument.characterSet);
		for (; i < len; i++) {
			body.appendChild(doc.importNode(html.childNodes.item(i), true));
		}
		var title_text = guess_title(doc);
		if (title_text) {
			title.appendChild(doc.createTextNode(title_text));
		}
		return doc;
	}
;
canvas.width = 500;
canvas.height = 300;

  if (typeof x_points === "string") {
	x_points = JSON.parse(x_points);
} if (typeof y_points === "string") {
	y_points = JSON.parse(y_points);
} if (typeof drag_points === "string") {
	drag_points = JSON.parse(drag_points);
} if (session.canvas_filename) {
	canvas_filename.value = session.canvas_filename;
} if (session.text) {
	text.value = session.text;
} if (session.text_filename) {
	text_filename.value = session.text_filename;
} if (session.html) {
	html.innerHTML = session.html;
} if (session.html_filename) {
	html_filename.value = session.html_filename;
}

drawing = true;
draw();
drawing = false;

canvas_clear_button.addEventListener("click", function() {
	canvas.width = canvas.width;
	x_points.length =
	y_points.length =
	drag_points.length =
		0;
}, false);
canvas.addEventListener("mousedown", function(event) {
	drawing = true;
	add_point(event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop, false);
	draw();
}, false);
canvas.addEventListener("mousemove", function(event) {
	if (drawing) {
		add_point(event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop, true);
		draw();
	}
}, false);
canvas.addEventListener("mouseup", stop_drawing, false);
canvas.addEventListener("mouseout", stop_drawing, false);

canvas_options_form.addEventListener("submit", function(event) {
	event.preventDefault();
	canvas.toBlob(function(blob) {
		saveAs(
			  blob
			, (canvas_filename.value || canvas_filename.placeholder) + ".png"
		);
	}, "image/png");
}, false);

text_options_form.addEventListener("submit", function(event) {
	event.preventDefault();
	var
		  BB = get_blob();
		, bb = new BB(text.value || text.placeholder)
	;
	saveAs(
		  bb.getBlob("text/plain;charset=" + document.characterSet)
		, (text_filename.value || text_filename.placeholder) + ".txt"
	);
}, false);

html_options_form.addEventListener("submit", function(event) {
	event.preventDefault();
	var
		  BB = get_blob()
		, bb
		, xml_serializer = new XMLSerializer
		, doc = create_html_doc(html)
	;
	bb = new BB(xml_serializer.serializeToString(doc));
	saveAs(
		  bb.getBlob("application/xhtml+xml;charset=" + document.characterSet)
		, (html_filename.value || html_filename.placeholder) + ".xhtml"
	);
}, false);

view.addEventListener("unload", function() {
	session.x_points = JSON.stringify(x_points);
	session.y_points = JSON.stringify(y_points);
	session.drag_points = JSON.stringify(drag_points);
	session.canvas_filename = canvas_filename.value;

	session.text = text.value;
	session.text_filename = text_filename.value;

	session.html = html.innerHTML;
	session.html_filename = html_filename.value;
}, false);
}(self));
<|endoftext|>


<commit_before>Meteor.startup(function() {

  if (Meteor.users.find({}).count() === 0) {

    var adminIds = [54118672, 57771272, 32213572, 28932772, 87620262, 11527138, 8187187];

    Meteor.call('MeetupAPI', 'getMembers', {"group_urlname": "Meteor-Las-Vegas"}, function(err, response) {

      for (var i = 0, l = response.meta.count; i < l; i++) {
        var node = response.results[i];

        if(response.results[i].hasOwnProperty("photo") && response.results[i].photo.photo_link !== "") {
          var thumbnailUrl = response.results[i].photo.photo_link;
        } else {
          var thumbnailUrl = "/default-avatar.png";
        }

        var socialLinks = [];
        for (service in response.results[i].other_services) {
          if(service === "twitter") {
            var username = response.results[i].other_services['twitter']['identifier'];
            socialLinks.push({'service': 'twitter', 'url': 'https://twitter.com/' + username});
          } else if(service) {
            var url = response.results[i].other_services[service]['identifier'];
            socialLinks.push({'service': service, 'url': url});
          }
        }

        var userId = Meteor.users.insert({
          createdAt: new Date(),
          profile: {
            'meetupId': response.results[i].id,
            'name': response.results[i].name,
            'bio': response.results[i].bio,
            'meetupProfileUrl': response.results[i].link,
            'socialLinks': socialLinks,
            'thumbnailUrl': thumbnailUrl,
            'points': _.random(5, 250)
          },
          services: {
            meetup: {
              id: response.results[i].id
            }
          }
        });

        if (_(adminIds).contains(response.results[i].id)) {
          Roles.addUsersToRoles(userId, ['admin'])
        }

      }
    });

  }

});
<commit_msg>more realistic points for seed users<commit_after>Meteor.startup(function() {

  if (Meteor.users.find({}).count() === 0) {

    var adminIds = [54118672, 57771272, 32213572, 28932772, 87620262, 11527138, 8187187];

    Meteor.call('MeetupAPI', 'getMembers', {"group_urlname": "Meteor-Las-Vegas"}, function(err, response) {

      for (var i = 0, l = response.meta.count; i < l; i++) {
        var node = response.results[i];

        if(response.results[i].hasOwnProperty("photo") && response.results[i].photo.photo_link !== "") {
          var thumbnailUrl = response.results[i].photo.photo_link;
        } else {
          var thumbnailUrl = "/default-avatar.png";
        }

        var socialLinks = [];
        for (service in response.results[i].other_services) {
          if(service === "twitter") {
            var username = response.results[i].other_services['twitter']['identifier'];
            socialLinks.push({'service': 'twitter', 'url': 'https://twitter.com/' + username});
          } else if(service) {
            var url = response.results[i].other_services[service]['identifier'];
            socialLinks.push({'service': service, 'url': url});
          }
        }

        var userId = Meteor.users.insert({
          createdAt: new Date(),
          profile: {
            'meetupId': response.results[i].id,
            'name': response.results[i].name,
            'bio': response.results[i].bio,
            'meetupProfileUrl': response.results[i].link,
            'socialLinks': socialLinks,
            'thumbnailUrl': thumbnailUrl,
            'points': _.random(5, 25)
          },
          services: {
            meetup: {
              id: response.results[i].id
            }
          }
        });

        if (_(adminIds).contains(response.results[i].id)) {
          Roles.addUsersToRoles(userId, ['admin']);
          Meteor.users.update({_id: userId}, {$set: {'profile.points': _.random(100, 500)}});
        }

      }
    });

  }

});
<|endoftext|>


<commit_before>// Copyright 2018-2019, University of Colorado Boulder

/**
 * Block types for EFAC intro
 *
 * @author Chris Klusendorf
 */
define( require => {
  'use strict';

  // modules
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );

  // @public
  var BlockType = {
    IRON: 'IRON',
    BRICK: 'BRICK'
  };

  // verify that enum is immutable, without the runtime penalty in production code
  if ( assert ) { Object.freeze( BlockType ); }

  return energyFormsAndChanges.register( 'BlockType', BlockType );
} );<commit_msg>Convert to ES6, see https://github.com/phetsims/energy-forms-and-changes/issues/211<commit_after>// Copyright 2018-2019, University of Colorado Boulder

/**
 * Block types for EFAC intro
 *
 * @author Chris Klusendorf
 */
define( require => {
  'use strict';

  // modules
  const energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );

  // @public
  const BlockType = {
    IRON: 'IRON',
    BRICK: 'BRICK'
  };

  // verify that enum is immutable, without the runtime penalty in production code
  if ( assert ) { Object.freeze( BlockType ); }

  return energyFormsAndChanges.register( 'BlockType', BlockType );
} );<|endoftext|>


<commit_before>const RequestError = require('qnode-error').RequestError;
const RuleTree = require('./RuleTree');
const Template = require('./Template');

module.exports = class RuleEngine {

    constructor(name, config) {
        this._name = name;
        this._config = config;
    }

    init() {
        this._ruleTree = new RuleTree(this._name + 'RuleTree');

        this._initRules();
    }

    _initRules() {
        const rules = this._config.rules;
        for (const ruleName in rules) {
            const rule = rules[ruleName];
            this.put(rule);
        }
    }

    put(rule) {
        this.prepareRule(rule);
        this._ruleTree.put(rule);
    }

    _buildRequestData(req) {
        return {
            charset: req.charset,
            ip: req.ip,
            method: req.method,
            path: req.path,
            protocol: req.protocol,
            q: req.query,
            url: req.url
        };
    }

    static renderMockResponse(request, ruleResponse, responseToMock) {
        if (ruleResponse.header) Object.assign(responseToMock.header, ruleResponse.header);

        responseToMock.type = ruleResponse.type;
        responseToMock.status = ruleResponse.status;

        responseToMock.body = Template.render(ruleResponse.body, request);

        //if (ruleResponse.redirect) responseToMock.redirect(ruleResponse.redirect);
    }

    static determineTimeToDelay(ruleResponse) {
        let delay = ruleResponse.delay + ruleResponse.delayFix;
        if (delay && delay > 0) {
            return delay;
        }
        return 0;
    }

    /**
     * looks for matched rule, raise error if matches nothing
     * @param {object} request
     */
    loadMatchedRule(request) {
        this._logger.debug('request: %s', request);
        const r = this._findMatchedRule(request);
        if (!r) {
            throw new RequestError('NO_RULE_MATCHES');
        }
        return r;
    }

    _findMatchedRule(request) {
        const candidateRules = this._ruleTree.match(request.method, request.path);
        this._logger.debug('candidate rules: %s', candidateRules);

        return this._filterRule(request, candidateRules);
    }

    _filterRule(req, candidateRules) {
        return (candidateRules.length > 0) ? candidateRules[0] : null;
    }

    prepareRule() {
        // dummy
    }

    /**
     * return mocked response for incoming request.
     *
     * it looks for matched rule, rendering mock response using the rule, and
     * executes hooks around the response.
     *
     * @param {object} rnr request and response
     */
    async mock(rnr) {
        const rule = this.loadMatchedRule(rnr.request);

        const cb = rule.hook;

        if (cb && cb.needCallBefore) {
            await cb.callBefore(rnr.requestAndResponse);
        }

        await this._mockResponse(rnr, rule);

        if (cb && cb.needCallAfter) {
            await cb.callAfter(rnr);
        }
    }

    /**
     * return mocked response, and, delay somewhile if configured
     *
     * @param {object} rnr request and response
     * @param {object} rule
     */
    async _mockResponse(rnr, rule) {
        const ruleResponse = rule.response;
        RuleEngine.renderMockResponse(rnr.request, ruleResponse, rnr.response);

        //TODO: be aware of how the hook delay interferes the response delay
        let delay = RuleEngine.determineTimeToDelay(ruleResponse);
        if (delay) {
            return new Promise(resolve => setTimeout(resolve, delay));
        }

        return Promise.resolve();
    }

}<commit_msg>Rename the local variable ‘cb’ to ‘hook’<commit_after>const RequestError = require('qnode-error').RequestError;
const RuleTree = require('./RuleTree');
const Template = require('./Template');

module.exports = class RuleEngine {

    constructor(name, config) {
        this._name = name;
        this._config = config;
    }

    init() {
        this._ruleTree = new RuleTree(this._name + 'RuleTree');

        this._initRules();
    }

    _initRules() {
        const rules = this._config.rules;
        for (const ruleName in rules) {
            const rule = rules[ruleName];
            this.put(rule);
        }
    }

    put(rule) {
        this.prepareRule(rule);
        this._ruleTree.put(rule);
    }

    _buildRequestData(req) {
        return {
            charset: req.charset,
            ip: req.ip,
            method: req.method,
            path: req.path,
            protocol: req.protocol,
            q: req.query,
            url: req.url
        };
    }

    static renderMockResponse(request, ruleResponse, responseToMock) {
        if (ruleResponse.header) Object.assign(responseToMock.header, ruleResponse.header);

        responseToMock.type = ruleResponse.type;
        responseToMock.status = ruleResponse.status;

        responseToMock.body = Template.render(ruleResponse.body, request);

        //if (ruleResponse.redirect) responseToMock.redirect(ruleResponse.redirect);
    }

    static determineTimeToDelay(ruleResponse) {
        let delay = ruleResponse.delay + ruleResponse.delayFix;
        if (delay && delay > 0) {
            return delay;
        }
        return 0;
    }

    /**
     * looks for matched rule, raise error if matches nothing
     * @param {object} request
     */
    loadMatchedRule(request) {
        this._logger.debug('request: %s', request);
        const r = this._findMatchedRule(request);
        if (!r) {
            throw new RequestError('NO_RULE_MATCHES');
        }
        return r;
    }

    _findMatchedRule(request) {
        const candidateRules = this._ruleTree.match(request.method, request.path);
        this._logger.debug('candidate rules: %s', candidateRules);

        return this._filterRule(request, candidateRules);
    }

    _filterRule(req, candidateRules) {
        return (candidateRules.length > 0) ? candidateRules[0] : null;
    }

    prepareRule() {
        // dummy
    }

    /**
     * return mocked response for incoming request.
     *
     * it looks for matched rule, rendering mock response using the rule, and
     * executes hooks around the response.
     *
     * @param {object} rnr request and response
     */
    async mock(rnr) {
        const rule = this.loadMatchedRule(rnr.request);

        const hook = rule.hook;

        if (hook && hook.needCallBefore) {
            await hook.callBefore(rnr.requestAndResponse);
        }

        await this._mockResponse(rnr, rule);

        if (hook && hook.needCallAfter) {
            await hook.callAfter(rnr);
        }
    }

    /**
     * return mocked response, and, delay somewhile if configured
     *
     * @param {object} rnr request and response
     * @param {object} rule
     */
    async _mockResponse(rnr, rule) {
        const ruleResponse = rule.response;
        RuleEngine.renderMockResponse(rnr.request, ruleResponse, rnr.response);

        //TODO: be aware of how the hook delay interferes the response delay
        let delay = RuleEngine.determineTimeToDelay(ruleResponse);
        if (delay) {
            return new Promise(resolve => setTimeout(resolve, delay));
        }

        return Promise.resolve();
    }

}<|endoftext|>


<commit_before>define([ "dialog/dialog", "util/lang", "text!layouts/header.html", "ui/user-data", "ui/webmakernav/webmakernav", "ui/widget/tooltip" ],
  function( Dialog, Lang, HEADER_TEMPLATE, UserData, WebmakerBar, ToolTip ) {

  return function( butter, options ){

    options = options || {};

    var TOOLTIP_NAME = "name-error-header-tooltip";

    var _this = this,
        _userData = new UserData( butter, options ),
        _rootElement = Lang.domFragment( HEADER_TEMPLATE, ".butter-header" ),
        _webmakerNavBar = _rootElement.querySelector( "#webmaker-nav" ),
        _saveButton = _rootElement.querySelector( ".butter-save-btn"),
        _projectTitle = _rootElement.querySelector( ".butter-project-title" ),
        _projectName = _projectTitle.querySelector( ".butter-project-name" ),
        _previewBtn = _rootElement.querySelector( ".butter-preview-btn" ),
        _tabzilla = _rootElement.querySelector( "#tabzilla" ),
        _noProjectNameToolTip,
        _projectTitlePlaceHolderText = _projectName.innerHTML,
        _webmakerNav;

    // create a tooltip for the plrojectName element
    ToolTip.create({
      title: "header-title-tooltip",
      message: "Change the name of your project",
      element: _projectTitle,
      top: "60px"
    });

    _this.element = _rootElement;

    ToolTip.apply( _projectTitle );

    _tabzilla.addEventListener( "click", function() {
      document.body.classList.toggle( "tabzilla-open" );
    }, false );

    function toggleSaveButton( on ) {
      if ( on ) {
        _saveButton.classList.remove( "butter-disabled" );
      } else {
        _saveButton.classList.add( "butter-disabled" );
      }
    }

    function togglePreviewButton( on ) {
      if ( on ) {
        _previewBtn.classList.remove( "butter-disabled" );
        _previewBtn.href = butter.project.publishUrl;
        _previewBtn.onclick = function() {
          return true;
        };
      } else {
        _previewBtn.classList.add( "butter-disabled" );
        _previewBtn.href = "";
        _previewBtn.onclick = function() {
          return false;
        };
      }
    }

    this.views = {
      dirty: function() {
        togglePreviewButton( false );
        toggleSaveButton( true );
      },
      clean: function() {
        togglePreviewButton( true );
        toggleSaveButton( false );
      },
      login: function() {
        togglePreviewButton( false );
        toggleSaveButton( false );
        _previewBtn.style.display = "";
        _projectTitle.style.display = "";
        _saveButton.innerHTML = "Save";
      },
      logout: function() {
        togglePreviewButton( false );
        toggleSaveButton( true );
        _previewBtn.style.display = "none";
        _projectTitle.style.display = "none";
        _saveButton.innerHTML = "Sign in to save";
      }
    };

    function feedbackCallback() {
      var dialog = Dialog.spawn( "feedback" );
      dialog.open();
    }

    _webmakerNav = new WebmakerBar({
      container: _webmakerNavBar,
      onLogin: _userData.authenticationRequired,
      onLogout: _userData.logout,
      feedbackCallback: feedbackCallback
    });

    function onLogin() {
      _webmakerNav.views.login( butter.cornfield.username() );
    }

    butter.listen( "autologinsucceeded", onLogin, false );
    butter.listen( "authenticated", onLogin, false );
    butter.listen( "logout", _webmakerNav.views.logout, false );

    function destroyToolTip() {
      if ( _noProjectNameToolTip && !_noProjectNameToolTip.destroyed ) {
        _projectTitle.removeEventListener( "mouseover", destroyToolTip, false );
        _noProjectNameToolTip.destroy();
      }
    }

    function prepare() {
      function afterSave() {
        butter.editor.openEditor( "share-properties" );
        togglePreviewButton( true );
      }

      if ( !butter.project.isSaved ) {
        // If saving fails, restore the "Save" button so the user can try again.
        _userData.save( function() { afterSave(); },
                        function() { toggleSaveButton( true );
                                     togglePreviewButton( false ); } );
      } else {
        afterSave();
      }
    }

    function onKeyPress( e ) {
      var node = _projectTitle.querySelector( ".butter-project-name" );

      // if this wasn't the 'enter' key, return early
      if ( e.keyCode !== 13 ) {
        return;
      }

      node.blur();
      node.removeEventListener( "keypress", onKeyPress, false );
    }

    /*
     * Function: checkProjectName
     *
     * Checks whether the current projects name is a valid one or not.
     * @returns boolean value representing whether or not the current project name is valid
     */
    function checkProjectName( name ) {
      return !!name && name !== _projectTitlePlaceHolderText;
    }

    function nameError() {
      destroyToolTip();

      _projectTitle.addEventListener( "mouseover", destroyToolTip, false );

      ToolTip.create({
        name: TOOLTIP_NAME,
        message: "Please give your project a name before saving",
        hidden: false,
        element: _projectTitle,
        top: "50px",
        error: true
      });

      _noProjectNameToolTip = ToolTip.get( TOOLTIP_NAME );
    }

    function onBlur() {
      var node = _projectTitle.querySelector( ".butter-project-name" );
      node.removeEventListener( "blur", onBlur, false );

      _projectName.textContent = node.value || _projectTitlePlaceHolderText;
      if( checkProjectName( _projectName.textContent ) ) {
        butter.project.name = _projectName.textContent;
        _userData.authenticationRequired( prepare );
      } else {
        nameError();
      }

      _projectTitle.replaceChild( _projectName, node );
      _projectTitle.addEventListener( "click", projectNameClick, false );
    }

    _saveButton.addEventListener( "click", function( e ) {
      if ( !butter.cornfield.authenticated() ) {
        _userData.authenticationRequired();
      }
      else if ( butter.project.isSaved ) {
        return;
      }
      else if ( checkProjectName( butter.project.name ) ) {
        _userData.authenticationRequired( prepare, nameError );
        return;
      }
      else {
        nameError();
      }
    }, false );

    function projectNameClick( e ) {
      var input = document.createElement( "input" );

      input.type = "text";

      input.placeholder = _projectTitlePlaceHolderText;
      input.classList.add( "butter-project-name" );
      input.value = _projectName.textContent !== _projectTitlePlaceHolderText ? _projectName.textContent : "";
      _projectTitle.replaceChild( input, _projectName );
      _projectTitle.removeEventListener( "click", projectNameClick, false );
      input.focus();
      input.addEventListener( "blur", onBlur, false );
      input.addEventListener( "keypress", onKeyPress, false );
    }

    _projectName.addEventListener( "click", projectNameClick, false );

    this.attachToDOM = function() {
      document.body.classList.add( "butter-header-spacing" );
      document.body.insertBefore( _rootElement, document.body.firstChild );
    };

    butter.listen( "autologinsucceeded", _this.views.login, false );
    butter.listen( "authenticated", _this.views.login, false );
    butter.listen( "logout", _this.views.logout, false );

    //Default view
    _this.views.logout();

    butter.listen( "projectsaved", function() {
      // Disable "Save" button
      _this.views.clean();
      _projectName.textContent = butter.project.name;
    });
    butter.listen( "projectchanged", function() {
      // Re-enable "Save" button to indicate things are not saved
      _this.views.dirty();
    });
    butter.listen( "ready", function() {
      if ( butter.project.name ) {
        _projectName.textContent = butter.project.name;
      }
    });

  };
});
<commit_msg>[#2510] Ensure save button listener isn't always active. Ensure save button has proper state when loading a remix project. Ensure preview button has proper state always when loading projects from dashboard<commit_after>define([ "dialog/dialog", "util/lang", "text!layouts/header.html", "ui/user-data", "ui/webmakernav/webmakernav", "ui/widget/tooltip" ],
  function( Dialog, Lang, HEADER_TEMPLATE, UserData, WebmakerBar, ToolTip ) {

  return function( butter, options ){

    options = options || {};

    var TOOLTIP_NAME = "name-error-header-tooltip";

    var _this = this,
        _userData = new UserData( butter, options ),
        _rootElement = Lang.domFragment( HEADER_TEMPLATE, ".butter-header" ),
        _webmakerNavBar = _rootElement.querySelector( "#webmaker-nav" ),
        _saveButton = _rootElement.querySelector( ".butter-save-btn"),
        _projectTitle = _rootElement.querySelector( ".butter-project-title" ),
        _projectName = _projectTitle.querySelector( ".butter-project-name" ),
        _previewBtn = _rootElement.querySelector( ".butter-preview-btn" ),
        _tabzilla = _rootElement.querySelector( "#tabzilla" ),
        _noProjectNameToolTip,
        _projectTitlePlaceHolderText = _projectName.innerHTML,
        _webmakerNav;

    // create a tooltip for the plrojectName element
    ToolTip.create({
      title: "header-title-tooltip",
      message: "Change the name of your project",
      element: _projectTitle,
      top: "60px"
    });

    _this.element = _rootElement;

    ToolTip.apply( _projectTitle );

    _tabzilla.addEventListener( "click", function() {
      document.body.classList.toggle( "tabzilla-open" );
    }, false );

    function saveProject( e ) {
      if ( !butter.cornfield.authenticated() ) {
        _userData.authenticationRequired();
      }
      else if ( butter.project.isSaved ) {
        return;
      }
      else if ( checkProjectName( butter.project.name ) ) {
        _userData.authenticationRequired( prepare, nameError );
        return;
      }
      else {
        nameError();
      }
    }

    function toggleSaveButton( on ) {
      if ( on ) {
        _saveButton.classList.remove( "butter-disabled" );
        _saveButton.addEventListener( "click", saveProject, false );
      } else {
        _saveButton.classList.add( "butter-disabled" );
        _saveButton.removeEventListener( "click", saveProject, false );
      }
    }

    function togglePreviewButton( on ) {
      if ( on ) {
        _previewBtn.classList.remove( "butter-disabled" );
        _previewBtn.href = butter.project.publishUrl;
        _previewBtn.onclick = function() {
          return true;
        };
      } else {
        _previewBtn.classList.add( "butter-disabled" );
        _previewBtn.href = "";
        _previewBtn.onclick = function() {
          return false;
        };
      }
    }

    this.views = {
      dirty: function() {
        togglePreviewButton( false );
        toggleSaveButton( true );
      },
      clean: function() {
        togglePreviewButton( true );
        toggleSaveButton( false );
      },
      login: function() {
        var isSaved = butter.project.isSaved;

        _previewBtn.style.display = "";
        _projectTitle.style.display = "";
        _saveButton.innerHTML = "Save";

        togglePreviewButton( isSaved );
        toggleSaveButton( !isSaved );
      },
      logout: function() {
        togglePreviewButton( false );
        toggleSaveButton( true );
        _previewBtn.style.display = "none";
        _projectTitle.style.display = "none";
        _saveButton.innerHTML = "Sign in to save";
      }
    };

    function feedbackCallback() {
      var dialog = Dialog.spawn( "feedback" );
      dialog.open();
    }

    _webmakerNav = new WebmakerBar({
      container: _webmakerNavBar,
      onLogin: _userData.authenticationRequired,
      onLogout: _userData.logout,
      feedbackCallback: feedbackCallback
    });

    function onLogin() {
      _webmakerNav.views.login( butter.cornfield.username() );
    }

    butter.listen( "autologinsucceeded", onLogin, false );
    butter.listen( "authenticated", onLogin, false );
    butter.listen( "logout", _webmakerNav.views.logout, false );

    function destroyToolTip() {
      if ( _noProjectNameToolTip && !_noProjectNameToolTip.destroyed ) {
        _projectTitle.removeEventListener( "mouseover", destroyToolTip, false );
        _noProjectNameToolTip.destroy();
      }
    }

    function prepare() {
      function afterSave() {
        butter.editor.openEditor( "share-properties" );
        togglePreviewButton( true );
      }

      if ( !butter.project.isSaved ) {
        // If saving fails, restore the "Save" button so the user can try again.
        _userData.save( function() { afterSave(); },
                        function() { toggleSaveButton( true );
                                     togglePreviewButton( false ); } );
      } else {
        afterSave();
      }
    }

    function onKeyPress( e ) {
      var node = _projectTitle.querySelector( ".butter-project-name" );

      // if this wasn't the 'enter' key, return early
      if ( e.keyCode !== 13 ) {
        return;
      }

      node.blur();
      node.removeEventListener( "keypress", onKeyPress, false );
    }

    /*
     * Function: checkProjectName
     *
     * Checks whether the current projects name is a valid one or not.
     * @returns boolean value representing whether or not the current project name is valid
     */
    function checkProjectName( name ) {
      return !!name && name !== _projectTitlePlaceHolderText;
    }

    function nameError() {
      destroyToolTip();

      _projectTitle.addEventListener( "mouseover", destroyToolTip, false );

      ToolTip.create({
        name: TOOLTIP_NAME,
        message: "Please give your project a name before saving",
        hidden: false,
        element: _projectTitle,
        top: "50px",
        error: true
      });

      _noProjectNameToolTip = ToolTip.get( TOOLTIP_NAME );
    }

    function onBlur() {
      var node = _projectTitle.querySelector( ".butter-project-name" );
      node.removeEventListener( "blur", onBlur, false );

      _projectName.textContent = node.value || _projectTitlePlaceHolderText;
      if( checkProjectName( _projectName.textContent ) ) {
        butter.project.name = _projectName.textContent;
        _userData.authenticationRequired( prepare );
      } else {
        nameError();
      }

      _projectTitle.replaceChild( _projectName, node );
      _projectTitle.addEventListener( "click", projectNameClick, false );
    }

    function projectNameClick( e ) {
      var input = document.createElement( "input" );

      input.type = "text";

      input.placeholder = _projectTitlePlaceHolderText;
      input.classList.add( "butter-project-name" );
      input.value = _projectName.textContent !== _projectTitlePlaceHolderText ? _projectName.textContent : "";
      _projectTitle.replaceChild( input, _projectName );
      _projectTitle.removeEventListener( "click", projectNameClick, false );
      input.focus();
      input.addEventListener( "blur", onBlur, false );
      input.addEventListener( "keypress", onKeyPress, false );
    }

    _projectName.addEventListener( "click", projectNameClick, false );

    this.attachToDOM = function() {
      document.body.classList.add( "butter-header-spacing" );
      document.body.insertBefore( _rootElement, document.body.firstChild );
    };

    butter.listen( "autologinsucceeded", _this.views.login, false );
    butter.listen( "authenticated", _this.views.login, false );
    butter.listen( "logout", _this.views.logout, false );

    //Default view
    _this.views.logout();

    butter.listen( "projectsaved", function() {
      // Disable "Save" button
      _this.views.clean();
      _projectName.textContent = butter.project.name;
    });
    butter.listen( "projectchanged", function() {
      // Re-enable "Save" button to indicate things are not saved
      _this.views.dirty();
    });
    butter.listen( "ready", function() {
      if ( butter.project.name ) {
        _projectName.textContent = butter.project.name;
      }
    });

  };
});
<|endoftext|>


<commit_before>/*
 * biojs-io-biom
 * https://github.com/iimog/biojs-io-biom
 *
 * Copyright (c) 2016 Markus J. Ankenbrand
 * Licensed under the MIT license.
 */

/**
 * Version
 * @type {string} version of this module
 */
export const VERSION = '0.1.0';

/**
 * Default Biom Object for empty initialization
 * @type {{
 * id: null,
 * format: string,
 * format_url: string,
 * type: string,
 * generated_by: string,
 * date: Date,
 * rows: Array,
 * columns: Array,
 * matrix_type: string,
 * matrix_element_type: string,
 * shape: number[],
 * data: Array
 * }}
 */
export const DEFAULT_BIOM = {
    id: null,
    format: 'Biological Observation Matrix 1.0.0',
    format_url: 'http://biom-format.org',
    type: 'OTU table',
    generated_by: `biojs-io-biom v${VERSION}`,
    date: null, // will be set to Date.now() in the constructor
    rows: [],
    columns: [],
    matrix_type: 'sparse',
    matrix_element_type: 'float',
    shape: [0,0],
    data: []
};

/**
 * @class Biom
 */
export class Biom {
    /**
     * constructor
     * @param _id
     * @param _format
     * @param _format_url
     * @param _type
     * @param _generated_by
     * @param _date
     * @param _rows
     * @param _columns
     * @param _matrix_type
     * @param _matrix_element_type
     * @param _shape
     * @param _data
     */
    constructor({
        id: _id = null,
        format: _format = DEFAULT_BIOM.format,
        format_url: _format_url = DEFAULT_BIOM.format_url,
        type: _type = DEFAULT_BIOM.type,
        generated_by: _generated_by = DEFAULT_BIOM.generated_by,
        date: _date = Date.now(),
        rows: _rows = DEFAULT_BIOM.rows,
        columns: _columns = DEFAULT_BIOM.columns,
        matrix_type: _matrix_type = DEFAULT_BIOM.matrix_type,
        matrix_element_type:
            _matrix_element_type = DEFAULT_BIOM.matrix_element_type,
        shape: _shape = DEFAULT_BIOM.shape,
        data: _data = DEFAULT_BIOM.data
    } = {}){
        this._id = _id;
        this._format = _format;
        this._format_url = _format_url;
        this._type = _type;
        this._generated_by = _generated_by;
        this._date = _date;
        this._rows = _rows;
        this._columns = _columns;
        this._matrix_type = _matrix_type;
        this._matrix_element_type = _matrix_element_type;
        this._shape = _shape;
        this._data = _data;
    }

    /**
     * Getter for id
     * @returns {string} - A field that can be used to id a table (or null)
     */
    get id(){
        return this._id;
    }

    /**
     * Getter for format
     * @returns {string} - The name and version of the current biom format
     */
    get format(){
        return this._format;
    }

    /**
     * Getter for format_url
     * @returns {string} - A string with a static URL providing format details
     */
    get format_url(){
        return this._format_url;
    }

    /**
     * Getter for type
     * @returns {string} - Table type (a controlled vocabulary)
     *                     Acceptable values:
     *                       "OTU table"
     *                       "Pathway table"
     *                       "Function table"
     *                       "Ortholog table"
     *                       "Gene table"
     *                       "Metabolite table"
     *                       "Taxon table"
     */
    get type(){
        return this._type;
    }

    /**
     * Getter for generated_by
     * @returns {string} - Package and revision that built the table
     */
    get generated_by(){
        return this._generated_by;
    }

    /**
     * Getter for date
     * @returns {Date} - Date the table was built (ISO 8601 format)
     */
    get date(){
        return this._date;
    }

    /**
     * Getter for rows
     * @returns {Array} - An ORDERED list of obj describing the rows
     */
    get rows(){
        return this._rows;
    }

    /**
     * Getter for columns
     * @returns {Array} - An ORDERED list of obj describing the columns
     */
    get columns(){
        return this._columns;
    }

    /**
     * Getter for matrix_type
     * @returns {string} - Type of matrix data representation
     *                     (a controlled vocabulary) Acceptable values:
     *                       "sparse" : only non-zero values are specified
     *                       "dense" : every element must be specified
     */
    get matrix_type(){
        return this._matrix_type;
    }

    /**
     * Getter for matrix_element_type
     * @returns {string} - Value type in matrix (a controlled vocabulary)
     *                     Acceptable values:
     *                       "int" : integer
     *                       "float" : floating point
     *                       "unicode" : unicode string
     */
    get matrix_element_type(){
        return this._matrix_element_type;
    }

    /**
     * Getter for shape
     * @returns {Array} - the number of rows and number of columns in data
     */
    get shape(){
        return this._shape;
    }

    /**
     * Getter for data
     * @returns {Array} - counts of observations by sample
     *                   if matrix_type is "sparse", [[row, column, value],
     *                                                 [row, column, value],
     *                                                                  ...]
     *                   if matrix_type is "dense", [[value, value, value, ...],
     *                                               [value, value, value, ...],
     *                                                                      ...]
     */
    get data(){
        return this._data;
    }
}
<commit_msg>Add id setter<commit_after>/*
 * biojs-io-biom
 * https://github.com/iimog/biojs-io-biom
 *
 * Copyright (c) 2016 Markus J. Ankenbrand
 * Licensed under the MIT license.
 */

/**
 * Version
 * @type {string} version of this module
 */
export const VERSION = '0.1.0';

/**
 * Default Biom Object for empty initialization
 * @type {{
 * id: null,
 * format: string,
 * format_url: string,
 * type: string,
 * generated_by: string,
 * date: Date,
 * rows: Array,
 * columns: Array,
 * matrix_type: string,
 * matrix_element_type: string,
 * shape: number[],
 * data: Array
 * }}
 */
export const DEFAULT_BIOM = {
    id: null,
    format: 'Biological Observation Matrix 1.0.0',
    format_url: 'http://biom-format.org',
    type: 'OTU table',
    generated_by: `biojs-io-biom v${VERSION}`,
    date: null, // will be set to Date.now() in the constructor
    rows: [],
    columns: [],
    matrix_type: 'sparse',
    matrix_element_type: 'float',
    shape: [0,0],
    data: []
};

/**
 * @class Biom
 */
export class Biom {
    /**
     * constructor
     * @param _id
     * @param _format
     * @param _format_url
     * @param _type
     * @param _generated_by
     * @param _date
     * @param _rows
     * @param _columns
     * @param _matrix_type
     * @param _matrix_element_type
     * @param _shape
     * @param _data
     */
    constructor({
        id: _id = null,
        format: _format = DEFAULT_BIOM.format,
        format_url: _format_url = DEFAULT_BIOM.format_url,
        type: _type = DEFAULT_BIOM.type,
        generated_by: _generated_by = DEFAULT_BIOM.generated_by,
        date: _date = Date.now(),
        rows: _rows = DEFAULT_BIOM.rows,
        columns: _columns = DEFAULT_BIOM.columns,
        matrix_type: _matrix_type = DEFAULT_BIOM.matrix_type,
        matrix_element_type:
            _matrix_element_type = DEFAULT_BIOM.matrix_element_type,
        shape: _shape = DEFAULT_BIOM.shape,
        data: _data = DEFAULT_BIOM.data
    } = {}){
        this._id = _id;
        this._format = _format;
        this._format_url = _format_url;
        this._type = _type;
        this._generated_by = _generated_by;
        this._date = _date;
        this._rows = _rows;
        this._columns = _columns;
        this._matrix_type = _matrix_type;
        this._matrix_element_type = _matrix_element_type;
        this._shape = _shape;
        this._data = _data;
    }

    /**
     * Getter for id
     * @returns {string} - A field that can be used to id a table (or null)
     */
    get id(){
        return this._id;
    }

    /**
     * Setter for id
     * @param id {string} - Update id to string or null
     */
    set id(id){
        if(id !== null && typeof id !== "string"){
            throw new TypeError("id must be string or null");
        }
        this._id = id;
    }

    /**
     * Getter for format
     * @returns {string} - The name and version of the current biom format
     */
    get format(){
        return this._format;
    }

    /**
     * Getter for format_url
     * @returns {string} - A string with a static URL providing format details
     */
    get format_url(){
        return this._format_url;
    }

    /**
     * Getter for type
     * @returns {string} - Table type (a controlled vocabulary)
     *                     Acceptable values:
     *                       "OTU table"
     *                       "Pathway table"
     *                       "Function table"
     *                       "Ortholog table"
     *                       "Gene table"
     *                       "Metabolite table"
     *                       "Taxon table"
     */
    get type(){
        return this._type;
    }

    /**
     * Getter for generated_by
     * @returns {string} - Package and revision that built the table
     */
    get generated_by(){
        return this._generated_by;
    }

    /**
     * Getter for date
     * @returns {Date} - Date the table was built (ISO 8601 format)
     */
    get date(){
        return this._date;
    }

    /**
     * Getter for rows
     * @returns {Array} - An ORDERED list of obj describing the rows
     */
    get rows(){
        return this._rows;
    }

    /**
     * Getter for columns
     * @returns {Array} - An ORDERED list of obj describing the columns
     */
    get columns(){
        return this._columns;
    }

    /**
     * Getter for matrix_type
     * @returns {string} - Type of matrix data representation
     *                     (a controlled vocabulary) Acceptable values:
     *                       "sparse" : only non-zero values are specified
     *                       "dense" : every element must be specified
     */
    get matrix_type(){
        return this._matrix_type;
    }

    /**
     * Getter for matrix_element_type
     * @returns {string} - Value type in matrix (a controlled vocabulary)
     *                     Acceptable values:
     *                       "int" : integer
     *                       "float" : floating point
     *                       "unicode" : unicode string
     */
    get matrix_element_type(){
        return this._matrix_element_type;
    }

    /**
     * Getter for shape
     * @returns {Array} - the number of rows and number of columns in data
     */
    get shape(){
        return this._shape;
    }

    /**
     * Getter for data
     * @returns {Array} - counts of observations by sample
     *                   if matrix_type is "sparse", [[row, column, value],
     *                                                 [row, column, value],
     *                                                                  ...]
     *                   if matrix_type is "dense", [[value, value, value, ...],
     *                                               [value, value, value, ...],
     *                                                                      ...]
     */
    get data(){
        return this._data;
    }
}
<|endoftext|>


<commit_before>
var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },

  getInitialState: function() {
    return {data: []};
  },

  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },

  render: function() {
    return (

        <EventTable data={this.state.data} url={this.props.url}/>

    );
  }
});

var EventDeleteBtn = React.createClass({
  handleClick: function(e) {
    console.log("clicked " + this.props.event.venue);
  },
  render: function() {
    return (

<button onClick={this.handleClick}>Delete</button>

    );
  }
});

var EventRow = React.createClass({
  render: function() {
    return (

        {this.props.event.date}
        {this.props.event.time}
        {this.props.event.venue}
        {this.props.event.attendees}
        {this.props.event.rating}
        <EventDeleteBtn event={this.props.event}></EventDeleteBtn>

    );
  }
});

var EventTable = React.createClass({
  render: function() {
    var rows = [];
    this.props.data.forEach(function(event) {
      rows.push(<EventRow event={event} key={event._id}/>);
    });
    return (

            Date
            Time
            Venue
            Attendees
            Rating

{rows}

    );
  }
});

ReactDOM.render(
  <CommentBox url="/events" pollInterval={2000} />,
  document.getElementById('content')
);      <commit_msg>Passed url down to EventRow<commit_after>
var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },

  getInitialState: function() {
    return {data: []};
  },

  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },

  render: function() {
    return (

        <EventTable data={this.state.data} url={this.props.url}/>

    );
  }
});

var EventDeleteBtn = React.createClass({
  handleClick: function(e) {
    console.log("clicked " + this.props.event.venue);
  },
  render: function() {
    return (

<button onClick={this.handleClick}>Delete</button>

    );
  }
});

var EventRow = React.createClass({
  render: function() {
    return (

        {this.props.event.date}
        {this.props.event.time}
        {this.props.event.venue}
        {this.props.event.attendees}
        {this.props.event.rating}
        <EventDeleteBtn event={this.props.event}></EventDeleteBtn>

    );
  }
});

var EventTable = React.createClass({
  render: function() {
    var rows = [];
    var baseUrl = this.props.url;

    this.props.data.forEach(function(event) {
      rows.push(<EventRow event={event} key={event._id} url={baseUrl}/>);
    });
    return (

            Date
            Time
            Venue
            Attendees
            Rating

{rows}

    );
  }
});

ReactDOM.render(
  <CommentBox url="/events" pollInterval={2000} />,
  document.getElementById('content')
);      <|endoftext|>


<commit_before>'use strict';

import NotificationComponent from '../main'; // for direct API usage

const pt = '1.0|idm|idm|piid=ffffffff53da3cb3e4b0eaaddd576877&sessid=beeaa30c981b41fbbb52dc3937006aa2|2016-05-11T19:09:18+00:00|2016-05-11T22:09:18+00:00|823b1d93bedb555b4a89f9807fe01b51';

const AppHeaderConfig = {
	// NotificationAPI
	nfApiUrl: 'https://notifications-api.stg-prsn.com',
	nfContentTypeHeader: 'application/json',
	nfPiToken: pt,
	nfRecipientId: 'ffffffff560c1a1ee4b04ebf43118c60',

	// CoachmarkAPI
	cmApiUrl: 'http://localhost:8080',
	cmContentTypeHeader: 'application/json',
	cmPiToken: pt,

	// FeedbackAPI
	fbApiUrl: 'http://localhost:8080',
	fbContentTypeHeader: 'application/json',
	fbPiToken: pt
};
function init() {

	// Demo eventing API
	document.body.dispatchEvent(new CustomEvent('o.InitNotificationComponent', {
			detail: {
				config: AppHeaderConfig,
				elementId: 'demo-target1'
			}
	 }));

	// Demo direct API
	// new NotificationComponent(
	// 		AppHeaderConfig,
	// 		'demo-target2'
	//  );

}

window.onload = init;
<commit_msg>removed unnneded demo<commit_after>'use strict';

import NotificationComponent from '../main'; // for direct API usage

const pt = '1.0|idm|idm|piid=ffffffff53da3cb3e4b0eaaddd576877&sessid=beeaa30c981b41fbbb52dc3937006aa2|2016-05-11T19:09:18+00:00|2016-05-11T22:09:18+00:00|823b1d93bedb555b4a89f9807fe01b51';

const AppHeaderConfig = {
	// NotificationAPI
	nfApiUrl: 'https://notifications-api.stg-prsn.com',
	nfContentTypeHeader: 'application/json',
	nfPiToken: pt,
	nfRecipientId: 'ffffffff560c1a1ee4b04ebf43118c60',

	// CoachmarkAPI
	cmApiUrl: 'http://localhost:8080',
	cmContentTypeHeader: 'application/json',
	cmPiToken: pt,

	// FeedbackAPI
	fbApiUrl: 'http://localhost:8080',
	fbContentTypeHeader: 'application/json',
	fbPiToken: pt
};
function init() {

	// Demo eventing API
	document.body.dispatchEvent(new CustomEvent('o.InitNotificationComponent', {
			detail: {
				config: AppHeaderConfig,
				elementId: 'demo-target1'
			}
	 }));

}

window.onload = init;
<|endoftext|>


<commit_before>const express = require('express')
const bodyParser = require('body-parser');
const app = express();
const mongoose = require('mongoose');
const dbController = require('./controllers/dbController.js')
const foodpairingController = require('./controllers/foodpairingController.js');
const recipesController = require('./controllers/recipesController.js');
const cameraController = require('./controllers/cameraController.js');

// connect to local database
// mongoose.connect('mongodb://localhost/snacktimetest');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log('we are connected!')
});

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/foodPairing', foodpairingController.getFoodpairing);
app.post('/recipeList', recipesController.getRecipeList);
app.post('/recipeSelector', recipesController.getRecipe);
app.post('/compareRecipes', recipesController.compareRecipes);
app.post('/getFoodID', foodpairingController.getFoodID);
app.post('/getMultipleFoodpairings', foodpairingController.getMultipleFoodpairings);

// find user in db and send back to cilent
app.get('/database', function(req, res){
  dbController.findUserId(req.query.ID, function(err, data) {
    if(err) {
  		console.log(err);
  	}
  console.log('server sending back data', data)
  res.send(data);
  })
});

// created a new user because no user is find
app.post('/database', function(req, res){
  var newUser = {
    'name': 'testing',
    'FacebookUserID': req.body.id,
    'InstagramToken': [],
    'FavoriteRecipe': [],
  }
  dbController.insertNewUser(newUser, function(err, data){
    if(err) {
      console.log(err);
    }
    console.log('server created user', data)
    res.send(data)
  })
});

// create a recipe schema

app.post('/AddRecipe', function(req, res){
  // var saveRecipe = {
  //   "name": req.body.name,
  //   "id": req.body.id,
  //   "image": req.body.image,
  //   "analyzedInstructions": req.body.analyzedInstructions
  // }
  // dbController.createRecipe(saveRecipe, function(err, newRecipe){
  //   if(err) {
  //     console.log(err);
  //   }
  //   console.log('server create recipe', newRecipe)
  //   res.send(newRecipe)
  // })
  res.send('hi')
})

module.exports = app;
<commit_msg>the server stuff for backend<commit_after>const express = require('express')
const bodyParser = require('body-parser');
const app = express();
const mongoose = require('mongoose');
const dbController = require('./controllers/dbController.js')
const foodpairingController = require('./controllers/foodpairingController.js');
const recipesController = require('./controllers/recipesController.js');
const cameraController = require('./controllers/cameraController.js');

// connect to local database
// mongoose.connect('mongodb://localhost/snacktimetest');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log('we are connected!')
});

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/foodPairing', foodpairingController.getFoodpairing);
app.post('/recipeList', recipesController.getRecipeList);
app.post('/recipeSelector', recipesController.getRecipe);
app.post('/compareRecipes', recipesController.compareRecipes);
app.post('/getFoodID', foodpairingController.getFoodID);
app.post('/getMultipleFoodpairings', foodpairingController.getMultipleFoodpairings);

// find user in db and send back to cilent
app.get('/database', function(req, res){
  dbController.findUserId(req.query.ID, function(err, data) {
    if(err) {
  		console.log(err);
  }
  res.send(data);
  })
});

// created a new user because no user is find
app.post('/database', function(req, res){
  var newUser = {
    'name': 'testing',
    'FacebookUserID': req.body.id,
    'InstagramToken': [],
    'FavoriteRecipe': [],
  }
  dbController.insertNewUser(newUser, function(err, data){
    if(err) {
      console.log(err);
    }
    console.log('server created user', data)
    res.send(data)
  })
});

// create a recipe schema

// send userid from store
// then use userModel findoneandUpdate to save recipe

app.post('/AddRecipe', function(req, res){
  var facebookuserid = req.body.facebookuserid
  var saveRecipe = {
    "name": req.body.name,
    "id": req.body.id,
    "image": req.body.image,
    "analyzedInstructions": req.body.analyzedInstructions
  }
  dbController.createRecipe(saveRecipe, function(err, newRecipe){
    if(err) {
      console.log(err);
    }
    var newR = newRecipe;
    dbController.findUserId(facebookuserid, function(err, user) {
      if(err) {
    		console.log(err);
    	}
      user[0].FavoriteRecipe.push(newR)
      user[0].save(function(err, user, num){
        if(err) {
          console.log(err)
        }
        console.log('user', user)
      });
    })
  })
})

module.exports = app;
<|endoftext|>


<commit_before>// Copyright 2018, University of Colorado Boulder

/**
 * Block types for EFAC intro
 *
 * @author Chris Klusendorf
 */
define( function( require ) {
  'use strict';

  // modules
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );

  // @public
  var BlockType = {
    IRON: 'IRON',
    BRICK: 'BRICK'
  };

  // verify that enum is immutable, without the runtime penalty in production code
  if ( assert ) { Object.freeze( BlockType ); }

  energyFormsAndChanges.register( 'BlockType', BlockType );

  return BlockType;

} );<commit_msg>Convert to ES6, see https://github.com/phetsims/energy-forms-and-changes/issues/211<commit_after>// Copyright 2018-2019, University of Colorado Boulder

/**
 * Block types for EFAC intro
 *
 * @author Chris Klusendorf
 */
define( require => {
  'use strict';

  // modules
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );

  // @public
  var BlockType = {
    IRON: 'IRON',
    BRICK: 'BRICK'
  };

  // verify that enum is immutable, without the runtime penalty in production code
  if ( assert ) { Object.freeze( BlockType ); }

  return energyFormsAndChanges.register( 'BlockType', BlockType );
} );<|endoftext|>


<commit_before>/* bxSlider Author:
DANNY POSTMA
www.dannypostma.com
*/
/*
I think that's a shit plugin. My grandma is better than him.
*/
$(document).ready(function(){
		"use strict";
		$('.testimonialsslider').bxSlider({
			 auto: true,
			 autoControls: false
		});

		var sliderTestimonial = $('.appslider').bxSlider({
			 auto: false,
			 autoControls: false
		});

		var slideToInfo = function(node){
			var transform_N = -270;
			var translate3d_N = 'translate3d('+((parseInt($(node).attr('data-slide-index'))+1)*parseInt(transform_N)).toString()+'px, 0px, 0px)';
			$('ul.bxslider.appslider').css('transition','0.5s');
			$('ul.bxslider.appslider').css('transform', translate3d_N);
			$('div.android-image a.bx-pager-link').css('background','none repeat scroll 0 0 #666666');
			$('div.android-image a.bx-pager-link').eq(parseInt($(this).attr('data-slide-index'))).css('background','none repeat scroll 0 0 #000000');
			return false;
		}

		$('div.android-image a.bx-pager-link').click(function(e){
			e.preventDefault();
			e.stopPropagation();
			slideToInfo(this);
		});
		$('div.info-box').hover(function(){
			slideToInfo(this);
			return false;
		});
});<commit_msg>fight with navigation problem.<commit_after>/* bxSlider Author:
DANNY POSTMA
www.dannypostma.com
*/
/*
I think that's a shit plugin. My grandma is better than him.
*/
"use strict";
var slideToInfo = function(node){
			var transform_N = -270;
			var translate3d_N = 'translate3d('+((parseInt($(node).attr('data-slide-index'))+1)*parseInt(transform_N)).toString()+'px, 0px, 0px)';
			$('ul.bxslider.appslider').css('transition','0.5s');
			$('ul.bxslider.appslider').css('transform', translate3d_N);
			$('div.android-image a.bx-pager-link').css('background','none repeat scroll 0 0 #666666');
			$('div.android-image a.bx-pager-link').eq(parseInt($(this).attr('data-slide-index'))).css('background','none repeat scroll 0 0 #000000');
			return false;
		}
$(document).ready(function(){
		"use strict";
		$('.testimonialsslider').bxSlider({
			 auto: true,
			 autoControls: false
		});

		var sliderTestimonial = $('.appslider').bxSlider({
			 auto: false,
			 autoControls: false
		});

		$('div.android-image a.bx-pager-link').click(function(e){
			e.preventDefault();
			e.stopPropagation();
			slideToInfo(this);
		});
		$('div.info-box').hover(function(){
			slideToInfo(this);
			return false;
		});
});<|endoftext|>