<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { browserHistory } from 'react-router'
import scrollTop from '../../vendor/scrollTop'
import classNames from 'classnames'
import _ from 'lodash'
import { runningFetches } from '../../middleware/requester'
import * as ACTION_TYPES from '../../constants/action_types'
import { SESSION_KEYS } from '../../constants/gui_types'
import * as MAPPING_TYPES from '../../constants/mapping_types'
import { findModel } from '../base/json_helper'
import { addScrollObject, removeScrollObject } from '../interface/ScrollComponent'
import { addResizeObject, removeResizeObject } from '../interface/ResizeComponent'
import { ElloMark } from '../interface/ElloIcons'
import { Paginator, emptyPagination } from './Paginator'
import { findLayoutMode } from '../../reducers/gui'
import { ErrorState4xx } from '../errors/Errors'
import Session from '../../vendor/session'

export class StreamComponent extends Component {

  static propTypes = {
    action: PropTypes.object,
    children: PropTypes.any,
    className: PropTypes.string,
    currentUser: PropTypes.object,
    dispatch: PropTypes.func.isRequired,
    history: PropTypes.object.isRequired,
    mode: PropTypes.string.isRequired,
    isModalComponent: PropTypes.bool,
    ignoresScrollPosition: PropTypes.bool.isRequired,
    initModel: PropTypes.object,
    isUserDetail: PropTypes.bool.isRequired,
    json: PropTypes.object.isRequired,
    omnibar: PropTypes.shape({
      isActive: PropTypes.bool,
    }),
    paginatorText: PropTypes.string,
    renderObj: PropTypes.shape({
      data: PropTypes.array.isRequired,
      nestedData: PropTypes.array.isRequired,
    }).isRequired,
    result: PropTypes.shape({
      next: PropTypes.shape({
        ids: PropTypes.array,
        pagination: PropTypes.shape({
          next: PropTypes.string,
          totalCount: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.string,
          ]),
          totalPages: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.string,
          ]),
          totalPagesRemaining: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.string,
          ]),
        }),
        type: PropTypes.string,
      }),
      ids: PropTypes.array,
      pagination: PropTypes.shape({
        next: PropTypes.string,
        totalCount: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string,
        ]),
        totalPages: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string,
        ]),
        totalPagesRemaining: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string,
        ]),
      }),
      type: PropTypes.string,
    }),
    resultPath: PropTypes.string,
    routerState: PropTypes.object,
    scrollSessionKey: PropTypes.string,
    stream: PropTypes.object.isRequired,
  }

  static defaultProps = {
    paginatorText: 'Loading',
    ignoresScrollPosition: false,
    isUserDetail: false,
    isModalComponent: false,
  }

  componentWillMount() {
    const { action, dispatch, omnibar } = this.props
    if (action) { dispatch(action) }

    let browserListen
    if (browserHistory) {
      browserListen = browserHistory.listen
    } else {
      browserListen = (listener) => {
        listener({ key: 'testing' })
        return () => null
      }
    }
    const unlisten = browserListen(location => {
      this.state = { action, locationKey: location.key }
    })
    unlisten()
    this.setDebouncedScroll = _.debounce(this.setDebouncedScroll, 300)
    this.shouldScroll = true
    this.wasOmnibarActive = omnibar.isActive
  }

  componentDidMount() {
    const { routerState } = this.props
    if (window.embetter) {
      window.embetter.reloadPlayers()
    }
    if (!this.props.isModalComponent) {
      addScrollObject(this)
    }

    let shouldScrollToTop = true
    if (this.props.isUserDetail) {
      this.scrollToUserDetail()
      shouldScrollToTop = false
      this.saveScroll = false
    } else if (routerState.didComeFromSeeMoreCommentsLink) {
      this.saveScroll = false
    } else {
      this.saveScroll = true
    }

    addResizeObject(this)

    this.attemptToRestoreScroll(shouldScrollToTop)
  }

  componentWillReceiveProps(nextProps) {
    const { stream } = nextProps
    const { action } = this.state
    if (!action) { return }

    if (stream.type === ACTION_TYPES.LOAD_NEXT_CONTENT_SUCCESS) {
      this.setState({ hidePaginator: true })
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { stream } = nextProps
    const { action } = nextState
    const updateKey = _.get(action, 'meta.updateKey')
    // this prevents nested stream components from clobbering parents
    if (updateKey && !stream.payload.endpoint.path.match(updateKey)) {
      return false
    // when hitting the back button the result can update and
    // try to feed wrong results to the actions render method
    // thus causing errors when trying to render wrong results
    } else if (nextProps.resultPath !== this.props.resultPath) {
      return false
    } else if (_.isEqual(nextState, this.state) &&
               _.isEqual(nextProps, this.props)) {
      return false
    }
    return true
  }

  componentDidUpdate() {
    if (window.embetter) {
      window.embetter.reloadPlayers()
    }

    const { action } = this.state
    const { stream, omnibar, isUserDetail } = this.props
    const canScroll = document.body.scrollHeight > window.innerHeight
    const shouldScroll = this.shouldScroll && (canScroll ||
      stream.type === ACTION_TYPES.LOAD_STREAM_SUCCESS &&
      action && action.payload &&
      stream.payload.endpoint.path === action.payload.endpoint.path)
    if (shouldScroll) {
      if (this.attemptToRestoreScroll()) {
        this.shouldScroll = false
      }
    }

    if (isUserDetail && !omnibar.isActive && this.wasOmnibarActive) {
      this.scrollToUserDetail()
    }
    this.wasOmnibarActive = omnibar.isActive
  }

  componentWillUnmount() {
    if (window.embetter) {
      window.embetter.stopPlayers()
    }
    removeScrollObject(this)
    removeResizeObject(this)

    this.saveScroll = false
  }

  onScroll() {
    this.setDebouncedScroll()
  }

  onScrollBottom() {
    this.loadPage('next', true)
  }

  onResize(resizeProps) {
    this.setState(resizeProps)
  }

  onLoadNextPage = () => {
    this.loadPage('next')
  }

  setAction(action) {
    this.setState({ action })
    this.props.dispatch(action)
  }

  setDebouncedScroll() {
    this.setScroll()
  }

  setScroll() {
    if (!this.saveScroll) { return }

    let scrollTopValue
    if (this.scrollContainer) {
      scrollTopValue = scrollTop(this.scrollContainer)
    } else {
      scrollTopValue = scrollTop(window)
    }

    if (this.props.scrollSessionKey) {
      const sessionStorageKey = SESSION_KEYS.scrollLocationKey(this.props.scrollSessionKey)
      Session.setItem(sessionStorageKey, scrollTopValue)
    }

    this.props.dispatch({
      type: ACTION_TYPES.GUI.SET_SCROLL,
      payload: {
        key: this.state.locationKey,
        scrollTop: scrollTopValue,
      },
    })
  }

  scrollToUserDetail() {
    const offset = Math.round((window.innerWidth * 0.5625)) - 200
    window.scrollTo(0, offset)
  }

  attemptToRestoreScroll(fromMount = false) {
    const { history, routerState, isModalComponent } = this.props
    let scrollTopValue = null
    if (!routerState.didComeFromSeeMoreCommentsLink && !this.props.ignoresScrollPosition) {
      if (fromMount && !isModalComponent) {
        window.scrollTo(0, 0)
        return false
      }

      this.saveScroll = true

      let sessionScrollLocation = null
      if (this.props.scrollSessionKey) {
        const sessionStorageKey = SESSION_KEYS.scrollLocationKey(this.props.scrollSessionKey)
        sessionScrollLocation = parseInt(Session.getItem(sessionStorageKey), 10)
      }

      if (sessionScrollLocation !== null) {
        scrollTopValue = sessionScrollLocation
      } else if (history[this.state.locationKey]) {
        const historyObj = history[this.state.locationKey]
        scrollTopValue = historyObj.scrollTop
      }
    } else if (routerState.didComeFromSeeMoreCommentsLink) {
      this.saveScroll = true
      scrollTopValue = document.body.scrollHeight - window.innerHeight
    }

    if (scrollTopValue) {
      requestAnimationFrame(() => {
        if (!this.saveScroll) {
          return
        }

        if (this.scrollContainer) {
          this.scrollContainer.scrollTop = scrollTopValue
        } else if (typeof window !== 'undefined') {
          window.scrollTo(0, scrollTopValue)
        }
      })
      return true
    }
    return false
  }

  loadPage(rel, scrolled = false) {
    const { dispatch, result } = this.props
    if (!result) { return }
    const { action } = this.state
    const { meta } = action
    if (scrolled && meta && meta.resultKey && meta.updateKey) { return }
    const { pagination } = result
    if (!action.payload.endpoint ||
        !pagination[rel] ||
        parseInt(pagination.totalPagesRemaining, 10) === 0 ||
        !action) { return }
    if (runningFetches[pagination[rel]]) { return }
    this.setState({ hidePaginator: false })
    const infiniteAction = {
      ...action,
      type: ACTION_TYPES.LOAD_NEXT_CONTENT,
      payload: {
        endpoint: { path: pagination[rel] },
      },
      meta: {
        mappingType: action.payload.endpoint.pagingPath || meta.mappingType,
        resultFilter: meta.resultFilter,
        resultKey: meta.resultKey,
      },
    }
    // this is used for updating the postId on a comment
    // so that the post exsists in the store after load
    if (action.payload.postIdOrToken) {
      infiniteAction.payload.postIdOrToken = action.payload.postIdOrToken
    }
    dispatch(infiniteAction)
  }

  renderError() {
    const { action } = this.props
    const { meta } = action
    return (

        { meta && meta.renderStream && meta.renderStream.asError ?
          meta.renderStream.asError :
          <ErrorState4xx />
        }

    )
  }

  renderLoading() {
    const { className } = this.props
    return (

          <ElloMark />

    )
  }

  renderZeroState() {
    const { action } = this.props
    if (!action) { return null }
    const { meta } = action
    return (

        { meta && meta.renderStream && meta.renderStream.asZero ?
          meta.renderStream.asZero :
          null
        }

    )
  }

  render() {
    const { className, currentUser, initModel, json, mode,
      paginatorText, renderObj, result, stream } = this.props
    const { action, gridColumnCount, hidePaginator } = this.state
    if (!action) { return null }
    const model = findModel(json, initModel)
    if (model && !result) {
      renderObj.data.push(model)
    } else if (!renderObj.data.length) {
      switch (stream.type) {
        case ACTION_TYPES.LOAD_STREAM_SUCCESS:
          return this.renderZeroState()
        case ACTION_TYPES.LOAD_STREAM_REQUEST:
          return this.renderLoading()
        case ACTION_TYPES.LOAD_STREAM_FAILURE:
          if (stream.error) {
            return this.renderError()
          }
          return null
        default:
          return null
      }
    }
    const { meta } = action
    const renderMethod = mode === 'grid' ? 'asGrid' : 'asList'
    const pagination = result && result.pagination ? result.pagination : emptyPagination()
    return (

        {
          meta.renderStream[renderMethod](
            renderObj,
            json,
            currentUser,
            gridColumnCount)
        }
        { this.props.children }
        <Paginator
          hasShowMoreButton={
            typeof meta.resultKey !== 'undefined' && typeof meta.updateKey !== 'undefined'
          }
          isHidden={ hidePaginator }
          loadNextPage={ this.onLoadNextPage }
          messageText={ paginatorText }
          totalPages={ parseInt(pagination.totalPages, 10) }
          totalPagesRemaining={ parseInt(pagination.totalPagesRemaining, 10) }
        />

    )
  }
}

