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 = {}
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
- contextUpdatePermissions('commons')}>
commons
- contextUpdatePermissions('public')}>
public
- contextUpdatePermissions('private')}>
private
}
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
- contextFetchSiblings(contextNode)}>All
Alt+R
{contextSiblingsData && Object.keys(contextSiblingsData).map(key => {
return - contextFetchSiblings(contextNode, key)}>
{contextSiblingsData[key]}
})}
{contextFetchingSiblingsData && - loading...
}
}
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
{this.hide()}
{this.remove()}
{this.delete()}
{this.center()}
{this.popout()}
{showSpacer && }
{this.permission()}
{this.metacode()}
{this.siblings()}
}
}
export default ContextMenu