<commit_before>import React, {Component, PropTypes} from 'react'
import Helmet from 'react-helmet'
import moment from 'moment'
import { Tabs, Tab, Grid, Row, Label, Col, Button, InputGroup, Table, FormControl, Glyphicon, ButtonToolbar, Panel, DropdownButton, MenuItem } from 'react-bootstrap'
import { sentence as toSentenceCase } from 'change-case'
import Icon from 'react-fa'
import { browserHistory, Link } from 'react-router'
import { shallowEqual } from 'react-pure-render'

import ManagerPage from '../../common/components/ManagerPage'
import Breadcrumbs from '../../common/components/Breadcrumbs'
import WatchButton from '../../common/containers/WatchButton'
import ProjectSettings from './ProjectSettings'
import FeedSourceTable from './FeedSourceTable'
import EditableTextField from '../../common/components/EditableTextField'
import { defaultSorter } from '../../common/util/util'
import { isModuleEnabled, isExtensionEnabled, getComponentMessages, getMessage, getConfigProperty } from '../../common/util/config'

export default class ProjectViewer extends Component {
  static propTypes = {
    project: PropTypes.object,
    onComponentMount: PropTypes.func,

    visibilityFilter: PropTypes.object,
    visibilityFilterChanged: PropTypes.func,
    searchTextChanged: PropTypes.func,
  }
  constructor (props) {
    super(props)

    this.state = {}
  }

  deleteFeedSource (feedSource) {
    this.refs['page'].showConfirmModal({
      title: 'Delete Feed Source?',
      body: `Are you sure you want to delete the feed source ${feedSource.name}?`,
      onConfirm: () => {
        console.log('OK, deleting')
        this.props.deleteFeedSourceConfirmed(feedSource)
      }
    })
  }

  showUploadFeedModal (feedSource) {
    this.refs.page.showSelectFileModal({
      title: 'Upload Feed',
      body: 'Select a GTFS feed to upload:',
      onConfirm: (files) => {
        let nameArray = files[0].name.split('.')
        if (files[0].type !== 'application/zip' || nameArray[nameArray.length - 1] !== 'zip') {
          return false
        }
        else {
          this.props.uploadFeedClicked(feedSource, files[0])
          return true
        }
      },
      errorMessage: 'Uploaded file must be a valid zip file (.zip).'
    })
  }

