<commit_before>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'

import Helmet from 'react-helmet'

import SpacesShowHeader from './header'
import SpacesShowToolbar from './Toolbar/index'
import SpaceSidebar from './sidebar'
import ClosedSpaceSidebar from './closed_sidebar'
import Canvas from 'gComponents/spaces/canvas'

import {denormalizedSpaceSelector} from '../denormalized-space-selector'

import {allowEdits, forbidEdits} from 'gModules/canvas_state/actions'
import * as spaceActions from 'gModules/spaces/actions'
import * as copiedActions from 'gModules/copied/actions'
import {undo, redo} from 'gModules/checkpoints/actions'

import e from 'gEngine/engine'

import * as elev from 'server/elev/index'

import './style.css'

function mapStateToProps(state) {
  return {
    me: state.me
  }
}

const PT = PropTypes

@connect(mapStateToProps)
@connect(denormalizedSpaceSelector)
export default class SpacesShow extends Component {
  displayName: 'RepoDetailPage'

  static propTypes = {
    dispatch: PT.func.isRequired,
    spaceId: PT.number,
    denormalizedSpace: PT.object,
    embed: PT.bool
  }

  state = {
    showSidebar: true,
    attemptedFetch: false,
  }

  componentWillMount() {
    this.considerFetch(this.props)
    if (!this.props.embed) { elev.show() }

    if (_.has(this.props, 'denormalizedSpace.editableByMe')) {
      this.setDefaultEditPermission(_.get(this.props, 'denormalizedSpace.editableByMe'))
    }
  }

  setDefaultEditPermission(editableByMe) {
    if (!!editableByMe) {
      this.props.dispatch(allowEdits())
    } else {
      this.props.dispatch(forbidEdits())
    }
  }

  componentWillUnmount() {
    if (!this.props.embed) { elev.hide() }
  }

  componentWillReceiveProps(nextProps) {
    const nextEditableState = _.get(nextProps, 'denormalizedSpace.editableByMe')
    const currEditableState = _.get(this.props, 'denormalizedSpace.editableByMe')
    if (nextEditableState !== currEditableState) {
      this.setDefaultEditPermission(nextEditableState)
    }
  }

  componentDidUpdate(prevProps) {
    this.considerFetch(prevProps)
  }

  considerFetch(newProps) {
    const space = newProps.denormalizedSpace
    const needsData = !_.has(space, 'graph')

    if (needsData) {
      this.fetchData()
    }
  }

  fetchData() {
    if (!this.state.attemptedFetch) {
      this.props.dispatch(spaceActions.fetchById(this._id()))
      this.setState({attemptedFetch: true})
    }
  }

  onSave() {
    this.props.dispatch(spaceActions.update(this._id()))
  }

  onRedo() {
    this.props.dispatch(redo(this._id()))
  }

  onUndo() {
    this.props.dispatch(undo(this._id()))
  }

  destroy() {
    this.props.dispatch(spaceActions.destroy(this.props.denormalizedSpace))
  }

  onPublicSelect() {
    this.props.dispatch(spaceActions.generalUpdate(this._id(), {is_private: false}))
  }

  onPrivateSelect() {
    this.props.dispatch(spaceActions.generalUpdate(this._id(), {is_private: true}))
  }

  onSaveName(name) {
    this.props.dispatch(spaceActions.update(this._id(), {name}))
  }

  onSaveDescription(description) {
    this.props.dispatch(spaceActions.update(this._id(), {description}))
  }

  hideSidebar() {
    this.setState({showSidebar: false})
  }
  openSidebar() {
    this.setState({showSidebar: true})
  }

  _handleCopyModel() {
    this.props.dispatch(spaceActions.copy())
  }

  onCopy() {
    this.props.dispatch(copiedActions.copy(this._id()))
  }

  onPaste() {
    this.props.dispatch(copiedActions.paste(this._id()))
  }

  onCut() {
    this.props.dispatch(copiedActions.cut(this._id()))
  }

  _id() {
    return parseInt(this.props.spaceId)
  }