export function mapStateToProps(state, ownProps) {
  let result

  const { action } = ownProps
  const meta = action ? action.meta : null
  const resultPath = (meta && meta.resultKey) ? meta.resultKey : state.routing.location.pathname
  const payload = action ? action.payload : null
  const renderObj = { data: [], nestedData: [] }
  if (state.json.pages) {
    result = state.json.pages[resultPath]
  }
  if (result && result.type === MAPPING_TYPES.NOTIFICATIONS) {
    renderObj.data = renderObj.data.concat(result.ids)
    if (result.next) {
      renderObj.data = renderObj.data.concat(result.next.ids)
    }
  } else if (meta && result && result.type === meta.mappingType ||
            (meta && meta.resultFilter && result && result.type !== meta.mappingType)) {
    const deletedCollection = state.json[`deleted_${result.type}`]
    // don't filter out blocked ids if we are in settings
    // since you can unblock/unmute them from here
    for (const id of result.ids) {
      if (_.get(state.json, [result.type, id]) &&
          (state.routing.location.pathname === '/settings' ||
          (!deletedCollection || deletedCollection.indexOf(id) === -1))) {
        renderObj.data.push(_.get(state.json, [result.type, id]))
      }
    }
    if (result.next) {
      const nextDeletedCollection = state.json[`deleted_${result.next.type}`]
      const dataProp = payload.endpoint.pagingPath ? 'nestedData' : 'data'
      for (const nextId of result.next.ids) {
        if (state.json[result.next.type][nextId] &&
            (state.routing.location.pathname === '/settings' ||
            (!nextDeletedCollection || nextDeletedCollection.indexOf(nextId) === -1))) {
          renderObj[dataProp].push(state.json[result.next.type][nextId])
        }
      }
    }
  }

  let stream = ownProps.stream
  if (!stream ||
    _.get(state.stream, 'payload.endpoint.path') === _.get(action, 'payload.endpoint.path')
  ) {
    stream = state.stream
  }
  return {
    currentUser: state.profile,
    history: state.gui.history,
    json: state.json,
    mode: findLayoutMode(state.gui.modes).mode,
    omnibar: state.omnibar,
    renderObj,
    result,
    resultPath,
    routerState: state.routing.location.state || {},
    stream,
  }
}

export default connect(mapStateToProps, null, null, { withRef: true })(StreamComponent)

<commit_msg>Actually fix the error..<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { browserHistory } from 'react-router'
import scrollTop from '../../vendor/scrollTop'
import classNames from 'classnames'
import _ from 'lodash'
import { runningFetches } from '../../middleware/requester'
import * as ACTION_TYPES from '../../constants/action_types'
import { SESSION_KEYS } from '../../constants/gui_types'
import * as MAPPING_TYPES from '../../constants/mapping_types'
import { findModel } from '../base/json_helper'
import { addScrollObject, removeScrollObject } from '../interface/ScrollComponent'
import { addResizeObject, removeResizeObject } from '../interface/ResizeComponent'
import { ElloMark } from '../interface/ElloIcons'
import { Paginator, emptyPagination } from './Paginator'
import { findLayoutMode } from '../../reducers/gui'
import { ErrorState4xx } from '../errors/Errors'
import Session from '../../vendor/session'

export class StreamComponent extends Component {

  static propTypes = {
    action: PropTypes.object,
    children: PropTypes.any,
    className: PropTypes.string,
    currentUser: PropTypes.object,
    dispatch: PropTypes.func.isRequired,
    history: PropTypes.object.isRequired,
    mode: PropTypes.string.isRequired,
    isModalComponent: PropTypes.bool,
    ignoresScrollPosition: PropTypes.bool.isRequired,
    initModel: PropTypes.object,
    isUserDetail: PropTypes.bool.isRequired,
    json: PropTypes.object.isRequired,
    omnibar: PropTypes.shape({
      isActive: PropTypes.bool,
    }),
    paginatorText: PropTypes.string,
    renderObj: PropTypes.shape({
      data: PropTypes.array.isRequired,
      nestedData: PropTypes.array.isRequired,
    }).isRequired,
    result: PropTypes.shape({
      next: PropTypes.shape({
        ids: PropTypes.array,
        pagination: PropTypes.shape({
          next: PropTypes.string,
          totalCount: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.string,
          ]),
          totalPages: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.string,
          ]),
          totalPagesRemaining: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.string,
          ]),
        }),
        type: PropTypes.string,
      }),
      ids: PropTypes.array,
      pagination: PropTypes.shape({
        next: PropTypes.string,
        totalCount: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string,
        ]),
        totalPages: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string,
        ]),
        totalPagesRemaining: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string,
        ]),
      }),
      type: PropTypes.string,
    }),
    resultPath: PropTypes.string,
    routerState: PropTypes.object,
    scrollSessionKey: PropTypes.string,
    stream: PropTypes.object.isRequired,
  }

  static defaultProps = {
    paginatorText: 'Loading',
    ignoresScrollPosition: false,
    isUserDetail: false,
    isModalComponent: false,
  }

  componentWillMount() {
    const { action, dispatch, omnibar } = this.props
    if (action) { dispatch(action) }

    let browserListen
    if (browserHistory) {
      browserListen = browserHistory.listen
    } else {
      browserListen = (listener) => {
        listener({ key: 'testing' })
        return () => null
      }
    }
    const unlisten = browserListen(location => {
      this.state = { action, locationKey: location.key }
    })
    unlisten()
    this.setDebouncedScroll = _.debounce(this.setDebouncedScroll, 300)
    this.shouldScroll = true
    this.wasOmnibarActive = omnibar.isActive
  }

  componentDidMount() {
    const { routerState } = this.props
    if (window.embetter) {
      window.embetter.reloadPlayers()
    }
    if (!this.props.isModalComponent) {
      addScrollObject(this)
    }

    let shouldScrollToTop = true
    if (this.props.isUserDetail) {
      this.scrollToUserDetail()
      shouldScrollToTop = false
      this.saveScroll = false
    } else if (routerState.didComeFromSeeMoreCommentsLink) {
      this.saveScroll = false
    } else {
      this.saveScroll = true
    }

    addResizeObject(this)

    this.attemptToRestoreScroll(shouldScrollToTop)
  }

  componentWillReceiveProps(nextProps) {
    const { stream } = nextProps
    const { action } = this.state
    if (!action) { return }

    if (stream.type === ACTION_TYPES.LOAD_NEXT_CONTENT_SUCCESS) {
      this.setState({ hidePaginator: true })
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { stream } = nextProps
    const { action } = nextState
    const updateKey = _.get(action, 'meta.updateKey')
    const streamPath = _.get(stream, 'payload.endpoint.path', '')
    // this prevents nested stream components from clobbering parents
    if (updateKey && !streamPath.match(updateKey)) {
      return false
    // when hitting the back button the result can update and
    // try to feed wrong results to the actions render method
    // thus causing errors when trying to render wrong results
    } else if (nextProps.resultPath !== this.props.resultPath) {
      return false
    } else if (_.isEqual(nextState, this.state) &&
               _.isEqual(nextProps, this.props)) {
      return false
    }
    return true
  }

  componentDidUpdate() {
    if (window.embetter) {
      window.embetter.reloadPlayers()
    }

    const { action } = this.state
    const { stream, omnibar, isUserDetail } = this.props
    const canScroll = document.body.scrollHeight > window.innerHeight
    const shouldScroll = this.shouldScroll && (canScroll ||
      stream.type === ACTION_TYPES.LOAD_STREAM_SUCCESS &&
      action && action.payload &&
      stream.payload.endpoint.path === action.payload.endpoint.path)
    if (shouldScroll) {
      if (this.attemptToRestoreScroll()) {
        this.shouldScroll = false
      }
    }

    if (isUserDetail && !omnibar.isActive && this.wasOmnibarActive) {
      this.scrollToUserDetail()
    }
    this.wasOmnibarActive = omnibar.isActive
  }

  componentWillUnmount() {
    if (window.embetter) {
      window.embetter.stopPlayers()
    }
    removeScrollObject(this)
    removeResizeObject(this)

    this.saveScroll = false
  }

  onScroll() {
    this.setDebouncedScroll()
  }

  onScrollBottom() {
    this.loadPage('next', true)
  }

  onResize(resizeProps) {
    this.setState(resizeProps)
  }

  onLoadNextPage = () => {
    this.loadPage('next')
  }

  setAction(action) {
    this.setState({ action })
    this.props.dispatch(action)
  }

  setDebouncedScroll() {
    this.setScroll()
  }

  setScroll() {
    if (!this.saveScroll) { return }

    let scrollTopValue
    if (this.scrollContainer) {
      scrollTopValue = scrollTop(this.scrollContainer)
    } else {
      scrollTopValue = scrollTop(window)
    }

    if (this.props.scrollSessionKey) {
      const sessionStorageKey = SESSION_KEYS.scrollLocationKey(this.props.scrollSessionKey)
      Session.setItem(sessionStorageKey, scrollTopValue)
    }

    this.props.dispatch({
      type: ACTION_TYPES.GUI.SET_SCROLL,
      payload: {
        key: this.state.locationKey,
        scrollTop: scrollTopValue,
      },
    })
  }

  scrollToUserDetail() {
    const offset = Math.round((window.innerWidth * 0.5625)) - 200
    window.scrollTo(0, offset)
  }

  attemptToRestoreScroll(fromMount = false) {
    const { history, routerState, isModalComponent } = this.props
    let scrollTopValue = null
    if (!routerState.didComeFromSeeMoreCommentsLink && !this.props.ignoresScrollPosition) {
      if (fromMount && !isModalComponent) {
        window.scrollTo(0, 0)
        return false
      }

      this.saveScroll = true

      let sessionScrollLocation = null
      if (this.props.scrollSessionKey) {
        const sessionStorageKey = SESSION_KEYS.scrollLocationKey(this.props.scrollSessionKey)
        sessionScrollLocation = parseInt(Session.getItem(sessionStorageKey), 10)
      }

      if (sessionScrollLocation !== null) {
        scrollTopValue = sessionScrollLocation
      } else if (history[this.state.locationKey]) {
        const historyObj = history[this.state.locationKey]
        scrollTopValue = historyObj.scrollTop
      }
    } else if (routerState.didComeFromSeeMoreCommentsLink) {
      this.saveScroll = true
      scrollTopValue = document.body.scrollHeight - window.innerHeight
    }

    if (scrollTopValue) {
      requestAnimationFrame(() => {
        if (!this.saveScroll) {
          return
        }

        if (this.scrollContainer) {
          this.scrollContainer.scrollTop = scrollTopValue
        } else if (typeof window !== 'undefined') {
          window.scrollTo(0, scrollTopValue)
        }
      })
      return true
    }
    return false
  }

  loadPage(rel, scrolled = false) {
    const { dispatch, result } = this.props
    if (!result) { return }
    const { action } = this.state
    const { meta } = action
    if (scrolled && meta && meta.resultKey && meta.updateKey) { return }
    const { pagination } = result
    if (!action.payload.endpoint ||
        !pagination[rel] ||
        parseInt(pagination.totalPagesRemaining, 10) === 0 ||
        !action) { return }
    if (runningFetches[pagination[rel]]) { return }
    this.setState({ hidePaginator: false })
    const infiniteAction = {
      ...action,
      type: ACTION_TYPES.LOAD_NEXT_CONTENT,
      payload: {
        endpoint: { path: pagination[rel] },
      },
      meta: {
        mappingType: action.payload.endpoint.pagingPath || meta.mappingType,
        resultFilter: meta.resultFilter,
        resultKey: meta.resultKey,
      },
    }
    // this is used for updating the postId on a comment
    // so that the post exsists in the store after load
    if (action.payload.postIdOrToken) {
      infiniteAction.payload.postIdOrToken = action.payload.postIdOrToken
    }
    dispatch(infiniteAction)
  }

  renderError() {
    const { action } = this.props
    const { meta } = action
    return (

        { meta && meta.renderStream && meta.renderStream.asError ?
          meta.renderStream.asError :
          <ErrorState4xx />
        }

    )
  }

  renderLoading() {
    const { className } = this.props
    return (

          <ElloMark />

    )
  }

  renderZeroState() {
    const { action } = this.props
    if (!action) { return null }
    const { meta } = action
    return (

        { meta && meta.renderStream && meta.renderStream.asZero ?
          meta.renderStream.asZero :
          null
        }

    )
  }

  render() {
    const { className, currentUser, initModel, json, mode,
      paginatorText, renderObj, result, stream } = this.props
    const { action, gridColumnCount, hidePaginator } = this.state
    if (!action) { return null }
    const model = findModel(json, initModel)
    if (model && !result) {
      renderObj.data.push(model)
    } else if (!renderObj.data.length) {
      switch (stream.type) {
        case ACTION_TYPES.LOAD_STREAM_SUCCESS:
          return this.renderZeroState()
        case ACTION_TYPES.LOAD_STREAM_REQUEST:
          return this.renderLoading()
        case ACTION_TYPES.LOAD_STREAM_FAILURE:
          if (stream.error) {
            return this.renderError()
          }
          return null
        default:
          return null
      }
    }
    const { meta } = action
    const renderMethod = mode === 'grid' ? 'asGrid' : 'asList'
    const pagination = result && result.pagination ? result.pagination : emptyPagination()
    return (

        {
          meta.renderStream[renderMethod](
            renderObj,
            json,
            currentUser,
            gridColumnCount)
        }
        { this.props.children }
        <Paginator
          hasShowMoreButton={
            typeof meta.resultKey !== 'undefined' && typeof meta.updateKey !== 'undefined'
          }
          isHidden={ hidePaginator }
          loadNextPage={ this.onLoadNextPage }
          messageText={ paginatorText }
          totalPages={ parseInt(pagination.totalPages, 10) }
          totalPagesRemaining={ parseInt(pagination.totalPagesRemaining, 10) }
        />

    )
  }
}

