diff --git a/app/policies/synapse_policy.rb b/app/policies/synapse_policy.rb index e3190c18..54cb47c1 100644 --- a/app/policies/synapse_policy.rb +++ b/app/policies/synapse_policy.rb @@ -38,7 +38,7 @@ class SynapsePolicy < ApplicationPolicy end def destroy? - record.user == user || admin_override + record.mappings.empty? && (record.user == user || admin_override) end # Helpers diff --git a/app/policies/topic_policy.rb b/app/policies/topic_policy.rb index 64463b4a..178f3d96 100644 --- a/app/policies/topic_policy.rb +++ b/app/policies/topic_policy.rb @@ -36,7 +36,7 @@ class TopicPolicy < ApplicationPolicy end def destroy? - record.user == user || admin_override + record.mappings.empty? && (record.user == user || admin_override) end def autocomplete_topic? diff --git a/frontend/src/Metamaps/Control.js b/frontend/src/Metamaps/Control.js index 8f613b16..bc5266e6 100644 --- a/frontend/src/Metamaps/Control.js +++ b/frontend/src/Metamaps/Control.js @@ -39,76 +39,13 @@ const Control = { Selected.Nodes.splice( Selected.Nodes.indexOf(node), 1) }, - deleteSelected: function() { - if (!Active.Map) return - - var n = Selected.Nodes.length - var e = Selected.Edges.length - var ntext = n === 1 ? '1 topic' : n + ' topics' - var etext = e === 1 ? '1 synapse' : e + ' synapses' - - var authorized = Active.Map.authorizeToEdit(Active.Mapper) - - if (!authorized) { - GlobalUI.notifyUser('Cannot edit Public map.') - return - } - - var r = window.confirm(outdent` - You have ${ntext} and ${etext} selected. Are you sure you want - to permanently delete them all? This will remove them from all - maps they appear on.`) - if (r) { - Control.deleteSelectedEdges() - Control.deleteSelectedNodes() - } - - if (DataModel.Topics.length === 0) { - GlobalUI.showDiv('#instructions') - } + removeSelected: function() { + Control.removeSelectedEdges() + Control.removeSelectedNodes() }, - deleteSelectedNodes: function() { // refers to deleting topics permanently - if (!Active.Map) return - - var authorized = Active.Map.authorizeToEdit(Active.Mapper) - - if (!authorized) { - GlobalUI.notifyUser('Cannot edit Public map.') - return - } - - var l = Selected.Nodes.length - for (var i = l - 1; i >= 0; i -= 1) { - var node = Selected.Nodes[i] - Control.deleteNode(node.id) - } - }, - deleteNode: function(nodeid) { // refers to deleting topics permanently - if (!Active.Map) return - - var authorized = Active.Map.authorizeToEdit(Active.Mapper) - - if (!authorized) { - GlobalUI.notifyUser('Cannot edit Public map.') - return - } - - var node = Visualize.mGraph.graph.getNode(nodeid) - var topic = node.getData('topic') - - var permToDelete = Active.Mapper.id === topic.get('user_id') || Active.Mapper.get('admin') - if (permToDelete) { - var mappableid = topic.id - var mapping = node.getData('mapping') - topic.destroy() - DataModel.Mappings.remove(mapping) - $(document).trigger(JIT.events.deleteTopic, [{ - mappableid: mappableid - }]) - Control.hideNode(nodeid) - } else { - GlobalUI.notifyUser('Only topics you created can be deleted') - } + hideSelected: function() { + Control.hideSelectedEdges() + Control.hideSelectedNodes() }, removeSelectedNodes: function() { // refers to removing topics permanently from a map if (Active.Topic) { @@ -237,59 +174,6 @@ const Control = { Selected.Edges.splice( Selected.Edges.indexOf(edge), 1) }, - deleteSelectedEdges: function() { // refers to deleting topics permanently - if (!Active.Map) return - - var authorized = Active.Map.authorizeToEdit(Active.Mapper) - - if (!authorized) { - GlobalUI.notifyUser('Cannot edit Public map.') - return - } - - const l = Selected.Edges.length - for (let i = l - 1; i >= 0; i -= 1) { - const edge = Selected.Edges[i] - Control.deleteEdge(edge) - } - }, - deleteEdge: function(edge) { - if (!Active.Map) return - - var authorized = Active.Map.authorizeToEdit(Active.Mapper) - - if (!authorized) { - GlobalUI.notifyUser('Cannot edit Public map.') - return - } - - var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0 - - var synapse = edge.getData('synapses')[index] - var mapping = edge.getData('mappings')[index] - - var permToDelete = Active.Mapper.id === synapse.get('user_id') || Active.Mapper.get('admin') - if (permToDelete) { - if (edge.getData('synapses').length - 1 === 0) { - Control.hideEdge(edge) - } - var mappableid = synapse.id - synapse.destroy() - - // the server will destroy the mapping, we just need to remove it here - DataModel.Mappings.remove(mapping) - edge.getData('mappings').splice(index, 1) - edge.getData('synapses').splice(index, 1) - if (edge.getData('displayIndex')) { - delete edge.data.$displayIndex - } - $(document).trigger(JIT.events.deleteSynapse, [{ - mappableid: mappableid - }]) - } else { - GlobalUI.notifyUser('Only synapses you created can be deleted') - } - }, removeSelectedEdges: function() { // Topic view is handled by removeSelectedNodes if (!Active.Map) return @@ -299,7 +183,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit this map.') return } diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index 903cc11d..8a0ac7c6 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -37,10 +37,8 @@ const JIT = { events: { topicDrag: 'Metamaps:JIT:events:topicDrag', newTopic: 'Metamaps:JIT:events:newTopic', - deleteTopic: 'Metamaps:JIT:events:deleteTopic', removeTopic: 'Metamaps:JIT:events:removeTopic', newSynapse: 'Metamaps:JIT:events:newSynapse', - deleteSynapse: 'Metamaps:JIT:events:deleteSynapse', removeSynapse: 'Metamaps:JIT:events:removeSynapse', pan: 'Metamaps:JIT:events:pan', zoom: 'Metamaps:JIT:events:zoom', @@ -1396,9 +1394,8 @@ const JIT = { const disabled = authorized ? '' : 'disabled' if (Active.Map) menustring += '
  • Hide until refresh
    Ctrl+H
  • ' - if (Active.Map && Active.Mapper) menustring += '
  • Remove from map
    Ctrl+M
  • ' - if (Active.Topic) menustring += '
  • Remove from view
    Ctrl+M
  • ' - if (Active.Map && Active.Mapper) menustring += '
  • Delete
    Ctrl+D
  • ' + if (Active.Map && Active.Mapper) menustring += '
  • Remove
    Ctrl+D
  • ' + if (Active.Topic) menustring += '
  • Remove from view
    Ctrl+D
  • ' if (Active.Topic) { menustring += '
  • Center this topic
    Alt+E
  • ' @@ -1483,28 +1480,18 @@ const JIT = { // 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() + Control.removeSelected() }) } // hide selected nodes and synapses until refresh $('.rc-hide').click(function() { $('.rightclickmenu').remove() - Control.hideSelectedEdges() - Control.hideSelectedNodes() + Control.hideSelected() }) // when in radial, center on the topic you picked @@ -1654,9 +1641,8 @@ const JIT = { const disabled = authorized ? '' : 'disabled' if (Active.Map) menustring += '
  • Hide until refresh
    Ctrl+H
  • ' - if (Active.Map && Active.Mapper) menustring += '
  • Remove from map
    Ctrl+M
  • ' - if (Active.Topic) menustring += '
  • Remove from view
    Ctrl+M
  • ' - if (Active.Map && Active.Mapper) menustring += '
  • Delete
    Ctrl+D
  • ' + if (Active.Map && Active.Mapper) menustring += '
  • Remove
    Ctrl+D
  • ' + if (Active.Topic) menustring += '
  • Remove from view
    Ctrl+D
  • ' if (Active.Map && Active.Mapper) menustring += '
  • ' @@ -1703,28 +1689,18 @@ const JIT = { // 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 (authorized) { $('.rc-remove').click(function() { $('.rightclickmenu').remove() - Control.removeSelectedEdges() - Control.removeSelectedNodes() + Control.removeSelected() }) } // hide selected nodes and synapses until refresh $('.rc-hide').click(function() { $('.rightclickmenu').remove() - Control.hideSelectedEdges() - Control.hideSelectedNodes() + Control.hideSelected() }) // change the permission of all the selected nodes and synapses that you were the originator of diff --git a/frontend/src/Metamaps/Listeners.js b/frontend/src/Metamaps/Listeners.js index 756227b1..76c5e540 100644 --- a/frontend/src/Metamaps/Listeners.js +++ b/frontend/src/Metamaps/Listeners.js @@ -60,7 +60,7 @@ const Listeners = { case 68: // if d or D is pressed if (e.ctrlKey || e.metaKey) { e.preventDefault() - Control.deleteSelected() + Control.removeSelected() } break case 69: // if e or E is pressed @@ -84,15 +84,16 @@ const Listeners = { case 72: // if h or H is pressed if (e.ctrlKey || e.metaKey) { e.preventDefault() - Control.hideSelectedNodes() - Control.hideSelectedEdges() + Control.hideSelected() } break case 77: // if m or M is pressed + // since we're removing 'deletion', we have Ctrl-D available for this now, but leave this in + // as a deprecated function, just in case its what people got used to + // or should we do a GlobalUI.notifyUser to ask them to switch? if (e.ctrlKey || e.metaKey) { e.preventDefault() - Control.removeSelectedNodes() - Control.removeSelectedEdges() + Control.removeSelected() } break case 82: // if r or R is pressed diff --git a/frontend/src/Metamaps/Realtime/index.js b/frontend/src/Metamaps/Realtime/index.js index 318753f0..65bbceea 100644 --- a/frontend/src/Metamaps/Realtime/index.js +++ b/frontend/src/Metamaps/Realtime/index.js @@ -29,11 +29,9 @@ import { TOPIC_CREATED, TOPIC_UPDATED, TOPIC_REMOVED, - TOPIC_DELETED, SYNAPSE_CREATED, SYNAPSE_UPDATED, SYNAPSE_REMOVED, - SYNAPSE_DELETED, PEER_COORDS_UPDATED, MAP_UPDATED } from './events' @@ -58,11 +56,9 @@ import { topicCreated, topicUpdated, topicRemoved, - topicDeleted, synapseCreated, synapseUpdated, synapseRemoved, - synapseDeleted, mapUpdated } from './receivable' @@ -84,11 +80,9 @@ import { createTopic, updateTopic, removeTopic, - deleteTopic, createSynapse, updateSynapse, removeSynapse, - deleteSynapse, updateMap } from './sendable' @@ -304,11 +298,6 @@ let Realtime = { } $(document).on(JIT.events.newTopic + '.map', createTopic) - var deleteTopic = function(event, data) { - self.deleteTopic(data) - } - $(document).on(JIT.events.deleteTopic + '.map', deleteTopic) - var removeTopic = function(event, data) { self.removeTopic(data) } @@ -319,11 +308,6 @@ let Realtime = { } $(document).on(JIT.events.newSynapse + '.map', createSynapse) - var deleteSynapse = function(event, data) { - self.deleteSynapse(data) - } - $(document).on(JIT.events.deleteSynapse + '.map', deleteSynapse) - var removeSynapse = function(event, data) { self.removeSynapse(data) } @@ -500,11 +484,9 @@ const sendables = [ ['createTopic', createTopic], ['updateTopic', updateTopic], ['removeTopic', removeTopic], - ['deleteTopic', deleteTopic], ['createSynapse', createSynapse], ['updateSynapse', updateSynapse], ['removeSynapse', removeSynapse], - ['deleteSynapse', deleteSynapse], ['updateMap', updateMap] ] sendables.forEach(sendable => { @@ -531,11 +513,9 @@ const subscribeToEvents = (Realtime, socket) => { socket.on(TOPIC_CREATED, topicCreated(Realtime)) socket.on(TOPIC_UPDATED, topicUpdated(Realtime)) socket.on(TOPIC_REMOVED, topicRemoved(Realtime)) - socket.on(TOPIC_DELETED, topicDeleted(Realtime)) socket.on(SYNAPSE_CREATED, synapseCreated(Realtime)) socket.on(SYNAPSE_UPDATED, synapseUpdated(Realtime)) socket.on(SYNAPSE_REMOVED, synapseRemoved(Realtime)) - socket.on(SYNAPSE_DELETED, synapseDeleted(Realtime)) socket.on(MAP_UPDATED, mapUpdated(Realtime)) } diff --git a/realtime/global.js b/realtime/global.js index 485085a6..0a00b3fd 100644 --- a/realtime/global.js +++ b/realtime/global.js @@ -1,9 +1,7 @@ const { // server sendable, client receivable TOPIC_UPDATED, - TOPIC_DELETED, SYNAPSE_UPDATED, - SYNAPSE_DELETED, MAP_UPDATED, JUNTO_UPDATED, @@ -13,15 +11,12 @@ const { JOIN_MAP, LEAVE_MAP, UPDATE_TOPIC, - DELETE_TOPIC, UPDATE_SYNAPSE, - DELETE_SYNAPSE, UPDATE_MAP } = require('../frontend/src/Metamaps/Realtime/events') module.exports = function(io, store) { store.subscribe(() => { - console.log(store.getState()) io.sockets.emit(JUNTO_UPDATED, store.getState()) }) @@ -38,18 +33,10 @@ module.exports = function(io, store) { socket.broadcast.emit(TOPIC_UPDATED, data) }) - socket.on(DELETE_TOPIC, function(data) { - socket.broadcast.emit(TOPIC_DELETED, data) - }) - socket.on(UPDATE_SYNAPSE, function(data) { socket.broadcast.emit(SYNAPSE_UPDATED, data) }) - socket.on(DELETE_SYNAPSE, function(data) { - socket.broadcast.emit(SYNAPSE_DELETED, data) - }) - socket.on(UPDATE_MAP, function(data) { socket.broadcast.emit(MAP_UPDATED, data) })