import React, { Component } from 'react' import PropTypes from 'prop-types' import MetacodeSelect from '../MetacodeSelect' class ContextMenu extends Component { static propTypes = { topicId: PropTypes.string, mapId: PropTypes.string, currentUser: PropTypes.object, map: PropTypes.object, contextNode: PropTypes.object, contextEdge: PropTypes.object, contextPos: PropTypes.object, contextFetchingSiblingsData: PropTypes.bool, contextSiblingsData: PropTypes.object, metacodeSets: PropTypes.array, contextDelete: PropTypes.func, contextRemove: PropTypes.func, contextHide: PropTypes.func, contextCenterOn: PropTypes.func, contextPopoutTopic: PropTypes.func, contextUpdatePermissions: PropTypes.func, contextOnMetacodeSelect: PropTypes.func, contextFetchSiblings: PropTypes.func, contextPopulateSiblings: PropTypes.func } constructor(props) { super(props) this.state = { populateSiblingsSent: false } } getPositionData = () => { const { contextPos } = this.props let extraClasses = [] const position = {} // TODO: make these dynamic values so that the ContextMenu can // change height and still work properly const RIGHTCLICK_WIDTH = 300 const RIGHTCLICK_HEIGHT = 144 // this does vary somewhat, but we can use static const SUBMENUS_WIDTH = 256 const MAX_SUBMENU_HEIGHT = 270 const windowWidth = document.documentElement.clientWidth const windowHeight = document.documentElement.clientHeight if (windowWidth - contextPos.x < SUBMENUS_WIDTH) { position.right = windowWidth - contextPos.x extraClasses.push('moveMenusToLeft') } else if (windowWidth - contextPos.x < RIGHTCLICK_WIDTH) { position.right = windowWidth - contextPos.x } else if (windowWidth - contextPos.x < RIGHTCLICK_WIDTH + SUBMENUS_WIDTH) { position.left = contextPos.x extraClasses.push('moveMenusToLeft') } else { position.left = contextPos.x } if (windowHeight - contextPos.y < MAX_SUBMENU_HEIGHT) { position.bottom = windowHeight - contextPos.y extraClasses.push('moveMenusUp') } else if (windowHeight - contextPos.y < RIGHTCLICK_HEIGHT + MAX_SUBMENU_HEIGHT) { position.top = contextPos.y extraClasses.push('moveMenusUp') } else { position.top = contextPos.y } return { pos: { top: position.top && position.top + 'px', bottom: position.bottom && position.bottom + 'px', left: position.left && position.left + 'px', right: position.right && position.right + 'px' }, extraClasses } } hide = () => { const { contextHide } = this.props return
  • Hide until refresh
    Ctrl+H
  • } remove = () => { const { contextRemove, map, currentUser } = this.props const canEditMap = map && map.authorizeToEdit(currentUser) if (!canEditMap) { return null } return
  • Remove from map
    Ctrl+M
  • } delete = () => { const { contextDelete, map, currentUser } = this.props const canEditMap = map && map.authorizeToEdit(currentUser) if (!canEditMap) { return null } return
  • Delete
    Ctrl+D
  • } center = () => { const { contextCenterOn, contextNode, topicId } = this.props if (!(contextNode && topicId)) { return null } return
  • contextCenterOn(contextNode.id)}>
    Center this topic
    Alt+E
  • } popout = () => { const { contextPopoutTopic, contextNode } = this.props if (!contextNode) { return null } return
  • contextPopoutTopic(contextNode.id)}>
    Open in new tab
  • } permission = () => { const { currentUser, contextUpdatePermissions } = this.props if (!currentUser) { return null } return
  • Change permissions
  • } metacode = () => { const { metacodeSets, contextOnMetacodeSelect, currentUser, contextNode } = this.props if (!currentUser) { return null } return
  • Change metacode
    { contextOnMetacodeSelect(contextNode && contextNode.id, id) }} metacodeSets={metacodeSets} />
  • } siblings = () => { const { contextPopulateSiblings, contextFetchSiblings, contextSiblingsData, contextFetchingSiblingsData, topicId, contextNode } = this.props const populateSiblings = () => { if (!this.state.populateSiblingsSent) { contextPopulateSiblings(contextNode.id) this.setState({populateSiblingsSent: true}) } } if (!(contextNode && topicId)) { return null } return
  • Reveal siblings
  • } render() { const { contextNode, currentUser, topicId } = this.props const positionData = this.getPositionData() const style = Object.assign({}, {position: 'absolute'}, positionData.pos) const showSpacer = currentUser || (contextNode && topicId) return
    } } export default ContextMenu