export function mapStateToProps(state, ownProps) {
  let result

  const { action } = ownProps
  const meta = action ? action.meta : null
  const resultPath = (meta && meta.resultKey) ? meta.resultKey : state.routing.location.pathname
  const payload = action ? action.payload : null
  const renderObj = { data: [], nestedData: [] }
  if (state.json.pages) {
    result = state.json.pages[resultPath]
  }
  if (result && result.type === MAPPING_TYPES.NOTIFICATIONS) {
    renderObj.data = renderObj.data.concat(result.ids)
    if (result.next) {
      renderObj.data = renderObj.data.concat(result.next.ids)
    }
  } else if (meta && result && result.type === meta.mappingType ||
            (meta && meta.resultFilter && result && result.type !== meta.mappingType)) {
    const deletedCollection = state.json[`deleted_${result.type}`]
    // don't filter out blocked ids if we are in settings
    // since you can unblock/unmute them from here
    for (const id of result.ids) {
      if (_.get(state.json, [result.type, id]) &&
          (state.routing.location.pathname === '/settings' ||
          (!deletedCollection || deletedCollection.indexOf(id) === -1))) {
        renderObj.data.push(_.get(state.json, [result.type, id]))
      }
    }
    if (result.next) {
      const nextDeletedCollection = state.json[`deleted_${result.next.type}`]
      const dataProp = payload.endpoint.pagingPath ? 'nestedData' : 'data'
      for (const nextId of result.next.ids) {
        if (state.json[result.next.type][nextId] &&
            (state.routing.location.pathname === '/settings' ||
            (!nextDeletedCollection || nextDeletedCollection.indexOf(nextId) === -1))) {
          renderObj[dataProp].push(state.json[result.next.type][nextId])
        }
      }
    }
  }

  let stream = ownProps.stream
  if (!stream ||
    _.get(state.stream, 'payload.endpoint.path') === _.get(action, 'payload.endpoint.path')
  ) {
    stream = state.stream
  }
  return {
    currentUser: state.profile,
    history: state.gui.history,
    json: state.json,
    mode: findLayoutMode(state.gui.modes).mode,
    omnibar: state.omnibar,
    renderObj,
    result,
    resultPath,
    routerState: state.routing.location.state || {},
    stream,
  }
}

export default connect(mapStateToProps, null, null, { withRef: true })(StreamComponent)

<|endoftext|>


<commit_before>var Container = require('./container');

exports = module.exports = new Container();

exports.Container = Container;

exports.node = require('./loaders/node');
exports.node_modules = require('./loaders/node_modules');
<commit_msg>Alias node loader to fs.<commit_after>var Container = require('./container');

exports = module.exports = new Container();

exports.Container = Container;

exports.fs =
exports.node = require('./loaders/node');
exports.node_modules = require('./loaders/node_modules');
<|endoftext|>


<commit_before>// es6 runtime requirements
require('babel/polyfill');
import express from 'express';
import { Server as http } from 'http';
import sockets from 'socket.io';
import ADB from './adb';

export default function service(){

  let app = express();
  let server = http(app);
  let io = sockets(server);
  let adb = new ADB();
  let log = console.log;

  let isTesting = false;

  io.on('connection', socket => {

    socket.emit("log", {msg: "socket connected"});
    log("socket connected");
    socket.on("test", data => {

      try {
        let devices = adb.devices();
        socket.emit("log", {msg: "available devices:" + devices});
        log("available devices:" + devices);

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

  // static files
  app.use(express.static(__dirname + '/../public'));
  app.get("/", (req, res) => {

    res.sendFile(__dirname + '/../public/index.html');

  });

  return server;
}
<commit_msg>check if the current package is installed, check if appium is running<commit_after>// es6 runtime requirements
require('babel/polyfill');
import express from 'express';
import { Server as http } from 'http';
import sockets from 'socket.io';
import ADB from './adb';
import ar from 'appium-running';
import monocle from 'monocle-js';

export default function service(){

  let app = express();
  let server = http(app);
  let io = sockets(server);
  let adb = new ADB();

  io.on('connection', socket => {

    let log = (msg) => {
      console.log(msg);
      socket.emit("log", {msg: msg});
    }

    log("socket connected");

    socket.on("test", data => {

        log("getting available devices");

        let devices = adb.devices();
        log("available devices:" + devices);

        if(!devices.length) {
          log("no available devices, please connect your android device");
          return;
        }

        log("checking current package is installed");
        if(!adb.isPackageInstalled(data.pkg)) {
          log("package: "+data.pkg+" not installed");
          return;
        }
        log("package: "+data.pkg+" is installed");

        log("checking appium is running");

        ar(4723, (success) => {
          if(!success) {
            log("Appium is not running, please run: appium &");
            return;
          }

          log("Appium is running, creating test");
          // TODO - create test

        });

    });
  });

  // static files
  app.use(express.static(__dirname + '/../public'));
  app.get("/", (req, res) => {

    res.sendFile(__dirname + '/../public/index.html');

  });

  return server;
}
<|endoftext|>


<commit_before>module.exports = [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env', '@babel/preset-react'],
        },
      },
    ],
  },
  {
    test: /\.c$/i,
    exclude: /node_modules/,
    loader: 'shader-loader',
  },
  {
    test: /\.mcss$/,
    use: [
      { loader: 'style-loader' },
      {
        loader: 'css-loader',
        options: {
          modules: {
            localIdentName: '[name]-[local]_[sha512:hash:base32:5]',
          },
        },
      },
      {
        loader: 'postcss-loader',
      },
    ],
  },
  {
    test: /\.html$/,
    loader: 'html-loader',
  },
  {
    test: /\.isvg$/,
    loader: 'html-loader',
    options: {
      attrs: false, // ?attrs=false
      sources: false, // ^ Replacemet?
    }
  },
  {
    test: /\.svg$/,
    loader: 'svg-sprite-loader',
    exclude: /fonts/,
    options: {
      runtimeCompat: true,
    },
  },
  {
    test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader',
    options: {
      limit: 60000,
      mimetype: 'application/font-woff',
    },
  },
  {
    test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader',
    include: /fonts/,
    options: {
      limit: 60000,
    },
  },
  {
    test: /\.(png|jpg)$/,
    loader: 'url-loader',
    options: {
      limit: 8192,
    },
  },
  {
    test: /\.css$/,
    use: [
      { loader: 'style-loader' },
      { loader: 'css-loader' },
      {
        loader: 'postcss-loader',
      },
    ],
  },
];
<commit_msg>chore(build): Update svg loader rules<commit_after>module.exports = [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env', '@babel/preset-react'],
        },
      },
    ],
  },
  {
    test: /\.c$/i,
    exclude: /node_modules/,
    loader: 'shader-loader',
  },
  {
    test: /\.mcss$/,
    use: [
      { loader: 'style-loader' },
      {
        loader: 'css-loader',
        options: {
          modules: {
            localIdentName: '[name]-[local]_[sha512:hash:base32:5]',
          },
        },
      },
      {
        loader: 'postcss-loader',
      },
    ],
  },
  {
    test: /\.html$/,
    loader: 'html-loader',
  },
  {
    test: /\.isvg$/,
    loader: 'html-loader',
    options: {
      attrs: false, // ?attrs=false
      sources: false, // ^ Replacemet?
    }
  },
  {
    test: /\.svg$/,
    loader: 'svg-sprite-loader',
    exclude: /fonts/,
  },
  {
    test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader',
    options: {
      limit: 60000,
      mimetype: 'application/font-woff',
    },
  },
  {
    test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'url-loader',
    include: /fonts/,
    options: {
      limit: 60000,
    },
  },
  {
    test: /\.(png|jpg)$/,
    loader: 'url-loader',
    options: {
      limit: 8192,
    },
  },
  {
    test: /\.css$/,
    use: [
      { loader: 'style-loader' },
      { loader: 'css-loader' },
      {
        loader: 'postcss-loader',
      },
    ],
  },
];
<|endoftext|>


<commit_before>/* jslint node: true */
"use strict";

/**
 * {description}
 * @module {name}
 * @param {Object} opts - optional options
 * @param {Object} [opts.modulePrefix=gulp-] - load dependencies that start with this prefix in package.json.
 * @returns {Object} result
 * @example @lang off
 {>example-index/}
 */
module.exports = function index(opts) {
  return opts;
};
<commit_msg>Deploy release 0.0.7<commit_after>/* jslint node: true */
"use strict";

/**
 * {description}
 * @module {name}
 * @param {Object} opts - optional options
 * @param {Object} [opts.modulePrefix=gulp-] - load dependencies that start with this prefix in package.json.
 * @returns {Object} result
 * @example @lang off
 {>example-index/}
 */
module.exports = function index(opts) {
  return opts !== null;
};
<|endoftext|>


<commit_before>'use strict';

class TeamcityReporter {
    constructor(emitter, reporterOptions, options) {
        this.reporterOptions = reporterOptions;
        this.options = options;
        const events = 'start beforeIteration iteration beforeItem item beforePrerequest prerequest beforeScript script beforeRequest request beforeTest test beforeAssertion assertion console exception beforeDone done'.split(' ');
        events.forEach((e) => { if (typeof this[e] == 'function') emitter.on(e, (err, args) => this[e](err, args)) });
    }

    start(err, args) {
        console.log(`##teamcity[testSuiteStarted name='${this.options.collection.name}']`);
    }

    beforeItem(err, args) {
        this.currItem = {name: args.item.name, passed: true, failedAssertions: []};
        console.log(`##teamcity[testStarted name='${this.currItem.name}' captureStandardOutput='true']`);
    }

    beforeRequest(err, args) {
        console.log(args.request.method, args.request.url.toString());
    }

    request(err, args) {
        if (err) {
            console.log('request error');
        } else {
            const sizeObj = args.response.size();
            const size = sizeObj && (sizeObj.header || 0) + (sizeObj.body || 0) || 0;
            console.log(`Response code: ${args.response.code}, duration: ${args.response.responseTime}ms, size: ${size} bytes`);
            this.currItem.response = args.response;
        }
    }