  render() {
    const space = this.props.denormalizedSpace;
    if (!space) { return <div className='spaceShow'></div> }

    const sidebarIsViseable = space.editableByMe || !_.isEmpty(space.description)
    const canBePrivate = !!space.organization_id || e.me.canMakeMorePrivateModels(this.props.me)
    const isLoggedIn = e.me.isLoggedIn(this.props.me)
    if (this.props.embed) {
      return (
        <div className='spaceShow screenshot'>
          <Canvas spaceId={space.id} overflow={'hidden'} screenshot={true}/>
        </div>
      )
    }

    let tagDescription = space.description
    if (_.has(space, 'user.name') || _.has(space, 'organization.name')) {
      const author = _.has(space, 'organization.name') ? space.organization.name : space.user.name
      const authorCallout = `Made by ${author}`
      if (_.isEmpty(space.description)) {
        tagDescription = authorCallout
      } else {
        tagDescription = `${authorCallout}: ${tagDescription}`
      }
    }

    return (
      <div className='spaceShow'>
        {!space.name &&
          <Helmet
            meta={[
              {name: "Description", content: tagDescription},
              {property: "og:description", content: tagDescription},
              {property: "og:site_name", content: "Guesstimate"},
              {property: "og:image", content: space.big_screenshot},
            ]}
          />
        }
        {space.name &&
          <Helmet
            title={space.name}
            meta={[
              {name: "Description", content: tagDescription},
              {property: "og:title", content: space.name},
              {property: "og:description", content: tagDescription},
              {property: "og:site_name", content: "Guesstimate"},
              {property: "og:image", content: space.big_screenshot},
            ]}
          />
        }

        <div className='hero-unit'>
          <SpacesShowHeader
            isLoggedIn={isLoggedIn}
            onSaveName={this.onSaveName.bind(this)}
            name={space.name}
            isPrivate={space.is_private}
            editableByMe={space.editableByMe}
            actionState={space.canvasState.actionState}
            canBePrivate={canBePrivate}
            onPublicSelect={this.onPublicSelect.bind(this)}
            onPrivateSelect={this.onPrivateSelect.bind(this)}
            onPrivateSelecundot={this.onPrivateSelect.bind(this)}
            space={space}
          />

          <SpacesShowToolbar
            editsAllowed={space.canvasState.editsAllowed}
            onAllowEdits={() => {this.props.dispatch(allowEdits())}}
            onForbidEdits={() => {this.props.dispatch(forbidEdits())}}
            isLoggedIn={isLoggedIn}
            onDestroy={this.destroy.bind(this)}
            onCopyModel={this._handleCopyModel.bind(this)}
            onCopyMetrics={this.onCopy.bind(this)}
            onPasteMetrics={this.onPaste.bind(this)}
            onCutMetrics={this.onCut.bind(this)}
            isPrivate={space.is_private}
            editableByMe={space.editableByMe}
            actionState={space.canvasState.actionState}
            onUndo={this.onUndo.bind(this)}
            onRedo={this.onRedo.bind(this)}
            canUndo={space.checkpointMetadata.head !== space.checkpointMetadata.length - 1}
            canRedo={space.checkpointMetadata.head !== 0}
          />
        </div>

        <div className='content'>
          {sidebarIsViseable && this.state.showSidebar &&
            <SpaceSidebar
                description={space.description}
                canEdit={space.editableByMe}
                onClose={this.hideSidebar.bind(this)}
                onSaveDescription={this.onSaveDescription.bind(this)}
            />
          }
          {sidebarIsViseable && !this.state.showSidebar &&
            <ClosedSpaceSidebar onOpen={this.openSidebar.bind(this)}/>
          }
          <Canvas
            spaceId={space.id}
            onCopy={this.onCopy.bind(this)}
            onPaste={this.onPaste.bind(this)}
            onCut={this.onCut.bind(this)}
          />
        </div>
      </div>
    )
  }
}
<commit_msg>When you make a new space, the 'editableByMe prop doesn't necessarily change, just the id does, (but we need the editableByMe prop check for when you load a space fresh, as there is no update where the id changes).<commit_after>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'

import Helmet from 'react-helmet'