  componentWillMount () {
    this.props.onComponentMount(this.props)
  }
  render () {
    if(!this.props.project) {
      return <ManagerPage />
    }
    const messages = getComponentMessages('ProjectViewer')
    const isWatchingProject = this.props.user.subscriptions.hasProjectSubscription(this.props.project.id, 'project-updated')
    const projectEditDisabled = !this.props.user.permissions.isProjectAdmin(this.props.project.id)
    const filteredFeedSources = this.props.project.feedSources
      ? this.props.project.feedSources.filter(feedSource => {
          if(feedSource.isCreating) return true // feeds actively being created are always visible
          let visible = feedSource.name !== null ? feedSource.name.toLowerCase().indexOf((this.props.visibilityFilter.searchText || '').toLowerCase()) !== -1 : '[unnamed project]'
          switch (this.props.visibilityFilter.filter) {
            case 'ALL':
              return visible
            case 'STARRED':
              return [].indexOf(feedSource.id) !== -1 // check userMetaData
            case 'PUBLIC':
              return feedSource.isPublic
            case 'PRIVATE':
              return !feedSource.isPublic
            default:
              return visible
          }
        }).sort(defaultSorter)
      : []
    const projectsHeader = (
      <Row>
        <Col xs={4}>
          <InputGroup>
            <DropdownButton
              componentClass={InputGroup.Button}
              id='input-dropdown-addon'
              title={this.props.visibilityFilter.filter ? toSentenceCase(this.props.visibilityFilter.filter) : 'Filter'}
              onSelect={(key) => {
                this.props.visibilityFilterChanged(key)
              }}
            >
              <MenuItem eventKey='ALL'>All</MenuItem>
              <MenuItem eventKey='STARRED'>Starred</MenuItem>
              <MenuItem eventKey='PUBLIC'>Public</MenuItem>
              <MenuItem eventKey='PRIVATE'>Private</MenuItem>
            </DropdownButton>
            <FormControl
              placeholder={getMessage(messages, 'feeds.search')}
              onChange={evt => this.props.searchTextChanged(evt.target.value)}
            />
          </InputGroup>
        </Col>
        <Col xs={8}>
          <Button
            bsStyle='primary'
            disabled={projectEditDisabled}
            className='pull-right'
            onClick={() => this.props.onNewFeedSourceClick()}
          >
            <Glyphicon glyph='plus' /> {getMessage(messages, 'feeds.new')}
          </Button>
          <ButtonToolbar>
          {isExtensionEnabled('transitland') || isExtensionEnabled('transitfeeds') || isExtensionEnabled('mtc')
            ? <DropdownButton bsStyle='success' title={<span><Icon name='refresh'/> Sync</span>}>
                {isExtensionEnabled('transitland')
                  ? <MenuItem
                      bsStyle='primary'
                      disabled={projectEditDisabled}
                      id='TRANSITLAND'
                      onClick={(evt) => {
                        this.props.thirdPartySync('TRANSITLAND')
                      }}
                    >
                      <Glyphicon glyph='refresh' /> transit.land
                    </MenuItem>
                  : null
                }
                {isExtensionEnabled('transitfeeds')
                  ? <MenuItem
                      bsStyle='primary'
                      disabled={projectEditDisabled}
                      id='TRANSITFEEDS'
                      onClick={(evt) => {
                        this.props.thirdPartySync('TRANSITFEEDS')
                      }}
                    >
                      <Glyphicon glyph='refresh' /> transitfeeds.com
                    </MenuItem>
                  : null
                }
                {isExtensionEnabled('mtc')
                  ? <MenuItem
                      bsStyle='primary'
                      disabled={projectEditDisabled}
                      id='MTC'
                      onClick={(evt) => {
                        this.props.thirdPartySync('MTC')
                      }}
                    >
                      <Glyphicon glyph='refresh' /> MTC
                    </MenuItem>
                  : null
                }
              </DropdownButton>
            : null
          }
            <Button
              bsStyle='default'
              disabled={projectEditDisabled}
              onClick={() => {
                console.log(this.props.project)
                this.props.updateAllFeeds(this.props.project)
              }}
            >
              <Icon name='cloud-download' /> {getMessage(messages, 'feeds.update')}
            </Button>
            <Button
              bsStyle='primary'
              onClick={() => { this.props.downloadMergedFeed(this.props.project) }}
            >
              <Glyphicon glyph='download'/> {getMessage(messages, 'mergeFeeds')}
            </Button>
          </ButtonToolbar>
        </Col>
      </Row>
    )
    return (
      <ManagerPage ref='page'
        breadcrumbs={
          <Breadcrumbs
            project={this.props.project}
          />
        }
      ><commit_msg>clean up code, shouldComponentUpdate check for feedsource changes<commit_after>import React, {Component, PropTypes} from 'react'
import Helmet from 'react-helmet'
import moment from 'moment'
import { Tabs, Tab, Grid, Row, Label, Col, Button, InputGroup, Table, FormControl, Glyphicon, ButtonToolbar, Panel, DropdownButton, MenuItem } from 'react-bootstrap'
import { sentence as toSentenceCase } from 'change-case'
import Icon from 'react-fa'
import { browserHistory, Link } from 'react-router'
import { shallowEqual } from 'react-pure-render'

import ManagerPage from '../../common/components/ManagerPage'
import Breadcrumbs from '../../common/components/Breadcrumbs'
import WatchButton from '../../common/containers/WatchButton'
import ProjectSettings from './ProjectSettings'
import FeedSourceTable from './FeedSourceTable'
import EditableTextField from '../../common/components/EditableTextField'
import { defaultSorter } from '../../common/util/util'
import { isModuleEnabled, isExtensionEnabled, getComponentMessages, getMessage, getConfigProperty } from '../../common/util/config'

export default class ProjectViewer extends Component {
  static propTypes = {
    project: PropTypes.object,
    onComponentMount: PropTypes.func,

    visibilityFilter: PropTypes.object,
    visibilityFilterChanged: PropTypes.func,
    searchTextChanged: PropTypes.func,
  }
  constructor (props) {
    super(props)

    this.state = {}
  }

  deleteFeedSource (feedSource) {
    this.refs['page'].showConfirmModal({
      title: 'Delete Feed Source?',
      body: `Are you sure you want to delete the feed source ${feedSource.name}?`,
      onConfirm: () => {
        console.log('OK, deleting')
        this.props.deleteFeedSourceConfirmed(feedSource)
      }
    })
  }

  showUploadFeedModal (feedSource) {
    this.refs.page.showSelectFileModal({
      title: 'Upload Feed',
      body: 'Select a GTFS feed to upload:',
      onConfirm: (files) => {
        let nameArray = files[0].name.split('.')
        if (files[0].type !== 'application/zip' || nameArray[nameArray.length - 1] !== 'zip') {
          return false
        }
        else {
          this.props.uploadFeedClicked(feedSource, files[0])
          return true
        }
      },
      errorMessage: 'Uploaded file must be a valid zip file (.zip).'
    })
  }
  shouldComponentUpdate (newProps) {
    if (!shallowEqual(newProps, this.props)) {
      return true
    } else {
      return false
    }
  }
  componentWillMount () {
    this.props.onComponentMount(this.props)
  }
  render () {
    if(!this.props.project) {
      return <ManagerPage />
    }
    const messages = getComponentMessages('ProjectViewer')
    const isWatchingProject = this.props.user.subscriptions.hasProjectSubscription(this.props.project.id, 'project-updated')
    const projectEditDisabled = !this.props.user.permissions.isProjectAdmin(this.props.project.id)
    const filteredFeedSources = this.props.project.feedSources
      ? this.props.project.feedSources.filter(feedSource => {
          if(feedSource.isCreating) return true // feeds actively being created are always visible
          let visible = feedSource.name !== null ? feedSource.name.toLowerCase().indexOf((this.props.visibilityFilter.searchText || '').toLowerCase()) !== -1 : '[unnamed project]'
          switch (this.props.visibilityFilter.filter) {
            case 'ALL':
              return visible
            case 'STARRED':
              return [].indexOf(feedSource.id) !== -1 // check userMetaData
            case 'PUBLIC':
              return feedSource.isPublic
            case 'PRIVATE':
              return !feedSource.isPublic
            default:
              return visible
          }
        }).sort(defaultSorter)
      : []
    const projectsHeader = (
      <Row>
        <Col xs={4}>
          <InputGroup>
            <DropdownButton
              componentClass={InputGroup.Button}
              id='input-dropdown-addon'
              title={this.props.visibilityFilter.filter ? toSentenceCase(this.props.visibilityFilter.filter) : 'Filter'}
              onSelect={(key) => {
                this.props.visibilityFilterChanged(key)
              }}
            >
              <MenuItem eventKey='ALL'>All</MenuItem>
              <MenuItem eventKey='STARRED'>Starred</MenuItem>
              <MenuItem eventKey='PUBLIC'>Public</MenuItem>
              <MenuItem eventKey='PRIVATE'>Private</MenuItem>
            </DropdownButton>
            <FormControl
              placeholder={getMessage(messages, 'feeds.search')}
              onChange={evt => this.props.searchTextChanged(evt.target.value)}
            />
          </InputGroup>
        </Col>
        <Col xs={8}>
          <Button
            bsStyle='primary'
            disabled={projectEditDisabled}
            className='pull-right'
            onClick={() => this.props.onNewFeedSourceClick()}
          >
            <Glyphicon glyph='plus' /> {getMessage(messages, 'feeds.new')}
          </Button>
          <ButtonToolbar>
          {isExtensionEnabled('transitland') || isExtensionEnabled('transitfeeds') || isExtensionEnabled('mtc')
            ? <DropdownButton id='sync-dropdown' bsStyle='success' title={<span><Icon name='refresh'/> Sync</span>}>
                {isExtensionEnabled('transitland')
                  ? <MenuItem
                      bsStyle='primary'
                      disabled={projectEditDisabled}
                      id='TRANSITLAND'
                      onClick={(evt) => {
                        this.props.thirdPartySync('TRANSITLAND')
                      }}
                    >
                      <Glyphicon glyph='refresh' /> transit.land
                    </MenuItem>
                  : null
                }
                {isExtensionEnabled('transitfeeds')
                  ? <MenuItem
                      bsStyle='primary'
                      disabled={projectEditDisabled}
                      id='TRANSITFEEDS'
                      onClick={(evt) => {
                        this.props.thirdPartySync('TRANSITFEEDS')
                      }}
                    >
                      <Glyphicon glyph='refresh' /> transitfeeds.com
                    </MenuItem>
                  : null
                }
                {isExtensionEnabled('mtc')
                  ? <MenuItem
                      bsStyle='primary'
                      disabled={projectEditDisabled}
                      id='MTC'
                      onClick={(evt) => {
                        this.props.thirdPartySync('MTC')
                      }}
                    >
                      <Glyphicon glyph='refresh' /> MTC
                    </MenuItem>
                  : null
                }
              </DropdownButton>
            : null
          }
            <Button
              bsStyle='default'
              disabled={projectEditDisabled}
              onClick={() => {
                this.props.updateAllFeeds(this.props.project)
              }}
            >
              <Icon name='cloud-download' /> {getMessage(messages, 'feeds.update')}
            </Button>
            <Button
              bsStyle='primary'
              onClick={() => { this.props.downloadMergedFeed(this.props.project) }}
            >
              <Glyphicon glyph='download'/> {getMessage(messages, 'mergeFeeds')}
            </Button>
          </ButtonToolbar>
        </Col>
      </Row>
    )
    return (
      <ManagerPage ref='page'
        breadcrumbs={
          <Breadcrumbs
            project={this.props.project}
          />
        }
      >
{'fraction_non_alphanumeric': 0.11651193633952255, 'fraction_numerical': 0.0010610079575596816, 'mean_word_length': 1.8104733507267983, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '249902', 'n_tokens_mistral': 3891, 'n_tokens_neox': 3819, 'n_words': 729}