    assertion(err, args) {
        if (err) {
            this.currItem.passed = false;
            this.currItem.failedAssertions.push(args.assertion);
        }
    }

    item(err, args) {
        if (!this.currItem.passed) {
            const msg = this.currItem.failedAssertions.join(", ");
            const details = `Response code: ${this.currItem.response.code}, reason: ${this.currItem.response.reason()}`;
            console.log(`##teamcity[testFailed name='${args.item.name}' message='${msg}' details='${msg} - ${details}']`);
            let body;
            try { body = JSON.parse(this.currItem.response.body) } catch (e) { body = '' };
            console.log('Response body:', body);
        }
        const duration = (this.currItem.response && this.currItem.response.responseTime) || 0;
        console.log(`##teamcity[testFinished name='${args.item.name}' duration='${duration}']`);
    }

    done(err, args) {
        console.log(`##teamcity[testSuiteFinished name='${this.options.collection.name}']`);
    }
}

module.exports = TeamcityReporter;
<commit_msg>Remove all non-TC messages from console output<commit_after>'use strict';

class TeamcityReporter {
    constructor(emitter, reporterOptions, options) {
        this.reporterOptions = reporterOptions;
        this.options = options;
        const events = 'start beforeIteration iteration beforeItem item beforePrerequest prerequest beforeScript script beforeRequest request beforeTest test beforeAssertion assertion console exception beforeDone done'.split(' ');
        events.forEach((e) => { if (typeof this[e] == 'function') emitter.on(e, (err, args) => this[e](err, args)) });
    }

    start(err, args) {
        console.log(`##teamcity[testSuiteStarted name='${this.options.collection.name}']`);
    }

    beforeItem(err, args) {
        this.currItem = {name: args.item.name, passed: true, failedAssertions: []};
        console.log(`##teamcity[testStarted name='${this.currItem.name}' captureStandardOutput='true']`);
    }

    request(err, args) {
        if (!err) {
            this.currItem.response = args.response;
        }
    }

    assertion(err, args) {
        if (err) {
            this.currItem.passed = false;
            this.currItem.failedAssertions.push(args.assertion);
        }
    }

    item(err, args) {
        if (!this.currItem.passed) {
            const msg = this.currItem.failedAssertions.join(", ");
            const responseCode = (this.currItem.response && this.currItem.response.responseTime) || "-";
            const reason = (this.currItem.response && this.currItem.response.reason()) || "-";
            const details = `Response code: ${responseCode}, reason: ${reason}`;
            console.log(`##teamcity[testFailed name='${args.item.name}' message='${msg}' details='${msg} - ${details}']`);
        }
        const duration = (this.currItem.response && this.currItem.response.responseTime) || 0;
        console.log(`##teamcity[testFinished name='${args.item.name}' duration='${duration}']`);
    }

    done(err, args) {
        console.log(`##teamcity[testSuiteFinished name='${this.options.collection.name}']`);
    }
}

module.exports = TeamcityReporter;
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.6.3
'use strict';
var defaultSettings, each, fs, sysPath,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

sysPath = require('path');

fs = require('fs');

each = require('async-each');

