From 6e1878413f9384444ef4d1138fd96b716e4df5b3 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Tue, 12 Sep 2017 15:17:15 -0400 Subject: [PATCH] wip right click in react --- frontend/src/Metamaps/GlobalUI/ReactApp.js | 2 +- frontend/src/Metamaps/JIT.js | 216 +----------------- frontend/src/Metamaps/Views/ContextMenu.js | 113 +++++++++ frontend/src/Metamaps/Views/index.js | 4 +- frontend/src/components/common/ContextMenu.js | 77 +++++++ 5 files changed, 196 insertions(+), 216 deletions(-) create mode 100644 frontend/src/Metamaps/Views/ContextMenu.js create mode 100644 frontend/src/components/common/ContextMenu.js diff --git a/frontend/src/Metamaps/GlobalUI/ReactApp.js b/frontend/src/Metamaps/GlobalUI/ReactApp.js index db850091..3393a951 100644 --- a/frontend/src/Metamaps/GlobalUI/ReactApp.js +++ b/frontend/src/Metamaps/GlobalUI/ReactApp.js @@ -9,7 +9,7 @@ import { notifyUser } from './index.js' import ImportDialog from './ImportDialog' import Active from '../Active' import DataModel from '../DataModel' -import { ExploreMaps, ChatView, TopicCard } from '../Views' +import { ExploreMaps, ChatView, TopicCard, ContextMenu } from '../Views' import Filter from '../Filter' import JIT from '../JIT' import Realtime from '../Realtime' diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index ffaab923..7116854f 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -11,6 +11,7 @@ import $jit from '../patched/JIT' import MetacodeSelect from '../components/MetacodeSelect' import Active from './Active' +import ContextMenu from './Views/ContextMenu' import Control from './Control' import Create from './Create' import DataModel from './DataModel' @@ -1354,222 +1355,9 @@ const JIT = { // select the node Control.selectNode(node, e) + ContextMenu.selectNode(node, {x: e.clientX, y: e.clientY}) - // delete old right click menu - $('.rightclickmenu').remove() - // create new menu for clicked on node - const rightclickmenu = document.createElement('div') - rightclickmenu.className = 'rightclickmenu' - // prevent the custom context menu from immediately opening the default context menu as well - rightclickmenu.setAttribute('oncontextmenu', 'return false') - - // add the proper options to the menu - let menustring = '' - rightclickmenu.innerHTML = menustring - - // position the menu where the click happened - 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 = $(window).width() - const windowHeight = $(window).height() - - if (windowWidth - e.clientX < SUBMENUS_WIDTH) { - position.right = windowWidth - e.clientX - $(rightclickmenu).addClass('moveMenusToLeft') - } else if (windowWidth - e.clientX < RIGHTCLICK_WIDTH) { - position.right = windowWidth - e.clientX - } else if (windowWidth - e.clientX < RIGHTCLICK_WIDTH + SUBMENUS_WIDTH) { - position.left = e.clientX - $(rightclickmenu).addClass('moveMenusToLeft') - } else { - position.left = e.clientX - } - - if (windowHeight - e.clientY < MAX_SUBMENU_HEIGHT) { - position.bottom = windowHeight - e.clientY - $(rightclickmenu).addClass('moveMenusUp') - } else if (windowHeight - e.clientY < RIGHTCLICK_HEIGHT + MAX_SUBMENU_HEIGHT) { - position.top = e.clientY - $(rightclickmenu).addClass('moveMenusUp') - } else { - position.top = e.clientY - } - - $(rightclickmenu).css(position) - // add the menu to the page - $('#wrapper').append(rightclickmenu) - - ReactDOM.render( - React.createElement(MetacodeSelect, { - onMetacodeSelect: metacodeId => { - if (Selected.Nodes.length > 1) { - // batch update multiple topics - Control.updateSelectedMetacodes(metacodeId) - } else { - const topic = DataModel.Topics.get(node.id) - topic.save({ - metacode_id: metacodeId - }) - } - $(rightclickmenu).remove() - }, - metacodeSets: ReactApp.metacodeSets - }), - document.getElementById('metacodeOptionsWrapper') - ) - - // attach events to clicks on the list items - - // delete the selected things from the database - if (authorized) { - $('.rc-delete').click(function() { - $('.rightclickmenu').remove() - Control.deleteSelected() - }) - } - - // remove the selected things from the map - if (Active.Topic || authorized) { - $('.rc-remove').click(function() { - $('.rightclickmenu').remove() - Control.removeSelectedEdges() - Control.removeSelectedNodes() - }) - } - - // hide selected nodes and synapses until refresh - $('.rc-hide').click(function() { - $('.rightclickmenu').remove() - Control.hideSelectedEdges() - Control.hideSelectedNodes() - }) - - // when in radial, center on the topic you picked - $('.rc-center').click(function() { - $('.rightclickmenu').remove() - Topic.centerOn(node.id) - }) - - // open the entity in a new tab - $('.rc-popout').click(function() { - $('.rightclickmenu').remove() - const win = window.open('/topics/' + node.id, '_blank') - win.focus() - }) - - // change the permission of all the selected nodes and synapses that you were the originator of - $('.rc-permission li').click(function() { - $('.rightclickmenu').remove() - // $(this).text() will be 'commons' 'public' or 'private' - Control.updateSelectedPermissions($(this).text()) - }) - - // fetch relatives - let fetchSent = false - $('.rc-siblings').hover(function() { - if (!fetchSent) { - JIT.populateRightClickSiblings(node) - fetchSent = true - } - }) - $('.rc-siblings .fetchAll').click(function() { - $('.rightclickmenu').remove() - // data-id is a metacode id - Topic.fetchRelatives(node) - }) }, // selectNodeOnRightClickHandler, - populateRightClickSiblings: function(node) { - // depending on how many topics are selected, do different things - const topic = node.getData('topic') - - // add a loading icon for now - const loader = new CanvasLoader('loadingSiblings') - loader.setColor('#4FC059') // default is '#000000' - loader.setDiameter(15) // default is 40 - loader.setDensity(41) // default is 40 - loader.setRange(0.9) // default is 1.3 - loader.show() // Hidden by default - - const topics = DataModel.Topics.map(function(t) { return t.id }) - const topicsString = topics.join() - - const successCallback = function(data) { - $('#loadingSiblings').remove() - - for (var key in data) { - const string = `${DataModel.Metacodes.get(key).get('name')} (${data[key]})` - $('#fetchSiblingList').append(`
  • ${string}
  • `) - } - - $('.rc-siblings .getSiblings').click(function() { - $('.rightclickmenu').remove() - // data-id is a metacode id - Topic.fetchRelatives(node, $(this).attr('data-id')) - }) - } - - $.ajax({ - type: 'GET', - url: '/topics/' + topic.id + '/relative_numbers.json?network=' + topicsString, - success: successCallback, - error: function() {} - }) - }, selectEdgeOnClickHandler: function(adj, e) { if (Visualize.mGraph.busy) return diff --git a/frontend/src/Metamaps/Views/ContextMenu.js b/frontend/src/Metamaps/Views/ContextMenu.js new file mode 100644 index 00000000..be799b4b --- /dev/null +++ b/frontend/src/Metamaps/Views/ContextMenu.js @@ -0,0 +1,113 @@ +import Control from '../Control' +import DataModel from '../DataModel' +import ReactApp from '../GlobalUI/ReactApp' +import Selected from '../Selected' +import Topic from '../Topic' + +const ContextMenu = { + clickedNode: null, + clickedEdge: null, + pos: {x: 0, y: 0}, + siblingsData: null, + selectNode: (node, pos) => { + ContextMenu.pos = pos + ContextMenu.clickedNode = node + ContextMenu.clickedEdge = null + ContextMenu.siblingsData = null + ReactApp.render() + }, + selectEdge: (edge, pos) => { + ContextMenu.pos = pos + ContextMenu.clickedNode = null + ContextMenu.clickedEdge = edge + ContextMenu.siblingsData = null + ReactApp.render() + }, + reset: () => { + ContextMenu.siblingsData = null + ContextMenu.clickedNode = null + ContextMenu.clickedEdge = null + ReactApp.render() + }, + delete: Control.deleteSelected, + remove: () => { + Control.removeSelectedEdges() + Control.removeSelectedNodes() + ContextMenu.reset() + }, + hide: () => { + Control.hideSelectedEdges() + Control.hideSelectedNodes() + ContextMenu.reset() + }, + centerOn: (id) => { + Topic.centerOn(id) + ContextMenu.reset() + }, + popoutTopic: (id) => { + ContextMenu.reset() + const win = window.open('/topics/' + id, '_blank') + win.focus() + }, + updatePermissions: (permission) => { + // will be 'commons' 'public' or 'private' + Control.updateSelectedPermissions(permission) + ContextMenu.reset() + }, + onMetacodeSelect: (id, metacodeId) => { + if (Selected.Nodes.length > 1) { + // batch update multiple topics + Control.updateSelectedMetacodes(metacodeId) + } else { + const topic = DataModel.Topics.get(id) + topic.save({ + metacode_id: metacodeId + }) + } + ContextMenu.reset() + }, + fetchRelatives: (node, metacodeId) => { + Topic.fetchRelatives(node, metacodeId) + ContextMenu.reset() + }, + populateSiblings: function(id) { + // depending on how many topics are selected, do different things + + // add a loading icon for now + /*const loader = new CanvasLoader('loadingSiblings') + loader.setColor('#4FC059') // default is '#000000' + loader.setDiameter(15) // default is 40 + loader.setDensity(41) // default is 40 + loader.setRange(0.9) // default is 1.3 + loader.show() // Hidden by default*/ + + const topics = DataModel.Topics.map(function(t) { return t.id }) + const topicsString = topics.join() + + const successCallback = function(data) { + ContextMenu.siblingsData = data + ReactApp.render() + /*$('#loadingSiblings').remove() + + for (var key in data) { + const string = `${DataModel.Metacodes.get(key).get('name')} (${data[key]})` + $('#fetchSiblingList').append(`
  • ${string}
  • `) + } + + $('.rc-siblings .getSiblings').click(function() { + $('.rightclickmenu').remove() + // data-id is a metacode id + Topic.fetchRelatives(node, $(this).attr('data-id')) + })*/ + } + + $.ajax({ + type: 'GET', + url: '/topics/' + id + '/relative_numbers.json?network=' + topicsString, + success: successCallback, + error: function() {} + }) + } +} + +export default ContextMenu diff --git a/frontend/src/Metamaps/Views/index.js b/frontend/src/Metamaps/Views/index.js index 0f7cf566..de9d5aab 100644 --- a/frontend/src/Metamaps/Views/index.js +++ b/frontend/src/Metamaps/Views/index.js @@ -1,5 +1,6 @@ /* global $ */ +import ContextMenu from './ContextMenu' import ExploreMaps from './ExploreMaps' import ChatView from './ChatView' import VideoView from './VideoView' @@ -12,6 +13,7 @@ const Views = { $(document).on(JUNTO_UPDATED, () => ExploreMaps.render()) ChatView.init([serverData['sounds/MM_sounds.mp3'], serverData['sounds/MM_sounds.ogg']]) }, + ContextMenu, ExploreMaps, ChatView, VideoView, @@ -19,5 +21,5 @@ const Views = { TopicCard } -export { ExploreMaps, ChatView, VideoView, Room, TopicCard } +export { ContextMenu, ExploreMaps, ChatView, VideoView, Room, TopicCard } export default Views diff --git a/frontend/src/components/common/ContextMenu.js b/frontend/src/components/common/ContextMenu.js new file mode 100644 index 00000000..abc0bad4 --- /dev/null +++ b/frontend/src/components/common/ContextMenu.js @@ -0,0 +1,77 @@ +import React, { Component, PropTypes } from 'react' + +class ContextMenu extends Component { + static propTypes = { + node: PropTypes.object, + edge: PropTypes.object + } + + render () { + const style = { + position: 'absolute', + top: '10px', + left: '10px' + } + return
    + +
    + + // position the menu where the click happened + /*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 = $(window).width() + const windowHeight = $(window).height() + + if (windowWidth - e.clientX < SUBMENUS_WIDTH) { + position.right = windowWidth - e.clientX + $(rightclickmenu).addClass('moveMenusToLeft') + } else if (windowWidth - e.clientX < RIGHTCLICK_WIDTH) { + position.right = windowWidth - e.clientX + } else if (windowWidth - e.clientX < RIGHTCLICK_WIDTH + SUBMENUS_WIDTH) { + position.left = e.clientX + $(rightclickmenu).addClass('moveMenusToLeft') + } else { + position.left = e.clientX + } + + if (windowHeight - e.clientY < MAX_SUBMENU_HEIGHT) { + position.bottom = windowHeight - e.clientY + $(rightclickmenu).addClass('moveMenusUp') + } else if (windowHeight - e.clientY < RIGHTCLICK_HEIGHT + MAX_SUBMENU_HEIGHT) { + position.top = e.clientY + $(rightclickmenu).addClass('moveMenusUp') + } else { + position.top = e.clientY + }*/ + } +} + +export default ContextMenu