import SpacesShowHeader from './header'
import SpacesShowToolbar from './Toolbar/index'
import SpaceSidebar from './sidebar'
import ClosedSpaceSidebar from './closed_sidebar'
import Canvas from 'gComponents/spaces/canvas'

import {denormalizedSpaceSelector} from '../denormalized-space-selector'

import {allowEdits, forbidEdits} from 'gModules/canvas_state/actions'
import * as spaceActions from 'gModules/spaces/actions'
import * as copiedActions from 'gModules/copied/actions'
import {undo, redo} from 'gModules/checkpoints/actions'

import e from 'gEngine/engine'

import * as elev from 'server/elev/index'

import './style.css'

function mapStateToProps(state) {
  return {
    me: state.me
  }
}

const PT = PropTypes

@connect(mapStateToProps)
@connect(denormalizedSpaceSelector)
export default class SpacesShow extends Component {
  displayName: 'RepoDetailPage'

  static propTypes = {
    dispatch: PT.func.isRequired,
    spaceId: PT.number,
    denormalizedSpace: PT.object,
    embed: PT.bool
  }

  state = {
    showSidebar: true,
    attemptedFetch: false,
  }

  componentWillMount() {
    this.considerFetch(this.props)
    if (!this.props.embed) { elev.show() }

    if (_.has(this.props, 'denormalizedSpace.editableByMe')) {
      this.setDefaultEditPermission(_.get(this.props, 'denormalizedSpace.editableByMe'))
    }
  }

  setDefaultEditPermission(editableByMe) {
    if (!!editableByMe) {
      this.props.dispatch(allowEdits())
    } else {
      this.props.dispatch(forbidEdits())
    }
  }

  componentWillUnmount() {
    if (!this.props.embed) { elev.hide() }
  }

  componentWillReceiveProps(nextProps) {
    const nextEditableState = _.get(nextProps, 'denormalizedSpace.editableByMe')
    const currEditableState = _.get(this.props, 'denormalizedSpace.editableByMe')
    const nextId = _.get(nextProps, 'spaceId')
    const currId = _.get(this.props, 'spaceId')
    if (nextId !== currId || nextEditableState !== currEditableState) {
      this.setDefaultEditPermission(nextEditableState)
    }
  }

  componentDidUpdate(prevProps) {
    this.considerFetch(prevProps)
  }

  considerFetch(newProps) {
    const space = newProps.denormalizedSpace
    const needsData = !_.has(space, 'graph')

    if (needsData) {
      this.fetchData()
    }
  }

  fetchData() {
    if (!this.state.attemptedFetch) {
      this.props.dispatch(spaceActions.fetchById(this._id()))
      this.setState({attemptedFetch: true})
    }
  }

  onSave() {
    this.props.dispatch(spaceActions.update(this._id()))
  }

  onRedo() {
    this.props.dispatch(redo(this._id()))
  }

  onUndo() {
    this.props.dispatch(undo(this._id()))
  }

  destroy() {
    this.props.dispatch(spaceActions.destroy(this.props.denormalizedSpace))
  }

  onPublicSelect() {
    this.props.dispatch(spaceActions.generalUpdate(this._id(), {is_private: false}))
  }

  onPrivateSelect() {
    this.props.dispatch(spaceActions.generalUpdate(this._id(), {is_private: true}))
  }

  onSaveName(name) {
    this.props.dispatch(spaceActions.update(this._id(), {name}))
  }

  onSaveDescription(description) {
    this.props.dispatch(spaceActions.update(this._id(), {description}))
  }

  hideSidebar() {
    this.setState({showSidebar: false})
  }
  openSidebar() {
    this.setState({showSidebar: true})
  }

  _handleCopyModel() {
    this.props.dispatch(spaceActions.copy())
  }

  onCopy() {
    this.props.dispatch(copiedActions.copy(this._id()))
  }

  onPaste() {
    this.props.dispatch(copiedActions.paste(this._id()))
  }

  onCut() {
    this.props.dispatch(copiedActions.cut(this._id()))
  }

  _id() {
    return parseInt(this.props.spaceId)
  }