defaultSettings = function(extname) {
  switch (extname) {
    case 'jade':
      return {
        regexp: /^\s*(?:include|extends)\s+(.*)/
      };
    case 'styl':
      return {
        regexp: /^\s*@import\s+['"](.*)['"]/,
        exclusion: 'nib'
      };
    case 'less':
      return {
        regexp: /^\s*@import\s+['"](.*)['"]/
      };
    case 'scss':
    case 'sass':
      return {
        regexp: /^\s*@import\s+['"](.*)['"]/,
        prefix: '_',
        exclusion: /^compass/,
        extensionsList: ['scss', 'sass']
      };
  }
};

module.exports = function(_arg) {
  var exclusion, extension, extensionsList, parseDeps, prefix, regexp, rootPath;
  rootPath = _arg.rootPath, extension = _arg.extension, regexp = _arg.regexp, prefix = _arg.prefix, exclusion = _arg.exclusion, extensionsList = _arg.extensionsList;
  parseDeps = function(data, path, depsList, callback) {
    var altExts, deps, parent, prefixed;
    parent = sysPath.dirname(path);
    deps = data.split('\n').map(function(line) {
      return line.match(regexp);
    }).filter(function(match) {
      return (match != null ? match.length : void 0) > 0;
    }).map(function(match) {
      return match[1];
    }).filter(function(path) {
      return !!path && !(function() {
        switch (false) {
          case !(exclusion instanceof RegExp):
            return exclusion.test(path);
          case !(exclusion instanceof String):
            return exclusion === path;
          default:
            return false;
        }
      })();
    }).map(function(path) {
      if (("." + extension) !== sysPath.extname(path)) {
        return path + ("." + extension);
      } else {
        return path;
      }
    }).map(function(path) {
      if (path.charAt(0) === '/') {
        return sysPath.join(rootPath, path.slice(1));
      } else {
        return sysPath.join(parent, path);
      }
    });
    if (prefix != null) {
      prefixed = [];
      deps.forEach(function(path) {
        var dir, file;
        dir = sysPath.dirname(path);
        file = sysPath.basename(path);
        if ((prefix != null) && 0 !== file.indexOf(prefix)) {
          return prefixed.push(sysPath.join(dir, "" + prefix + file));
        }
      });
      deps = deps.concat(prefixed);
    }
    if (extensionsList.length) {
      altExts = [];
      deps.forEach(function(path) {
        var dir;
        dir = sysPath.dirname(path);
        return extensionsList.forEach(function(ext) {
          var base;
          if (("." + ext) !== sysPath.extname(path)) {
            base = sysPath.basename(path, "." + extension);
            return altExts.push(sysPath.join(dir, "" + base + "." + ext));
          }
        });
      });
      deps = deps.concat(altExts);
    }
    if (deps.length) {
      return each(deps, function(path, callback) {
        if (__indexOf.call(depsList, path) >= 0) {
          return callback();
        } else {
          depsList.push(path);
          return fs.readFile(path, {
            encoding: 'utf8'
          }, function(err, data) {
            if (err) {
              return callback();
            }
            return parseDeps(data, path, depsList, callback);
          });
        }
      }, callback);
    } else {
      return callback();
    }
  };
  return function(data, path, callback) {
    var def, depsList, extname, run;
    depsList = [];
    data = void 0;
    extname = sysPath.extname(path).slice(1);
    def = defaultSettings(extname);
    if (extension == null) {
      extension = extname;
    }
    if (regexp == null) {
      regexp = def.regexp;
    }
    if (prefix == null) {
      prefix = def.prefix;
    }
    if (exclusion == null) {
      exclusion = def.exclusion;
    }
    if (extensionsList == null) {
      extensionsList = def.extensionsList || [];
    }
    run = function() {
      return parseDeps(data, path, depsList, function() {
        return callback(null, depsList);
      });
    };
    if (data != null) {
      return run();
    } else {
      return fs.readFile(path, {
        encoding: 'utf8'
      }, function(err, fileContents) {
        if (err) {
          return callback(err);
        }
        console.log('HEY');
        data = fileContents;
        return run();
      });
    }
  };
};
<commit_msg>update compiled<commit_after>// Generated by CoffeeScript 1.6.3
'use strict';
var defaultSettings, each, fs, sysPath,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

sysPath = require('path');

fs = require('fs');

each = require('async-each');

defaultSettings = function(extname) {
  switch (extname) {
    case 'jade':
      return {
        regexp: /^\s*(?:include|extends)\s+(.*)/
      };
    case 'styl':
      return {
        regexp: /^\s*@import\s+['"](.*)['"]/,
        exclusion: 'nib'
      };
    case 'less':
      return {
        regexp: /^\s*@import\s+['"](.*)['"]/
      };
    case 'scss':
    case 'sass':
      return {
        regexp: /^\s*@import\s+['"](.*)['"]/,
        prefix: '_',
        exclusion: /^compass/,
        extensionsList: ['scss', 'sass']
      };
  }
};

module.exports = function(_arg) {
  var exclusion, extension, extensionsList, parseDeps, prefix, regexp, rootPath;
  rootPath = _arg.rootPath, extension = _arg.extension, regexp = _arg.regexp, prefix = _arg.prefix, exclusion = _arg.exclusion, extensionsList = _arg.extensionsList;
  parseDeps = function(data, path, depsList, callback) {
    var altExts, deps, parent, prefixed;
    parent = sysPath.dirname(path);
    deps = data.split('\n').map(function(line) {
      return line.match(regexp);
    }).filter(function(match) {
      return (match != null ? match.length : void 0) > 0;
    }).map(function(match) {
      return match[1];
    }).filter(function(path) {
      return !!path && !(function() {
        switch (false) {
          case !(exclusion instanceof RegExp):
            return exclusion.test(path);
          case !(exclusion instanceof String):
            return exclusion === path;
          default:
            return false;
        }
      })();
    }).map(function(path) {
      if (("." + extension) !== sysPath.extname(path)) {
        return path + ("." + extension);
      } else {
        return path;
      }
    }).map(function(path) {
      if (path.charAt(0) === '/') {
        return sysPath.join(rootPath, path.slice(1));
      } else {
        return sysPath.join(parent, path);
      }
    });
    if (prefix != null) {
      prefixed = [];
      deps.forEach(function(path) {
        var dir, file;
        dir = sysPath.dirname(path);
        file = sysPath.basename(path);
        if ((prefix != null) && 0 !== file.indexOf(prefix)) {
          return prefixed.push(sysPath.join(dir, "" + prefix + file));
        }
      });
      deps = deps.concat(prefixed);
    }
    if (extensionsList.length) {
      altExts = [];
      deps.forEach(function(path) {
        var dir;
        dir = sysPath.dirname(path);
        return extensionsList.forEach(function(ext) {
          var base;
          if (("." + ext) !== sysPath.extname(path)) {
            base = sysPath.basename(path, "." + extension);
            return altExts.push(sysPath.join(dir, "" + base + "." + ext));
          }
        });
      });
      deps = deps.concat(altExts);
    }
    if (deps.length) {
      return each(deps, function(path, callback) {
        if (__indexOf.call(depsList, path) >= 0) {
          return callback();
        } else {
          depsList.push(path);
          return fs.readFile(path, {
            encoding: 'utf8'
          }, function(err, data) {
            if (err) {
              return callback();
            }
            return parseDeps(data, path, depsList, callback);
          });
        }
      }, callback);
    } else {
      return callback();
    }
  };
  return function(data, path, callback) {
    var def, depsList, extname, run;
    depsList = [];
    extname = sysPath.extname(path).slice(1);
    def = defaultSettings(extname);
    if (extension == null) {
      extension = extname;
    }
    if (regexp == null) {
      regexp = def.regexp;
    }
    if (prefix == null) {
      prefix = def.prefix;
    }
    if (exclusion == null) {
      exclusion = def.exclusion;
    }
    if (extensionsList == null) {
      extensionsList = def.extensionsList || [];
    }
    run = function() {
      return parseDeps(data, path, depsList, function() {
        return callback(null, depsList);
      });
    };
    if (data != null) {
      return run();
    } else {
      return fs.readFile(path, {
        encoding: 'utf8'
      }, function(err, fileContents) {
        if (err) {
          return callback(err);
        }
        data = fileContents;
        return run();
      });
    }
  };
};
<|endoftext|>


<commit_before>var _ = require('dominatrix')
var doom = require('doom')()
var boo = require('boo')

var isArray     = Array.isArray
var append      = doom.append
var query       = doom.query
var head        = doom.head
var replace     = doom.replace
var listen      = doom.listen
var toggleClass = doom.toggleClass
var addClass    = doom.addClass
var setText     = doom.setText
var merge       = boo.merge

function last(xs){ return xs[xs.length - 1] }

function verdictFor(result) {
  return result.verdict?  '.' + result.verdict
  :      /* otherwise */  ''
}

function isSlow(result) {
  return result.slow?     '.slow'
  :      /* otherwise */  ''
}

function suiteVerdict(results) {
  var verdicts = results.map(function(r) { return r.verdict })

  return verdicts.indexOf('failure') != -1?  'failure'
  :      verdicts.indexOf('success') != -1?  'success'
  :      /* otherwise */                     ''
}

function isSuiteSlow(results) {
  return results.some(function(result) { return result.slow })
}

function runningTime(result) {
  var time = result.finished - result.started

  return isNaN(time)?     null
  :      /* otherwise */  _('.running-time', '(' + time + 'ms)')
}

function renderException(exception) {
  if (!exception) return _('.no-exception')

  return _('.exception'
          , _('strong.title'
             , _('.type', exception.name)
             , _('.message', exception.message))
          , _('.stack', exception.stack))
}

function renderTitle(result) {
  return _('.title'
          , result.title
          , runningTime(result))
}

function renderResult(type, result, details) {
  return _('li.report.test-result' + verdictFor(result)
                                   + isSlow(result)
                                   + '.' + type
          , toggleDetails(renderTitle(result))
          , details)
}

function renderTestResult(result) {
  return renderResult('test-case'
                     , result
                     , _('.details'
                        , renderException(result.exception)))
}

function renderSuiteResult(result) {
  return renderResult('suite'
                     , result
                     , _('ul.details.active'))
}

function makeTestResult(result) {
  return merge(result
              , { title: result.test.title })
}

function makeSuiteResult(suite, results) {
  return { title: suite.title }
}

var toggleDetails = listen('click', function(ev) {
                     var parent = ev.currentTarget.parentElement
                     toggleClass('active', query('.details', parent))
                   })

function setupSearchPanel(button, panel) {
  var all = doom.concat(button, panel)
  doom.listen( 'click'
             , doom.toggleClass.bind(null, 'active', all)
             , button)
}

function reporter(report) {
  var container = head(query('#test-results'))
  var context   = container
  var current   = null
  var stack     = [] // :: [Result]

  var passedTests  = head(query('#status .passed .test-count'))
  var failedTests  = head(query('#status .failed .test-count'))
  var ignoredTests = head(query('#status .ignored .test-count'))

  report.on('suite:started', function(ev, suite) {
    var render = renderSuiteResult(makeSuiteResult(suite))
    append(context, render)
    stack.push(context)
    context = head(query('.details', render))
  })

  report.on('suite:finished', function(ev, results, suite) {
    var verdict = suiteVerdict(results)
    var slow    = isSuiteSlow(results)

    if (verdict)  addClass(verdict, context.parentElement)
    if (slow)     addClass('slow', context.parentElement)

    context = stack.pop()
  })

  report.on('test:started', function(ev, test) {
    current = renderTestResult(makeTestResult({ test: test }))
    append(context, current)
  })

  report.on('result', function(ev, result) {
    var r = renderTestResult(makeTestResult(result))
    replace(current, r)
  })

  report.on('success', function() {
    setText(report.passed.length, passedTests)
  })

  report.on('failure', function() {
    setText(report.failed.length, failedTests)
  })

  report.on('ignored', function() {
    setText(report.ignored.length, ignoredTests)
  })
}

setupSearchPanel(query('#search-button'), query('#search-panel'))

module.exports = reporter<commit_msg>Computes suite running time.<commit_after>var _ = require('dominatrix')
var doom = require('doom')()
var boo = require('boo')

var isArray     = Array.isArray
var append      = doom.append
var query       = doom.query
var head        = doom.head
var replace     = doom.replace
var listen      = doom.listen
var toggleClass = doom.toggleClass
var addClass    = doom.addClass
var setText     = doom.setText
var merge       = boo.merge

function last(xs){ return xs[xs.length - 1] }

function verdictFor(result) {
  return result.verdict?  '.' + result.verdict
  :      /* otherwise */  ''
}

function isSlow(result) {
  return result.slow?     '.slow'
  :      /* otherwise */  ''
}

function suiteVerdict(results) {
  var verdicts = results.map(function(r) { return r.verdict })

  return verdicts.indexOf('failure') != -1?  'failure'
  :      verdicts.indexOf('success') != -1?  'success'
  :      /* otherwise */                     ''
}

function isSuiteSlow(results) {
  return results.some(function(result) { return result.slow })
}

function suiteTime(results) {
  return results.reduce(function(r, a) {
           return r + (time(a) || 0)
         }, 0)
}

function time(result) {
  return result.finished - result.started
}

function runningTime(t) {
  return isNaN(t)?  null
  :      /* _ */    _('.running-time', '(' + t + 'ms)')
}

function renderException(exception) {
  if (!exception) return _('.no-exception')

  return _('.exception'
          , _('strong.title'
             , _('.type', exception.name)
             , _('.message', exception.message))
          , _('.stack', exception.stack))
}

function renderTitle(result) {
  return _('.title'
          , result.title
          , runningTime(time(result)))
}

function renderResult(type, result, details) {
  return _('li.report.test-result' + verdictFor(result)
                                   + isSlow(result)
                                   + '.' + type
          , toggleDetails(renderTitle(result))
          , details)
}

function renderTestResult(result) {
  return renderResult('test-case'
                     , result
                     , _('.details'
                        , renderException(result.exception)))
}

function renderSuiteResult(result) {
  return renderResult('suite'
                     , result
                     , _('ul.details.active'))
}

function makeTestResult(result) {
  return merge(result
              , { title: result.test.title })
}

function makeSuiteResult(suite, results) {
  return { title: suite.title }
}

var toggleDetails = listen('click', function(ev) {
                     var parent = ev.currentTarget.parentElement
                     toggleClass('active', query('.details', parent))
                   })

function setupSearchPanel(button, panel) {
  var all = doom.concat(button, panel)
  doom.listen( 'click'
             , doom.toggleClass.bind(null, 'active', all)
             , button)
}

function reporter(report) {
  var container = head(query('#test-results'))
  var context   = container
  var current   = null
  var stack     = [] // :: [Result]

  var passedTests  = head(query('#status .passed .test-count'))
  var failedTests  = head(query('#status .failed .test-count'))
  var ignoredTests = head(query('#status .ignored .test-count'))

  report.on('suite:started', function(ev, suite) {
    var render = renderSuiteResult(makeSuiteResult(suite))
    append(context, render)
    stack.push(context)
    context = head(query('.details', render))
  })

  report.on('suite:finished', function(ev, results, suite) {
    var verdict = suiteVerdict(results)
    var slow    = isSuiteSlow(results)
    var parent  = context.parentElement

    if (verdict)  addClass(verdict, parent)
    if (slow)     addClass('slow', parent)

    append( head(query('.title', parent))
          , runningTime(suiteTime(results)))

    context = stack.pop()
  })

  report.on('test:started', function(ev, test) {
    current = renderTestResult(makeTestResult({ test: test }))
    append(context, current)
  })

  report.on('result', function(ev, result) {
    var r = renderTestResult(makeTestResult(result))
    replace(current, r)
  })

  report.on('success', function() {
    setText(report.passed.length, passedTests)
  })

  report.on('failure', function() {
    setText(report.failed.length, failedTests)
  })

  report.on('ignored', function() {
    setText(report.ignored.length, ignoredTests)
  })
}

setupSearchPanel(query('#search-button'), query('#search-panel'))

module.exports = reporter<|endoftext|>


<commit_before>const XMLDownloader = require("./xmldownloader");
const XMLParser = require("./xmlparser");
const EntryParser = require("./entryparser");

const EventEmitter = require("events");

// 3rd party dependencies
const CronJob = require("cron").CronJob;

class Realworks extends EventEmitter {
	constructor(options) {
		super();

		this._options = options;

		if(!this._options.user) throw new TypeError("'options.user' is not set");
		if(!this._options.password) throw new TypeError("'options.password' is not set");

		this._cron = this._options.cron || true;
		this._cronPattern = this._options.cronPattern || "0 0 9 * * *";
		this._cronTimezone = this._options.cronTimezone || "Europe/Amsterdam";

		if(!this._options.types) throw new TypeError("'options.types' is not set");
		if(typeof this._options.types == "string") this._options.types = [this._options.types];
		this._types = this._options.types;

		this._downloader = new XMLDownloader(this._options, this);
		this._converter = new XMLParser(this._options, this);
		this._parser = new EntryParser(this._options, this);

		if(this._cron) {
			try {
				this._cronjob = new CronJob(this._cronPattern, function () {
					this.update()
						.catch((err) => {
							this.emit("error", err);
						});
				}, null, true, this._cronTimezone);
			} catch(err) {
				throw new Error("Invalid cron pattern: "+err.message);
			}
		}
	}

	update() {
		return new Promise((resolve, reject) => {
			Promise.all(this._types.map((type) => {
				return this._downloader.download(type)
					.then((xmlData) => {
						return this._converter.parse(xmlData);
					})
					.then((entries) => {
						return this._parser.parse(entries);
					});
			}))
			.then((results) => {
				resolve(results);
			})
			.catch((err) => {
				reject(err);
			});
		});
	}
}

module.exports = Realworks;<commit_msg>Fix "this" is not defined<commit_after>const XMLDownloader = require("./xmldownloader");
const XMLParser = require("./xmlparser");
const EntryParser = require("./entryparser");

const EventEmitter = require("events");

// 3rd party dependencies
const CronJob = require("cron").CronJob;

class Realworks extends EventEmitter {
	constructor(options) {
		super();

		this._options = options;

		if(!this._options.user) throw new TypeError("'options.user' is not set");
		if(!this._options.password) throw new TypeError("'options.password' is not set");

		this._cron = this._options.cron || true;
		this._cronPattern = this._options.cronPattern || "0 0 9 * * *";
		this._cronTimezone = this._options.cronTimezone || "Europe/Amsterdam";

		if(!this._options.types) throw new TypeError("'options.types' is not set");
		if(typeof this._options.types == "string") this._options.types = [this._options.types];
		this._types = this._options.types;

		this._downloader = new XMLDownloader(this._options, this);
		this._converter = new XMLParser(this._options, this);
		this._parser = new EntryParser(this._options, this);

		if(this._cron) {
			try {
				this._cronjob = new CronJob(this._cronPattern, function () {
					this.update()
						.catch((err) => {
							this.emit("error", err);
						});
				}.bind(this), null, true, this._cronTimezone);
			} catch(err) {
				throw new Error("Invalid cron pattern: "+err.message);
			}
		}
	}

	update() {
		return new Promise((resolve, reject) => {
			Promise.all(this._types.map((type) => {
				return this._downloader.download(type)
					.then((xmlData) => {
						return this._converter.parse(xmlData);
					})
					.then((entries) => {
						return this._parser.parse(entries);
					});
			}))
			.then((results) => {
				resolve(results);
			})
			.catch((err) => {
				reject(err);
			});
		});
	}
}

module.exports = Realworks;<|endoftext|>


<commit_before>'use strict';
/**
 * @file Easy access to AnyFetch API.
 *
 * @see http://anyFetch.com
 */
 // TODO: migrate to supertest
var request = require('request')
var util = require('util');

// TODO: wrap into an Anyfetch class
// TODO: Anyfetch.getAccessToken(APP_ID, APP_SECRET, code, function(err, accessToken)
// Use the access token from the Anyfetch object instance
var accessToken = process.env.ACCESS_TOKEN;

// TODO: make configurable
var apiUrl = 'https://api.anyfetch.com';

/**
 * Will be used to automatically generate the simplest mapping functions
 * @see api.anyfetch.com/config/routes.js
 */
var defaultDescriptor = {
  expectedStatus: 200,
  verb: 'GET',
  requireId: false,
  params: null,
  body: null
}

var mappingDescriptor = {
  'getStatus': {
    endpoint: '/status'
  },

  // ----- Index
  'getIndex': {
    endpoint: '/'
  },

  // ----- Company
  'getCompany': {
    endpoint: '/company'
  },
  'postCompanyUpdate': {
    endpoint: '/company/update',
    verb: 'POST',
    expectedStatus: 202
  },
  'deleteCompanyReset': {
    endpoint: '/company/reset',
    verb: 'DELETE',
    expectedStatus: 204
  },

  // ----- Subcompanies
  'getSubcompanies': {
    endpoint: '/subcompanies'
  },
  'postSubcompanies': {
    endpoint: '/subcompanies',
    verb: 'POST',
    body: ['name', 'hydraters']
  },
  'getSubcompanyById': {
    endpoint: '/subcompanies/{id}',
    requireId: true
  },
  'deleteSubcompanyById': {
    endpoint: '/subcompanies/{id}',
    verb: 'DELETE',
    requireId: true,
    params: ['force']
  },

  // ----- Documents (by id or by identifier)
  'getDocuments': {
    endpoint: '/documents',
    // TODO: here, parameter `_meta` could actually be any key
    params: ['search', 'before', 'after','document_type', 'token', '_meta', 'has_meta', 'snippet_size', 'start', 'limit']
  },
  'postDocuments': {
    endpoint: '/documents',
    verb: 'POST',
    body: ['identifier', 'document_type', 'actions', 'data', 'metadata', 'related', 'user_access']
  },
  // TODO: Post document file (with id param, with multipart form upload)
  'getDocumentById': {
    endpoint: '/documents/{id}',
    requireId: true // Or generate params directly from `endpoint`?
    // TODO: body ≠ GET params
  },
  'deleteDocumentById': {
    endpoint: '/documents/{id}',
    verb: 'DELETE',
    requireId: true
  },

  // ----- Users
  'getUsers': {
    endpoint: '/users'
  },
  // TODO: rename to `postUser` for clarity? (but that would break the naming convention)
  'postUsers': {
    endpoint: '/users',
    verb: 'POST',
    body: ['email', 'name', 'password', 'is_admin']
  },
  'getUserById': {
    endpoint: '/users/{id}',
    requireId: true
  },
  'deleteUserById': {
    endpoint: '/users/{id}',
    verb: 'DELETE',
    requireId: true,
    expectedStatus: 204
  },

  // ----- Document types
  'getDocumentTypes': {
    endpoint: '/document_types'
  },

  // ----- Providers
  'getProviders': {
    endpoint: '/providers'
  }
}

var generateMapping = function(config) {
  // `config` extends the default descriptor
  for(var i in defaultDescriptor) {
    if(!config[i])
      config[i] = defaultDescriptor[i];
  }

  return function() {
    // Convert arguments to an array
    var args = [];
    for (var i in arguments)
      args.push(arguments[i]);

    // We must support quite a lot of different call syntaxes
    var params = {},
        body = {};

    // cb is always the last parameter
    var cb = args.pop();

    if (config.body) {
      body = args.pop();
      // Make sure that every field of the body is accepted
      for(var key in body) {
        if(config.body.indexOf(key) < 0)
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s body'));
      }
    }

    if (config.params) {
      params = args.pop();
      // Make sure that every GET parameter is accepted
      for(var key in params) {
        if(config.params.indexOf(key) < 0)
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s GET parameters'));
      }
    }

    // id is always the first parameter (when it's actually required)
    if(config.requireId) {
      var id = args.pop();
      if(!isNaN(id)) {
        // Substitute id parameter in endpoint string
        config.endpoint = config.endpoint.replace('{id}', id);
      }
      else
        return cb(new Error('Argument error, the first parameter must be a numeric id'));
    }

    var options = {
      // TODO: make sure SSL is used
      url: apiUrl + config.endpoint,
      method: config.verb,
      qs: params, // TODO: url encode
      headers: {
        'Authorization': 'Bearer ' + accessToken
      },
      body: JSON.stringify(body)
    };

    request(options, function(err, res, body) {
      if(res.statusCode != config.expectedStatus)
        return cb(new Error('Received code ' + res.statusCode + ', expected ' + config.expectedStatus));

      cb(err, body);
    });
  };
};

// Generate the function for each endpoint
var mappingFunctions = {};
for (var name in mappingDescriptor) {
  mappingFunctions[name] = generateMapping(mappingDescriptor[name]);
}

// TODO: add nice semantic aliases
// E.g. postSubcompany --> postSubcompanies
// What is actually done is to post ONE company, so it makes more sense)

// TODO: more complex syntax: getDocumentById(123).getRelated(cb);<commit_msg>Code style & comments<commit_after>'use strict';
/**
 * @file Easy access to AnyFetch API.
 *
 * @see http://anyFetch.com
 */
 // TODO: migrate to supertest
var request = require('request')
var util = require('util');

// TODO: wrap into an Anyfetch class
// TODO: Anyfetch.getAccessToken(APP_ID, APP_SECRET, code, function(err, accessToken)
// Use the access token from the Anyfetch object instance
var accessToken = process.env.ACCESS_TOKEN;

// TODO: make configurable
var apiUrl = 'https://api.anyfetch.com';

/**
 * Will be used to automatically generate the simplest mapping functions
 * @see api.anyfetch.com/config/routes.js
 */
var defaultDescriptor = {
  expectedStatus: 200,
  verb: 'GET',
  requireId: false,
  params: null,
  body: null
}

var mappingDescriptor = {
  'getStatus': {
    endpoint: '/status'
  },

  // ----- Index
  'getIndex': {
    endpoint: '/'
  },

  // ----- Company
  'getCompany': {
    endpoint: '/company'
  },
  'postCompanyUpdate': {
    endpoint: '/company/update',
    verb: 'POST',
    expectedStatus: 202
  },
  'deleteCompanyReset': {
    endpoint: '/company/reset',
    verb: 'DELETE',
    expectedStatus: 204
  },

  // ----- Subcompanies
  'getSubcompanies': {
    endpoint: '/subcompanies'
  },
  'postSubcompanies': {
    endpoint: '/subcompanies',
    verb: 'POST',
    body: ['name', 'hydraters']
  },
  'getSubcompanyById': {
    endpoint: '/subcompanies/{id}',
    requireId: true
  },
  'deleteSubcompanyById': {
    endpoint: '/subcompanies/{id}',
    verb: 'DELETE',
    requireId: true,
    params: ['force']
  },

  // ----- Documents (by id or by identifier)
  'getDocuments': {
    endpoint: '/documents',
    // TODO: here, parameter `_meta` could actually be any key
    params: ['search', 'before', 'after','document_type', 'token', '_meta', 'has_meta', 'snippet_size', 'start', 'limit']
  },
  'postDocuments': {
    endpoint: '/documents',
    verb: 'POST',
    body: ['identifier', 'document_type', 'actions', 'data', 'metadata', 'related', 'user_access']
  },
  // TODO: Post document file (with id param, with multipart form upload)
  'getDocumentById': {
    endpoint: '/documents/{id}',
    requireId: true // Or generate params directly from `endpoint`?
    // TODO: body ≠ GET params
  },
  'deleteDocumentById': {
    endpoint: '/documents/{id}',
    verb: 'DELETE',
    requireId: true
  },

  // ----- Users
  'getUsers': {
    endpoint: '/users'
  },
  // TODO: rename to `postUser` for clarity? (but that would break the naming convention)
  'postUsers': {
    endpoint: '/users',
    verb: 'POST',
    body: ['email', 'name', 'password', 'is_admin']
  },
  'getUserById': {
    endpoint: '/users/{id}',
    requireId: true
  },
  'deleteUserById': {
    endpoint: '/users/{id}',
    verb: 'DELETE',
    requireId: true,
    expectedStatus: 204
  },

  // ----- Document types
  'getDocumentTypes': {
    endpoint: '/document_types'
  },

  // ----- Providers
  'getProviders': {
    endpoint: '/providers'
  }
}

var generateMapping = function(config) {
  // `config` extends the default descriptor
  for(var i in defaultDescriptor) {
    if(!config[i])
      config[i] = defaultDescriptor[i];
  }

  /**
   * Example of accepted call syntaxes:
   * (depending on the requirements of the API endpoint)
   * apiMapping(cb)
   * apiMapping(id, cb)
   * apiMapping(body, cb)
   * apiMapping(id, body, cb)
   * apiMapping(id, params, cb)
   * apiMapping(params, cb)
   */
  return function apiMapping() {
    // Convert arguments to an array
    var args = [];
    for (var i in arguments)
      args.push(arguments[i]);

    // We must support quite a lot of different call syntaxes
    var params = {};
    var body = {};

    // cb is always the last parameter
    var cb = args.pop();

    if (config.body) {
      body = args.pop() || {};
      // Make sure that every field of the body is accepted
      for(var key in body) {
        if(config.body.indexOf(key) < 0) {
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s body'));
        }
      }
    }

    if (config.params) {
      params = args.pop() || {};
      // Make sure that every GET parameter is accepted
      for(var key in params) {
        if(config.params.indexOf(key) === -1) {
          return cb(new Error('Argument error, the key ' + key + ' is not allowed in this request\'s GET parameters'));
        }
      }
    }

    // id is always the first parameter (when it's actually required)
    if(config.requireId) {
      var id = args.pop();
      if(!isNaN(id)) {
        // Substitute id parameter in endpoint string
        config.endpoint = config.endpoint.replace('{id}', id);
      }
      else {
        return cb(new Error('Argument error, the first parameter must be a numeric id'));
      }
    }

    var options = {
      // TODO: make sure SSL is used
      url: apiUrl + config.endpoint,
      method: config.verb,
      qs: params, // TODO: url encode
      headers: {
        'Authorization': 'Bearer ' + accessToken
      },
      body: JSON.stringify(body)
    };

    request(options, function(err, res, body) {
      if(res.statusCode != config.expectedStatus) {
        return cb(new Error('Received code ' + res.statusCode + ', expected ' + config.expectedStatus));
      }

      cb(err, body);
    });
  };
};

// Generate the function for each endpoint
var mappingFunctions = {};
for (var name in mappingDescriptor) {
  mappingFunctions[name] = generateMapping(mappingDescriptor[name]);
}

// TODO: add nice semantic aliases
// E.g. postSubcompany --> postSubcompanies
// What is actually done is to post ONE company, so it makes more sense)

// TODO: more complex syntax: getDocumentById(123).getRelated(cb);<|endoftext|>


<commit_before>/**
 * Created by gillbeits on 01/04/15.
 */

var
  HOST        = 'http://fontello.com',

  fs          = require('fs'),
  crypto      = require('crypto'),
  needle      = require('needle'),
  through2    = require('through2'),
  AdmZip      = require('adm-zip'),
  path        = require('path'),
  Vinyl       = reguire('vinyl'),
  log         = require('fancy-log'),
  yargs       = require('yargs'),
  extend      = require('util')._extend,

  PluginError = require('gulp-error')
  ;

const PLUGIN_NAME = 'gulp-fontello';

function fontello (opts) {
  "use strict";

  opts = extend({
    assetsOnly: true,
    host: HOST
  }, extend(opts || {}, yargs.argv));

  return through2.obj(function (file, enc, callback) {
    var self = this;

    var process = function (zipContents, callback) {
      var
        zip = new AdmZip(zipContents),
        zipEntries = zip.getEntries()
        ;

      zipEntries.forEach(function (zipEntry) {
        var dirName, fileName, pathName, _ref;

        if (zipEntry.isDirectory) return;

        pathName = zipEntry.entryName;
        dirName = (_ref = path.dirname(pathName).match(/\/([^\/]*)$/)) != null ? _ref[1] : void 0;
        fileName = path.basename(pathName);

        if (opts.assetsOnly && !dirName) return;

        var content = zipEntry.getData();
        if (opts['font'] && opts['font'] != 'font' && path.extname(fileName) == '.css') {
          content = new Buffer(String(content).replace(new RegExp('\.\.\/font\/', 'g'), '../' + opts['font'] + '/'));
        }

        var file = new Vinyl({
          cwd: "./",
          path: (dirName ? ((opts[dirName] ? opts[dirName] : dirName) + '/') : '') + fileName,
          contents: content
        });
        self.push(file);
      });

      callback();
    };

    var fetchFromHost = function (callback) {
      var stream = through2.obj(function (file) {
        if (!file.toString()) {
          throw new PluginError(PLUGIN_NAME, "No session at Fontello for zip archive");
        }

        needle.get(opts.host + "/" + file.toString() + "/get", function (error, response) {
          if (error) {
            throw error;
          }

          // store in cache if configured
          if (opts.cache) {
            opts.cache.set(configHash, response.body);
          }

          process(response.body, callback);
        });
      });

      needle.post(opts.host, {
        config: {
          buffer: file.contents,
          filename: 'fontello.json',
          content_type: 'application/json'
        }
      }, {multipart: true}).pipe(stream);
    };

    // create SHA256 of the contents of the config file
    var configHash = crypto.createHash('sha256').update(file.contents).digest('hex');

    // use cache if configured
    if (opts.cache) {
      // check cache first
      opts.cache.get(configHash, function (error, cachedResponseBody) {
        // on cache err or empty response use normal fetch
        if (error || !cachedResponseBody) {
          fetchFromHost(callback);
        } else {
          log('using cached fontello zip for config with sha1: ' + configHash);
          process(cachedResponseBody, callback);
        }
      });
    } else {
      fetchFromHost(callback);
    }
  });
}

/**
 * simple file-system based cache
 *
 * @param cacheDir
 * @returns {{get: 'get', set: 'set'}}
 */
fontello.simpleFsCache = function(cacheDir) {
  if (!fs.lstatSync(cacheDir).isDirectory()) {
    fs.mkdirSync(cacheDir);
  }

  return {
    'get': function(file, cb) {
      fs.readFile(path.join(cacheDir, file + ".cached.zip"), function(err, result) {
        if (err || !result) {
          cb();
        } else {
          cb(null, result);
        }
      });
    },
    'set': function(file, response) {
      fs.writeFile(path.join(cacheDir, file + ".cached.zip"), response, function noop() {});
    }
  }
};

module.exports = fontello;
<commit_msg>correct syntax error<commit_after>/**
 * Created by gillbeits on 01/04/15.
 */

var
  HOST        = 'http://fontello.com',

  fs          = require('fs'),
  crypto      = require('crypto'),
  needle      = require('needle'),
  through2    = require('through2'),
  AdmZip      = require('adm-zip'),
  path        = require('path'),
  Vinyl       = require('vinyl'),
  log         = require('fancy-log'),
  yargs       = require('yargs'),
  extend      = require('util')._extend,

  PluginError = require('gulp-error')
  ;

const PLUGIN_NAME = 'gulp-fontello';

function fontello (opts) {
  "use strict";

  opts = extend({
    assetsOnly: true,
    host: HOST
  }, extend(opts || {}, yargs.argv));

  return through2.obj(function (file, enc, callback) {
    var self = this;

    var process = function (zipContents, callback) {
      var
        zip = new AdmZip(zipContents),
        zipEntries = zip.getEntries()
        ;

      zipEntries.forEach(function (zipEntry) {
        var dirName, fileName, pathName, _ref;

        if (zipEntry.isDirectory) return;

        pathName = zipEntry.entryName;
        dirName = (_ref = path.dirname(pathName).match(/\/([^\/]*)$/)) != null ? _ref[1] : void 0;
        fileName = path.basename(pathName);

        if (opts.assetsOnly && !dirName) return;

        var content = zipEntry.getData();
        if (opts['font'] && opts['font'] != 'font' && path.extname(fileName) == '.css') {
          content = new Buffer(String(content).replace(new RegExp('\.\.\/font\/', 'g'), '../' + opts['font'] + '/'));
        }

        var file = new Vinyl({
          cwd: "./",
          path: (dirName ? ((opts[dirName] ? opts[dirName] : dirName) + '/') : '') + fileName,
          contents: content
        });
        self.push(file);
      });

      callback();
    };

    var fetchFromHost = function (callback) {
      var stream = through2.obj(function (file) {
        if (!file.toString()) {
          throw new PluginError(PLUGIN_NAME, "No session at Fontello for zip archive");
        }

        needle.get(opts.host + "/" + file.toString() + "/get", function (error, response) {
          if (error) {
            throw error;
          }

          // store in cache if configured
          if (opts.cache) {
            opts.cache.set(configHash, response.body);
          }

          process(response.body, callback);
        });
      });

      needle.post(opts.host, {
        config: {
          buffer: file.contents,
          filename: 'fontello.json',
          content_type: 'application/json'
        }
      }, {multipart: true}).pipe(stream);
    };

    // create SHA256 of the contents of the config file
    var configHash = crypto.createHash('sha256').update(file.contents).digest('hex');

    // use cache if configured
    if (opts.cache) {
      // check cache first
      opts.cache.get(configHash, function (error, cachedResponseBody) {
        // on cache err or empty response use normal fetch
        if (error || !cachedResponseBody) {
          fetchFromHost(callback);
        } else {
          log('using cached fontello zip for config with sha1: ' + configHash);
          process(cachedResponseBody, callback);
        }
      });
    } else {
      fetchFromHost(callback);
    }
  });
}

/**
 * simple file-system based cache
 *
 * @param cacheDir
 * @returns {{get: 'get', set: 'set'}}
 */
fontello.simpleFsCache = function(cacheDir) {
  if (!fs.lstatSync(cacheDir).isDirectory()) {
    fs.mkdirSync(cacheDir);
  }

  return {
    'get': function(file, cb) {
      fs.readFile(path.join(cacheDir, file + ".cached.zip"), function(err, result) {
        if (err || !result) {
          cb();
        } else {
          cb(null, result);
        }
      });
    },
    'set': function(file, response) {
      fs.writeFile(path.join(cacheDir, file + ".cached.zip"), response, function noop() {});
    }
  }
};

module.exports = fontello;
<|endoftext|>


<commit_before>/* global analytics */
/* eslint no-console:0, no-unused-vars:0, no-extra-parens:0 */

'use strict';

var integration = require('analytics.js-integration');
var request = require('visionmedia/superagent');
var prefix = require('johntron/superagent-prefix');
var async = require('caolan/async');
window._astq = window._astq || [];

/**
 * Expose `Astronomer` integration.
 */
var Astronomer = module.exports = exports = integration('astronomer')
  .global('_astq')
  .option('appId', null)
  .option('credentialServer', 'https://app.astronomer.io:443')
  .option('credentialsExpiration', 900)
  .option('trackAllPages', false)
  .option('trackNamedPages', true)
  .option('trackCategorizedPages', true)
  .tag('library', '<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.33.min.js">');

/**
 * Initialize astronomer.
 * @param {Facade} page The page object
 */
Astronomer.prototype.initialize = function() {
  var self = this;
  self.props = {};
  self.kinesis = null;
  self.kinesisQueue = async.queue(self.putRecord.bind(self), 1);

  console.log('Authenticating with ' + self.options.credentialServer);

  self.load('library', self.ready);

  // Load lib, auth, config, ready, dequeue
  // async.waterfall([
  //   self.loadAwsLib.bind(self),
  //   self.auth.bind(self)
  // ],
  // function(err, response) {
  //   self.configAws(response.body);
  //   self.setCredentialToken(response.body.credentials.Token);
  //   self.ready();
  //   self.dequeue();
  // });
};

/**
 * Load the aws library from CDN
 * @param {Function} callback Callback
 */
// Astronomer.prototype.loadAwsLib = function(callback) {
//   this.load('library', callback);
// };

/**
 * Authenticate with our server
 * @param {Function} callback Callback
 */
Astronomer.prototype.auth = function() {
  var self = this;
  console.log('authing');

  // Pause the event queue
  self.kinesisQueue.pause();

  // Request fresh config (token)
  request.get('/api/v1/applications/credentials/' + self.options.appId)
    .use(prefix(self.options.credentialServer))
    .end(function(err, response) {
      console.log('authed', err, response);
      // Update global config object
      self.config = response.body;

      console.log(self.kinesis.config);

      // Assign kinesis service object to new one with fresh config
      self.kinesis = new Window.AWS.Kinesis({
        region: self.config.region,
        credentials: new window.AWS.WebIdentityCredentials({
          RoleArn: self.config.roleArn,
          WebIdentityToken: self.config.credentials.Token,
          DurationSeconds: self.options.credentialsExpiration
        })
      });

      console.log(self.kinesis.config);

      // Do not resume, unless we have gotten fresh config (token)
      if (!err) {
        self.kinesisQueue.resume();
      }
    });
};

/**
 * Assign our kinesis object with a new one configured with new credentials
 * @param {Object} config Config object from our server
 */
// Astronomer.prototype.configAws = function(config) {
//   this.config = config;
//   this.kinesis = new window.AWS.Kinesis({
//     region: this.config.region,
//     credentials: new window.AWS.WebIdentityCredentials({
//       RoleArn: this.config.roleArn,
//       DurationSeconds: this.options.credentialsExpiration
//     })
//   });
// };

/**
 * Invalidate credentials and set new token
 * @param {String} token The new token
 */
// Astronomer.prototype.setCredentialToken = function(token) {
//   this.kinesis.config.credentials.expired = true;
//   this.kinesis.config.credentials.params.WebIdentityToken = token;
// };

/**
 * Replay the queue
 */
Astronomer.prototype.dequeue = function() {
  while (window._astq.length > 0) {
    var item = window._astq.shift();
    var method = item.shift();
    if (analytics[method]) analytics[method].apply(analytics, item);
  }
};

/**
 * Has the astronomer library been loaded yet?
 * @return {Boolean}
 */
Astronomer.prototype.loaded = function() {
  return !!((((window.AWS) || {}).config || {}).credentials || {}).accessKeyId;
};

/**
 * Trigger a page view.
 * @param {Facade} page A page object
 */
Astronomer.prototype.page = function(page) {
  var category = page.category();
  var props = page.properties();
  var name = page.fullName();
  var opts = this.options;

  // all pages
  if (opts.trackAllPages) {
    this.track(page.track());
  }

  // named pages
  if (name && opts.trackNamedPages) {
    this.track(page.track(name));
  }

  // categorized pages
  // if (category && opts.trackCategorizedPages) {
  //   this.track(page.track(category));
  // }
};

/**
 * Identify a user.
 * @param {Facade} identify An identify object
 */
Astronomer.prototype.identify = function(identify) {
  var id = identify.userId();
  var traits = identify.traits();
  this.props.userId = id;
  this.props.userProperties = traits;
};

/**
 * Associate the current user with a group of users.
 * @param {Facade} group A group object
 */
Astronomer.prototype.group = function(group) {
  var id = group.groupId();
  var traits = group.traits();
  this.props.groupId = id;
  this.props.groupProperties = traits;
};

/**
 * Track an event.
 * @param {Facade} track A track object
 */
Astronomer.prototype.track = function(track) {
  try {
      var self = this;
      console.log('track');

      var record = JSON.stringify({
        event: track.event(),
        properties: track.properties(),
        anonymousId: analytics.user().anonymousId(),
        userId: self.props.userId,
        traits: self.props.userProperties
      });

      console.log('track', self.kinesis.config.credentials);

      var expireTime = (((self.kinesis || {}).config || {}).credentials || {}).expireTime;
      if (!expireTime || expireTime.getTime() <= Date.now()) {
        console.log('expired');
        self.auth();
      }

      self.kinesisQueue.push(record);
  } catch(e) {
    console.error(e);
  }
};

Astronomer.prototype.putRecord = function(record, callback) {
  var params = {
    Data: record,
    StreamName: this.config.streamName,
    PartitionKey: this.options.appId
  };

  console.log('putting record');
  this.kinesis.putRecord(params, function(err, data) {
    console.log(err, data);
    callback();
  });
};
<commit_msg>SAVEPOINT<commit_after>/* global analytics */
/* eslint no-console:0, no-unused-vars:0, no-extra-parens:0 */

'use strict';

var integration = require('analytics.js-integration');
var request = require('visionmedia/superagent');
var prefix = require('johntron/superagent-prefix');
var async = require('caolan/async');
window._astq = window._astq || [];

/**
 * Expose `Astronomer` integration.
 */
var Astronomer = module.exports = exports = integration('astronomer')
  .global('_astq')
  .option('appId', null)
  .option('credentialServer', 'https://app.astronomer.io:443')
  .option('credentialsExpiration', 900)
  .option('trackAllPages', false)
  .option('trackNamedPages', true)
  .option('trackCategorizedPages', true)
  .tag('library', '<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.33.min.js">');

/**
 * Initialize astronomer.
 * @param {Facade} page The page object
 */
Astronomer.prototype.initialize = function() {
  var self = this;
  self.props = {};
  self.kinesis = null;
  self.kinesisQueue = async.queue(self.putRecord.bind(self), 1);

  console.log('Authenticating with ' + self.options.credentialServer);

  self.load('library', self.ready);

  // Load lib, auth, config, ready, dequeue
  // async.waterfall([
  //   self.loadAwsLib.bind(self),
  //   self.auth.bind(self)
  // ],
  // function(err, response) {
  //   self.configAws(response.body);
  //   self.setCredentialToken(response.body.credentials.Token);
  //   self.ready();
  //   self.dequeue();
  // });
};

/**
 * Load the aws library from CDN
 * @param {Function} callback Callback
 */
// Astronomer.prototype.loadAwsLib = function(callback) {
//   this.load('library', callback);
// };

/**
 * Authenticate with our server
 * @param {Function} callback Callback
 */
Astronomer.prototype.auth = function() {
  var self = this;
  console.log('authing');

  // Pause the event queue
  self.kinesisQueue.pause();

  // Request fresh config (token)
  request.get('/api/v1/applications/credentials/' + self.options.appId)
    .use(prefix(self.options.credentialServer))
    .end(function(err, response) {
      console.log('authed', err, response);
      // Update global config object
      self.config = response.body;

      console.log(self.kinesis.config);

      // Assign kinesis service object to new one with fresh config
      self.kinesis = new Window.AWS.Kinesis({
        region: self.config.region,
        credentials: new window.AWS.WebIdentityCredentials({
          RoleArn: self.config.roleArn,
          WebIdentityToken: self.config.credentials.Token,
          DurationSeconds: self.options.credentialsExpiration
        })
      });

      console.log(self.kinesis.config);

      // Do not resume, unless we have gotten fresh config (token)
      if (!err) {
        self.kinesisQueue.resume();
      }
    });
};

/**
 * Assign our kinesis object with a new one configured with new credentials
 * @param {Object} config Config object from our server
 */
// Astronomer.prototype.configAws = function(config) {
//   this.config = config;
//   this.kinesis = new window.AWS.Kinesis({
//     region: this.config.region,
//     credentials: new window.AWS.WebIdentityCredentials({
//       RoleArn: this.config.roleArn,
//       DurationSeconds: this.options.credentialsExpiration
//     })
//   });
// };

/**
 * Invalidate credentials and set new token
 * @param {String} token The new token
 */
// Astronomer.prototype.setCredentialToken = function(token) {
//   this.kinesis.config.credentials.expired = true;
//   this.kinesis.config.credentials.params.WebIdentityToken = token;
// };

/**
 * Replay the queue
 */
Astronomer.prototype.dequeue = function() {
  while (window._astq.length > 0) {
    var item = window._astq.shift();
    var method = item.shift();
    if (analytics[method]) analytics[method].apply(analytics, item);
  }
};

/**
 * Has the astronomer library been loaded yet?
 * @return {Boolean}
 */
Astronomer.prototype.loaded = function() {
  return !!((((window.AWS) || {}).config || {}).credentials || {}).accessKeyId;
};

/**
 * Trigger a page view.
 * @param {Facade} page A page object
 */
Astronomer.prototype.page = function(page) {
  var category = page.category();
  var props = page.properties();
  var name = page.fullName();
  var opts = this.options;

  // all pages
  if (opts.trackAllPages) {
    this.track(page.track());
  }

  // named pages
  if (name && opts.trackNamedPages) {
    this.track(page.track(name));
  }

  // categorized pages
  // if (category && opts.trackCategorizedPages) {
  //   this.track(page.track(category));
  // }
};

/**
 * Identify a user.
 * @param {Facade} identify An identify object
 */
Astronomer.prototype.identify = function(identify) {
  var id = identify.userId();
  var traits = identify.traits();
  this.props.userId = id;
  this.props.userProperties = traits;
};

/**
 * Associate the current user with a group of users.
 * @param {Facade} group A group object
 */
Astronomer.prototype.group = function(group) {
  var id = group.groupId();
  var traits = group.traits();
  this.props.groupId = id;
  this.props.groupProperties = traits;
};

/**
 * Track an event.
 * @param {Facade} track A track object
 */
Astronomer.prototype.track = function(track) {
  var self = this;

  var record = JSON.stringify({
    event: track.event(),
    properties: track.properties(),
    anonymousId: analytics.user().anonymousId(),
    userId: self.props.userId,
    traits: self.props.userProperties
  });

  var expireTime = (((self.kinesis || {}).config || {}).credentials || {}).expireTime;
  if (!expireTime || expireTime.getTime() <= Date.now()) {
    console.log('expired');
    self.auth();
  }

  self.kinesisQueue.push(record);
};

Astronomer.prototype.putRecord = function(record, callback) {
  var params = {
    Data: record,
    StreamName: this.config.streamName,
    PartitionKey: this.options.appId
  };

  console.log('putting record');
  this.kinesis.putRecord(params, function(err, data) {
    console.log(err, data);
    callback();
  });
};
<|endoftext|>


<commit_before>var fs = require('fs');
var grunt = require('grunt');
var opts = {
  stdout: true,
  stderr: true,
  failOnError: true
};

var isCardDir = function (dir){
  return dir[0] != ".";
};

function cardGruntCommand(cardName) {
  var cmd = "(cd cards/" + cardName + " && grunt)";
  return cmd;
}

function cardGruntDeployCommand(cardName) {
  var cmd = "(cd cards/" + cardName + " && grunt deploy)";
  return cmd;
}

function cardNpmInstallCommand(cardName) {
  var cmd = "(cd cards/" + cardName + " && npm install)";
  return cmd;
}

function cardNpmRefreshCommand(cardName) {
  var cmd = "rm -rf cards/*/node_modules";
  return cmd;
}

function cardIngestManigestCommand(cardName) {
  var manifestPath = 'cards/' + cardName + '/dist/dev/' + cardName + '/manifest.json';
  var cmd = '(cd glazier-server && bundle exec rake "glazier:card:ingest[../' + manifestPath + ']")';
  return cmd;
}

function herokuIngestCommand(cardName) {
  var deployJSON = grunt.file.readJSON('cards/' + cardName + '/package.json');
  var glazierConfig = deployJSON.glazierConfig;
  var url = glazierConfig.assetHost + '/assets/cards/' + glazierConfig.repositoryName + '/manifest.json';
  var cmd = "(cd glazier-server && heroku surrogate rails runner \"PaneType.ingest('" + url + "')\" --app glazier)";
  return cmd;
}

herokuIngestIndexCommand = "(cd glazier-server && heroku surrogate rake 'glazier:ingest_as_current[../tmp/public/index.html]' --app glazier)";

module.exports = {
  glazierServer: {
    command: [
      "cd glazier-server",
      "PORT=3040 foreman start"
    ].join(' && '),
    options: opts
  },
  ingest: {
    command: [
      "cd glazier-server",
      "bundle exec rake 'glazier:ingest_as_current[../tmp/public/index.html]'"
    ].join(' && '),
    options: opts
  },
  ingestIndex: {
    command: herokuIngestIndexCommand,
    options: opts
  },
  npmRefreshForCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardNpmRefreshCommand).join(' && '),
    options: opts
  },
  npmInstallForCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardNpmInstallCommand).join(' && '),
    options: opts
  },
  buildCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardGruntCommand).join(' && '),
    options: opts
  },
  ingestCardManifests: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardIngestManigestCommand).join(' && '),
    options: opts
  },
  deployCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardGruntDeployCommand).join(' && '),
    options: opts
  },
  herokuIngestCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(herokuIngestCommand).join(' && '),
    options: opts
  }
};
<commit_msg>fix typo<commit_after>var fs = require('fs');
var grunt = require('grunt');
var opts = {
  stdout: true,
  stderr: true,
  failOnError: true
};

var isCardDir = function (dir){
  return dir[0] != ".";
};

function cardGruntCommand(cardName) {
  var cmd = "(cd cards/" + cardName + " && grunt)";
  return cmd;
}

function cardGruntDeployCommand(cardName) {
  var cmd = "(cd cards/" + cardName + " && grunt deploy)";
  return cmd;
}

function cardNpmInstallCommand(cardName) {
  var cmd = "(cd cards/" + cardName + " && npm install)";
  return cmd;
}

function cardNpmRefreshCommand(cardName) {
  var cmd = "rm -rf cards/*/node_modules";
  return cmd;
}

function cardIngestManifestCommand(cardName) {
  var manifestPath = 'cards/' + cardName + '/dist/dev/' + cardName + '/manifest.json';
  var cmd = '(cd glazier-server && bundle exec rake "glazier:card:ingest[../' + manifestPath + ']")';
  return cmd;
}

function herokuIngestCommand(cardName) {
  var deployJSON = grunt.file.readJSON('cards/' + cardName + '/package.json');
  var glazierConfig = deployJSON.glazierConfig;
  var url = glazierConfig.assetHost + '/assets/cards/' + glazierConfig.repositoryName + '/manifest.json';
  var cmd = "(cd glazier-server && heroku surrogate rails runner \"PaneType.ingest('" + url + "')\" --app glazier)";
  return cmd;
}