  render() {
    const space = this.props.denormalizedSpace;
    if (!space) { return <div className='spaceShow'></div> }

    const sidebarIsViseable = space.editableByMe || !_.isEmpty(space.description)
    const canBePrivate = !!space.organization_id || e.me.canMakeMorePrivateModels(this.props.me)
    const isLoggedIn = e.me.isLoggedIn(this.props.me)
    if (this.props.embed) {
      return (
        <div className='spaceShow screenshot'>
          <Canvas spaceId={space.id} overflow={'hidden'} screenshot={true}/>
        </div>
      )
    }

    let tagDescription = space.description
    if (_.has(space, 'user.name') || _.has(space, 'organization.name')) {
      const author = _.has(space, 'organization.name') ? space.organization.name : space.user.name
      const authorCallout = `Made by ${author}`
      if (_.isEmpty(space.description)) {
        tagDescription = authorCallout
      } else {
        tagDescription = `${authorCallout}: ${tagDescription}`
      }
    }

    return (
      <div className='spaceShow'>
        {!space.name &&
          <Helmet
            meta={[
              {name: "Description", content: tagDescription},
              {property: "og:description", content: tagDescription},
              {property: "og:site_name", content: "Guesstimate"},
              {property: "og:image", content: space.big_screenshot},
            ]}
          />
        }
        {space.name &&
          <Helmet
            title={space.name}
            meta={[
              {name: "Description", content: tagDescription},
              {property: "og:title", content: space.name},
              {property: "og:description", content: tagDescription},
              {property: "og:site_name", content: "Guesstimate"},
              {property: "og:image", content: space.big_screenshot},
            ]}
          />
        }

        <div className='hero-unit'>
          <SpacesShowHeader
            isLoggedIn={isLoggedIn}
            onSaveName={this.onSaveName.bind(this)}
            name={space.name}
            isPrivate={space.is_private}
            editableByMe={space.editableByMe}
            actionState={space.canvasState.actionState}
            canBePrivate={canBePrivate}
            onPublicSelect={this.onPublicSelect.bind(this)}
            onPrivateSelect={this.onPrivateSelect.bind(this)}
            onPrivateSelecundot={this.onPrivateSelect.bind(this)}
            space={space}
          />

          <SpacesShowToolbar
            editsAllowed={space.canvasState.editsAllowed}
            onAllowEdits={() => {this.props.dispatch(allowEdits())}}
            onForbidEdits={() => {this.props.dispatch(forbidEdits())}}
            isLoggedIn={isLoggedIn}
            onDestroy={this.destroy.bind(this)}
            onCopyModel={this._handleCopyModel.bind(this)}
            onCopyMetrics={this.onCopy.bind(this)}
            onPasteMetrics={this.onPaste.bind(this)}
            onCutMetrics={this.onCut.bind(this)}
            isPrivate={space.is_private}
            editableByMe={space.editableByMe}
            actionState={space.canvasState.actionState}
            onUndo={this.onUndo.bind(this)}
            onRedo={this.onRedo.bind(this)}
            canUndo={space.checkpointMetadata.head !== space.checkpointMetadata.length - 1}
            canRedo={space.checkpointMetadata.head !== 0}
          />
        </div>

        <div className='content'>
          {sidebarIsViseable && this.state.showSidebar &&
            <SpaceSidebar
                description={space.description}
                canEdit={space.editableByMe}
                onClose={this.hideSidebar.bind(this)}
                onSaveDescription={this.onSaveDescription.bind(this)}
            />
          }
          {sidebarIsViseable && !this.state.showSidebar &&
            <ClosedSpaceSidebar onOpen={this.openSidebar.bind(this)}/>
          }
          <Canvas
            spaceId={space.id}
            onCopy={this.onCopy.bind(this)}
            onPaste={this.onPaste.bind(this)}
            onCut={this.onCut.bind(this)}
          />
        </div>
      </div>
    )
  }
}

{'fraction_non_alphanumeric': 0.13270887030866915, 'fraction_numerical': 0.00025146162067014524, 'mean_word_length': 2.7563164108618654, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2997604', 'n_tokens_mistral': 4909, 'n_tokens_neox': 4841, 'n_words': 756}