herokuIngestIndexCommand = "(cd glazier-server && heroku surrogate rake 'glazier:ingest_as_current[../tmp/public/index.html]' --app glazier)";

module.exports = {
  glazierServer: {
    command: [
      "cd glazier-server",
      "PORT=3040 foreman start"
    ].join(' && '),
    options: opts
  },
  ingest: {
    command: [
      "cd glazier-server",
      "bundle exec rake 'glazier:ingest_as_current[../tmp/public/index.html]'"
    ].join(' && '),
    options: opts
  },
  ingestIndex: {
    command: herokuIngestIndexCommand,
    options: opts
  },
  npmRefreshForCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardNpmRefreshCommand).join(' && '),
    options: opts
  },
  npmInstallForCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardNpmInstallCommand).join(' && '),
    options: opts
  },
  buildCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardGruntCommand).join(' && '),
    options: opts
  },
  ingestCardManifests: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardIngestManifestCommand).join(' && '),
    options: opts
  },
  deployCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(cardGruntDeployCommand).join(' && '),
    options: opts
  },
  herokuIngestCards: {
    command: fs.readdirSync('cards').filter(isCardDir).map(herokuIngestCommand).join(' && '),
    options: opts
  }
};
<|endoftext|>


<commit_before>export default {
  abc: 200,
  name: 'lu',
  age: 20
};
<commit_msg>add age<commit_after>export default {
  abc: 200,
  name: 'lu',
  age: 32
};
<|endoftext|>