Stream map related events from rails server via actioncable instead of nodejs (#1010)
* actioncable needs puma not webrick * add framework * remove the old way * send events from server to client * get all events working * clean up receivable * map is polymorphic on message * add the moved event * make todo comments clear * verify before streaming from map channel * rubocop fixes * wasn't set up correctly for nodejs realtime
This commit is contained in:
parent
5c1261892f
commit
3868910dde
29 changed files with 383 additions and 641 deletions
1
Gemfile
1
Gemfile
|
@ -44,6 +44,7 @@ group :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
|
gem 'puma'
|
||||||
gem 'better_errors'
|
gem 'better_errors'
|
||||||
gem 'binding_of_caller'
|
gem 'binding_of_caller'
|
||||||
gem 'pry-byebug'
|
gem 'pry-byebug'
|
||||||
|
|
|
@ -167,6 +167,7 @@ GEM
|
||||||
pry (~> 0.10)
|
pry (~> 0.10)
|
||||||
pry-rails (0.3.4)
|
pry-rails (0.3.4)
|
||||||
pry (>= 0.9.10)
|
pry (>= 0.9.10)
|
||||||
|
puma (3.6.2)
|
||||||
pundit (1.1.0)
|
pundit (1.1.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
pundit_extra (0.3.0)
|
pundit_extra (0.3.0)
|
||||||
|
@ -298,6 +299,7 @@ DEPENDENCIES
|
||||||
pg
|
pg
|
||||||
pry-byebug
|
pry-byebug
|
||||||
pry-rails
|
pry-rails
|
||||||
|
puma
|
||||||
pundit
|
pundit
|
||||||
pundit_extra
|
pundit_extra
|
||||||
rack-attack
|
rack-attack
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
//= require jquery
|
//= require jquery
|
||||||
//= require jquery-ui
|
//= require jquery-ui
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
|
//= require action_cable
|
||||||
//= require_directory ./lib
|
//= require_directory ./lib
|
||||||
//= require ./webpacked/metamaps.bundle
|
//= require ./webpacked/metamaps.bundle
|
||||||
//= require ./Metamaps.ServerData
|
//= require ./Metamaps.ServerData
|
||||||
|
|
4
app/channels/application_cable/channel.rb
Normal file
4
app/channels/application_cable/channel.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module ApplicationCable
|
||||||
|
class Channel < ActionCable::Channel::Base
|
||||||
|
end
|
||||||
|
end
|
22
app/channels/application_cable/connection.rb
Normal file
22
app/channels/application_cable/connection.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
module ApplicationCable
|
||||||
|
class Connection < ActionCable::Connection::Base
|
||||||
|
identified_by :current_user
|
||||||
|
|
||||||
|
def connect
|
||||||
|
self.current_user = find_verified_user
|
||||||
|
logger.add_tags 'ActionCable', current_user.name
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def find_verified_user
|
||||||
|
verified_user = User.find_by(id: cookies.signed['user.id'])
|
||||||
|
if verified_user && cookies.signed['user.expires_at'] > Time.now.getlocal
|
||||||
|
verified_user
|
||||||
|
else
|
||||||
|
reject_unauthorized_connection
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
8
app/channels/map_channel.rb
Normal file
8
app/channels/map_channel.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class MapChannel < ApplicationCable::Channel
|
||||||
|
# Called when the consumer has successfully
|
||||||
|
# become a subscriber of this channel.
|
||||||
|
def subscribed
|
||||||
|
return unless Pundit.policy(current_user, Map.find(params[:id])).show?
|
||||||
|
stream_from "map_#{params[:id]}"
|
||||||
|
end
|
||||||
|
end
|
|
@ -33,6 +33,7 @@ class Map < ApplicationRecord
|
||||||
# Validate the attached image is image/jpg, image/png, etc
|
# Validate the attached image is image/jpg, image/png, etc
|
||||||
validates_attachment_content_type :screenshot, content_type: /\Aimage\/.*\Z/
|
validates_attachment_content_type :screenshot, content_type: /\Aimage\/.*\Z/
|
||||||
|
|
||||||
|
after_update :after_updated
|
||||||
after_save :update_deferring_topics_and_synapses, if: :permission_changed?
|
after_save :update_deferring_topics_and_synapses, if: :permission_changed?
|
||||||
|
|
||||||
delegate :count, to: :topics, prefix: :topic # same as `def topic_count; topics.count; end`
|
delegate :count, to: :topics, prefix: :topic # same as `def topic_count; topics.count; end`
|
||||||
|
@ -119,6 +120,13 @@ class Map < ApplicationRecord
|
||||||
end
|
end
|
||||||
removed.compact
|
removed.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_updated
|
||||||
|
attrs = ['name', 'desc', 'permission']
|
||||||
|
if attrs.any? {|k| changed_attributes.key?(k)}
|
||||||
|
ActionCable.server.broadcast 'map_' + id.to_s, type: 'mapUpdated'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update_deferring_topics_and_synapses
|
def update_deferring_topics_and_synapses
|
||||||
Topic.where(defer_to_map_id: id).update_all(permission: permission)
|
Topic.where(defer_to_map_id: id).update_all(permission: permission)
|
||||||
|
|
|
@ -33,8 +33,16 @@ class Mapping < ApplicationRecord
|
||||||
if mappable_type == 'Topic'
|
if mappable_type == 'Topic'
|
||||||
meta = {'x': xloc, 'y': yloc, 'mapping_id': id}
|
meta = {'x': xloc, 'y': yloc, 'mapping_id': id}
|
||||||
Events::TopicAddedToMap.publish!(mappable, map, user, meta)
|
Events::TopicAddedToMap.publish!(mappable, map, user, meta)
|
||||||
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicAdded', topic: mappable.filtered, mapping_id: id
|
||||||
elsif mappable_type == 'Synapse'
|
elsif mappable_type == 'Synapse'
|
||||||
Events::SynapseAddedToMap.publish!(mappable, map, user, meta)
|
Events::SynapseAddedToMap.publish!(mappable, map, user, meta)
|
||||||
|
ActionCable.server.broadcast(
|
||||||
|
'map_' + map.id.to_s,
|
||||||
|
type: 'synapseAdded',
|
||||||
|
synapse: mappable.filtered,
|
||||||
|
topic1: mappable.topic1.filtered,
|
||||||
|
topic2: mappable.topic2.filtered,
|
||||||
|
mapping_id: id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -42,6 +50,7 @@ class Mapping < ApplicationRecord
|
||||||
if mappable_type == 'Topic' and (xloc_changed? or yloc_changed?)
|
if mappable_type == 'Topic' and (xloc_changed? or yloc_changed?)
|
||||||
meta = {'x': xloc, 'y': yloc, 'mapping_id': id}
|
meta = {'x': xloc, 'y': yloc, 'mapping_id': id}
|
||||||
Events::TopicMovedOnMap.publish!(mappable, map, updated_by, meta)
|
Events::TopicMovedOnMap.publish!(mappable, map, updated_by, meta)
|
||||||
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicMoved', id: mappable.id, mapping_id: id, x: xloc, y: yloc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -55,8 +64,10 @@ class Mapping < ApplicationRecord
|
||||||
meta = {'mapping_id': id}
|
meta = {'mapping_id': id}
|
||||||
if mappable_type == 'Topic'
|
if mappable_type == 'Topic'
|
||||||
Events::TopicRemovedFromMap.publish!(mappable, map, updated_by, meta)
|
Events::TopicRemovedFromMap.publish!(mappable, map, updated_by, meta)
|
||||||
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicRemoved', id: mappable.id, mapping_id: id
|
||||||
elsif mappable_type == 'Synapse'
|
elsif mappable_type == 'Synapse'
|
||||||
Events::SynapseRemovedFromMap.publish!(mappable, map, updated_by, meta)
|
Events::SynapseRemovedFromMap.publish!(mappable, map, updated_by, meta)
|
||||||
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseRemoved', id: mappable.id, mapping_id: id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,8 @@ class Message < ApplicationRecord
|
||||||
belongs_to :resource, polymorphic: true
|
belongs_to :resource, polymorphic: true
|
||||||
|
|
||||||
delegate :name, to: :user, prefix: true
|
delegate :name, to: :user, prefix: true
|
||||||
|
|
||||||
|
after_create :after_created
|
||||||
|
|
||||||
def user_image
|
def user_image
|
||||||
user.image.url
|
user.image.url
|
||||||
|
@ -13,4 +15,8 @@ class Message < ApplicationRecord
|
||||||
json = super(methods: [:user_name, :user_image])
|
json = super(methods: [:user_name, :user_image])
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_created
|
||||||
|
ActionCable.server.broadcast 'map_' + resource.id.to_s, type: 'messageCreated', message: self.as_json
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,6 +38,15 @@ class Synapse < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filtered
|
||||||
|
{
|
||||||
|
id: id,
|
||||||
|
permission: permission,
|
||||||
|
user_id: user_id,
|
||||||
|
collaborator_ids: collaborator_ids
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def as_json(_options = {})
|
def as_json(_options = {})
|
||||||
super(methods: [:user_name, :user_image, :collaborator_ids])
|
super(methods: [:user_name, :user_image, :collaborator_ids])
|
||||||
end
|
end
|
||||||
|
@ -50,6 +59,9 @@ class Synapse < ApplicationRecord
|
||||||
meta = new.merge(old) # we are prioritizing the old values, keeping them
|
meta = new.merge(old) # we are prioritizing the old values, keeping them
|
||||||
meta['changed'] = changed_attributes.keys.select {|k| attrs.include?(k) }
|
meta['changed'] = changed_attributes.keys.select {|k| attrs.include?(k) }
|
||||||
Events::SynapseUpdated.publish!(self, user, meta)
|
Events::SynapseUpdated.publish!(self, user, meta)
|
||||||
|
maps.each {|map|
|
||||||
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'synapseUpdated', id: id
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,6 +90,15 @@ class Topic < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filtered
|
||||||
|
{
|
||||||
|
id: id,
|
||||||
|
permission: permission,
|
||||||
|
user_id: user_id,
|
||||||
|
collaborator_ids: collaborator_ids
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# TODO: move to a decorator?
|
# TODO: move to a decorator?
|
||||||
def synapses_csv(output_format = 'array')
|
def synapses_csv(output_format = 'array')
|
||||||
output = []
|
output = []
|
||||||
|
@ -145,6 +154,9 @@ class Topic < ApplicationRecord
|
||||||
meta = new.merge(old) # we are prioritizing the old values, keeping them
|
meta = new.merge(old) # we are prioritizing the old values, keeping them
|
||||||
meta['changed'] = changed_attributes.keys.select {|k| attrs.include?(k) }
|
meta['changed'] = changed_attributes.keys.select {|k| attrs.include?(k) }
|
||||||
Events::TopicUpdated.publish!(self, user, meta)
|
Events::TopicUpdated.publish!(self, user, meta)
|
||||||
|
maps.each {|map|
|
||||||
|
ActionCable.server.broadcast 'map_' + map.id.to_s, type: 'topicUpdated', id: id
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
10
config/initializers/warden_hooks.rb
Normal file
10
config/initializers/warden_hooks.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Warden::Manager.after_set_user do |user,auth,opts|
|
||||||
|
scope = opts[:scope]
|
||||||
|
auth.cookies.signed["#{scope}.id"] = user.id
|
||||||
|
auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
|
||||||
|
end
|
||||||
|
Warden::Manager.before_logout do |user, auth, opts|
|
||||||
|
scope = opts[:scope]
|
||||||
|
auth.cookies.signed["#{scope}.id"] = nil
|
||||||
|
auth.cookies.signed["#{scope}.expires_at"] = nil
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
Metamaps::Application.routes.draw do
|
Metamaps::Application.routes.draw do
|
||||||
use_doorkeeper
|
use_doorkeeper
|
||||||
|
mount ActionCable.server => '/cable'
|
||||||
|
|
||||||
root to: 'main#home', via: :get
|
root to: 'main#home', via: :get
|
||||||
get 'request', to: 'main#requestinvite', as: :request
|
get 'request', to: 'main#requestinvite', as: :request
|
||||||
|
|
232
frontend/src/Metamaps/Cable.js
Normal file
232
frontend/src/Metamaps/Cable.js
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
/* global $, ActionCable */
|
||||||
|
|
||||||
|
import Active from './Active'
|
||||||
|
import Control from './Control'
|
||||||
|
import DataModel from './DataModel'
|
||||||
|
import Map from './Map'
|
||||||
|
import Mapper from './Mapper'
|
||||||
|
import Synapse from './Synapse'
|
||||||
|
import Topic from './Topic'
|
||||||
|
import { ChatView } from './Views'
|
||||||
|
import Visualize from './Visualize'
|
||||||
|
|
||||||
|
const Cable = {
|
||||||
|
init: () => {
|
||||||
|
let self = Cable
|
||||||
|
self.cable = ActionCable.createConsumer()
|
||||||
|
},
|
||||||
|
subscribeToMap: id => {
|
||||||
|
let self = Cable
|
||||||
|
self.sub = self.cable.subscriptions.create({
|
||||||
|
channel: 'MapChannel',
|
||||||
|
id: id
|
||||||
|
}, {
|
||||||
|
received: event => self[event.type](event)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
unsubscribeFromMap: () => {
|
||||||
|
let self = Cable
|
||||||
|
self.sub.unsubscribe()
|
||||||
|
delete self.sub
|
||||||
|
},
|
||||||
|
synapseAdded: event => {
|
||||||
|
// we receive contentless models from the server
|
||||||
|
// containing only the information we need to determine whether the active mapper
|
||||||
|
// can view this synapse and the two topics it connects,
|
||||||
|
// then if we determine it can, we make a call for the full model
|
||||||
|
const m = Active.Mapper
|
||||||
|
const s = new DataModel.Synapse(event.synapse)
|
||||||
|
const t1 = new DataModel.Topic(event.topic1)
|
||||||
|
const t2 = new DataModel.Topic(event.topic2)
|
||||||
|
|
||||||
|
if (t1.authorizeToShow(m) && t2.authorizeToShow(m) && s.authorizeToShow(m) && !DataModel.Synapses.get(event.synapse.id)) {
|
||||||
|
// refactor the heck outta this, its adding wicked wait time
|
||||||
|
var topic1, topic2, node1, node2, synapse, mapping, cancel, mapper
|
||||||
|
|
||||||
|
function waitThenRenderSynapse() {
|
||||||
|
if (synapse && mapping && mapper) {
|
||||||
|
topic1 = synapse.getTopic1()
|
||||||
|
node1 = topic1.get('node')
|
||||||
|
topic2 = synapse.getTopic2()
|
||||||
|
node2 = topic2.get('node')
|
||||||
|
|
||||||
|
Synapse.renderSynapse(mapping, synapse, node1, node2, false)
|
||||||
|
} else if (!cancel) {
|
||||||
|
setTimeout(waitThenRenderSynapse, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapper = DataModel.Mappers.get(event.synapse.user_id)
|
||||||
|
if (mapper === undefined) {
|
||||||
|
Mapper.get(event.synapse.user_id, function(m) {
|
||||||
|
DataModel.Mappers.add(m)
|
||||||
|
mapper = m
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: '/synapses/' + event.synapse.id + '.json',
|
||||||
|
success: function(response) {
|
||||||
|
DataModel.Synapses.add(response)
|
||||||
|
synapse = DataModel.Synapses.get(response.id)
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
cancel = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$.ajax({
|
||||||
|
url: '/mappings/' + event.mapping_id + '.json',
|
||||||
|
success: function(response) {
|
||||||
|
DataModel.Mappings.add(response)
|
||||||
|
mapping = DataModel.Mappings.get(response.id)
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
cancel = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
waitThenRenderSynapse()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
synapseUpdated: event => {
|
||||||
|
// TODO: handle case where permission changed
|
||||||
|
var synapse = DataModel.Synapses.get(event.id)
|
||||||
|
if (synapse) {
|
||||||
|
// edge reset necessary because fetch causes model reset
|
||||||
|
var edge = synapse.get('edge')
|
||||||
|
synapse.fetch({
|
||||||
|
success: function(model) {
|
||||||
|
model.set({ edge: edge })
|
||||||
|
model.trigger('changeByOther')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
synapseRemoved: event => {
|
||||||
|
var synapse = DataModel.Synapses.get(event.id)
|
||||||
|
if (synapse) {
|
||||||
|
var edge = synapse.get('edge')
|
||||||
|
var mapping = synapse.getMapping()
|
||||||
|
if (edge.getData('mappings').length - 1 === 0) {
|
||||||
|
Control.hideEdge(edge)
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = indexOf(edge.getData('synapses'), synapse)
|
||||||
|
edge.getData('mappings').splice(index, 1)
|
||||||
|
edge.getData('synapses').splice(index, 1)
|
||||||
|
if (edge.getData('displayIndex')) {
|
||||||
|
delete edge.data.$displayIndex
|
||||||
|
}
|
||||||
|
DataModel.Synapses.remove(synapse)
|
||||||
|
DataModel.Mappings.remove(mapping)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topicAdded: event => {
|
||||||
|
const m = Active.Mapper
|
||||||
|
// we receive a contentless model from the server
|
||||||
|
// containing only the information we need to determine whether the active mapper
|
||||||
|
// can view this topic, then if we determine it can, we make a call for the full model
|
||||||
|
const t = new DataModel.Topic(event.topic)
|
||||||
|
|
||||||
|
if (t.authorizeToShow(m) && !DataModel.Topics.get(event.topic.id)) {
|
||||||
|
// refactor the heck outta this, its adding wicked wait time
|
||||||
|
var topic, mapping, mapper, cancel
|
||||||
|
|
||||||
|
function waitThenRenderTopic() {
|
||||||
|
if (topic && mapping && mapper) {
|
||||||
|
Topic.renderTopic(mapping, topic, false, false)
|
||||||
|
} else if (!cancel) {
|
||||||
|
setTimeout(waitThenRenderTopic, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapper = DataModel.Mappers.get(event.topic.user_id)
|
||||||
|
if (mapper === undefined) {
|
||||||
|
Mapper.get(event.topic.user_id, function(m) {
|
||||||
|
DataModel.Mappers.add(m)
|
||||||
|
mapper = m
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: '/topics/' + event.topic.id + '.json',
|
||||||
|
success: function(response) {
|
||||||
|
DataModel.Topics.add(response)
|
||||||
|
topic = DataModel.Topics.get(response.id)
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
cancel = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$.ajax({
|
||||||
|
url: '/mappings/' + event.mapping_id + '.json',
|
||||||
|
success: function(response) {
|
||||||
|
DataModel.Mappings.add(response)
|
||||||
|
mapping = DataModel.Mappings.get(response.id)
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
cancel = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
waitThenRenderTopic()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topicUpdated: event => {
|
||||||
|
// TODO: handle case where permission changed
|
||||||
|
var topic = DataModel.Topics.get(event.id)
|
||||||
|
if (topic) {
|
||||||
|
var node = topic.get('node')
|
||||||
|
topic.fetch({
|
||||||
|
success: function(model) {
|
||||||
|
model.set({ node: node })
|
||||||
|
model.trigger('changeByOther')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topicMoved: event => {
|
||||||
|
var topic, node, mapping
|
||||||
|
if (Active.Map) {
|
||||||
|
topic = DataModel.Topics.get(event.id)
|
||||||
|
mapping = DataModel.Mappings.get(event.mapping_id)
|
||||||
|
mapping.set('xloc', event.x)
|
||||||
|
mapping.set('yloc', event.y)
|
||||||
|
if (topic) node = topic.get('node')
|
||||||
|
if (node) node.pos.setc(event.x, event.y)
|
||||||
|
Visualize.mGraph.plot()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topicRemoved: event => {
|
||||||
|
var topic = DataModel.Topics.get(event.id)
|
||||||
|
if (topic) {
|
||||||
|
var node = topic.get('node')
|
||||||
|
var mapping = topic.getMapping()
|
||||||
|
Control.hideNode(node.id)
|
||||||
|
DataModel.Topics.remove(topic)
|
||||||
|
DataModel.Mappings.remove(mapping)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
messageCreated: event => {
|
||||||
|
if (Active.Mapper && Active.Mapper.id === event.message.user_id) return
|
||||||
|
ChatView.addMessages(new DataModel.MessageCollection(event.message))
|
||||||
|
},
|
||||||
|
mapUpdated: event => {
|
||||||
|
var map = Active.Map
|
||||||
|
var couldEditBefore = map.authorizeToEdit(Active.Mapper)
|
||||||
|
var idBefore = map.id
|
||||||
|
map.fetch({
|
||||||
|
success: function(model, response) {
|
||||||
|
var idNow = model.id
|
||||||
|
var canEditNow = model.authorizeToEdit(Active.Mapper)
|
||||||
|
if (idNow !== idBefore) {
|
||||||
|
Map.leavePrivateMap() // this means the map has been changed to private
|
||||||
|
} else if (couldEditBefore && !canEditNow) {
|
||||||
|
Map.cantEditNow()
|
||||||
|
} else if (!couldEditBefore && canEditNow) {
|
||||||
|
Map.canEditNow()
|
||||||
|
} else {
|
||||||
|
model.trigger('changeByOther')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Cable
|
|
@ -102,9 +102,6 @@ const Control = {
|
||||||
var mapping = node.getData('mapping')
|
var mapping = node.getData('mapping')
|
||||||
topic.destroy()
|
topic.destroy()
|
||||||
DataModel.Mappings.remove(mapping)
|
DataModel.Mappings.remove(mapping)
|
||||||
$(document).trigger(JIT.events.deleteTopic, [{
|
|
||||||
mappableid: mappableid
|
|
||||||
}])
|
|
||||||
Control.hideNode(nodeid)
|
Control.hideNode(nodeid)
|
||||||
} else {
|
} else {
|
||||||
GlobalUI.notifyUser('Only topics you created can be deleted')
|
GlobalUI.notifyUser('Only topics you created can be deleted')
|
||||||
|
@ -155,9 +152,6 @@ const Control = {
|
||||||
var mapping = node.getData('mapping')
|
var mapping = node.getData('mapping')
|
||||||
mapping.destroy()
|
mapping.destroy()
|
||||||
DataModel.Topics.remove(topic)
|
DataModel.Topics.remove(topic)
|
||||||
$(document).trigger(JIT.events.removeTopic, [{
|
|
||||||
mappableid: mappableid
|
|
||||||
}])
|
|
||||||
Control.hideNode(nodeid)
|
Control.hideNode(nodeid)
|
||||||
},
|
},
|
||||||
hideSelectedNodes: function() {
|
hideSelectedNodes: function() {
|
||||||
|
@ -283,9 +277,6 @@ const Control = {
|
||||||
if (edge.getData('displayIndex')) {
|
if (edge.getData('displayIndex')) {
|
||||||
delete edge.data.$displayIndex
|
delete edge.data.$displayIndex
|
||||||
}
|
}
|
||||||
$(document).trigger(JIT.events.deleteSynapse, [{
|
|
||||||
mappableid: mappableid
|
|
||||||
}])
|
|
||||||
} else {
|
} else {
|
||||||
GlobalUI.notifyUser('Only synapses you created can be deleted')
|
GlobalUI.notifyUser('Only synapses you created can be deleted')
|
||||||
}
|
}
|
||||||
|
@ -337,9 +328,6 @@ const Control = {
|
||||||
if (edge.getData('displayIndex')) {
|
if (edge.getData('displayIndex')) {
|
||||||
delete edge.data.$displayIndex
|
delete edge.data.$displayIndex
|
||||||
}
|
}
|
||||||
$(document).trigger(JIT.events.removeSynapse, [{
|
|
||||||
mappableid: mappableid
|
|
||||||
}])
|
|
||||||
},
|
},
|
||||||
hideSelectedEdges: function() {
|
hideSelectedEdges: function() {
|
||||||
const l = Selected.Edges.length
|
const l = Selected.Edges.length
|
||||||
|
|
|
@ -15,32 +15,8 @@ const Map = Backbone.Model.extend({
|
||||||
toJSON: function(options) {
|
toJSON: function(options) {
|
||||||
return _.omit(this.attributes, this.blacklist)
|
return _.omit(this.attributes, this.blacklist)
|
||||||
},
|
},
|
||||||
save: function(key, val, options) {
|
|
||||||
var attrs
|
|
||||||
|
|
||||||
// Handle both `"key", value` and `{key: value}` -style arguments.
|
|
||||||
if (key == null || typeof key === 'object') {
|
|
||||||
attrs = key
|
|
||||||
options = val
|
|
||||||
} else {
|
|
||||||
(attrs = {})[key] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
var newOptions = options || {}
|
|
||||||
var s = newOptions.success
|
|
||||||
|
|
||||||
newOptions.success = function(model, response, opt) {
|
|
||||||
if (s) s(model, response, opt)
|
|
||||||
model.trigger('saved')
|
|
||||||
}
|
|
||||||
return Backbone.Model.prototype.save.call(this, attrs, newOptions)
|
|
||||||
},
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.on('changeByOther', this.updateView)
|
this.on('changeByOther', this.updateView)
|
||||||
this.on('saved', this.savedEvent)
|
|
||||||
},
|
|
||||||
savedEvent: function() {
|
|
||||||
Realtime.updateMap(this)
|
|
||||||
},
|
},
|
||||||
authorizeToEdit: function(mapper) {
|
authorizeToEdit: function(mapper) {
|
||||||
if (mapper && (
|
if (mapper && (
|
||||||
|
|
|
@ -20,34 +20,6 @@ const Synapse = Backbone.Model.extend({
|
||||||
toJSON: function(options) {
|
toJSON: function(options) {
|
||||||
return _.omit(this.attributes, this.blacklist)
|
return _.omit(this.attributes, this.blacklist)
|
||||||
},
|
},
|
||||||
save: function(key, val, options) {
|
|
||||||
var attrs
|
|
||||||
|
|
||||||
// Handle both `"key", value` and `{key: value}` -style arguments.
|
|
||||||
if (key == null || typeof key === 'object') {
|
|
||||||
attrs = key
|
|
||||||
options = val
|
|
||||||
} else {
|
|
||||||
(attrs = {})[key] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
var newOptions = options || {}
|
|
||||||
var s = newOptions.success
|
|
||||||
|
|
||||||
var permBefore = this.get('permission')
|
|
||||||
|
|
||||||
newOptions.success = function(model, response, opt) {
|
|
||||||
if (s) s(model, response, opt)
|
|
||||||
model.trigger('saved')
|
|
||||||
|
|
||||||
if (permBefore === 'private' && model.get('permission') !== 'private') {
|
|
||||||
model.trigger('noLongerPrivate')
|
|
||||||
} else if (permBefore !== 'private' && model.get('permission') === 'private') {
|
|
||||||
model.trigger('nowPrivate')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Backbone.Model.prototype.save.call(this, attrs, newOptions)
|
|
||||||
},
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
if (this.isNew()) {
|
if (this.isNew()) {
|
||||||
this.set({
|
this.set({
|
||||||
|
@ -56,24 +28,8 @@ const Synapse = Backbone.Model.extend({
|
||||||
'category': 'from-to'
|
'category': 'from-to'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.on('changeByOther', this.updateCardView)
|
this.on('changeByOther', this.updateCardView)
|
||||||
this.on('change', this.updateEdgeView)
|
this.on('change', this.updateEdgeView)
|
||||||
this.on('saved', this.savedEvent)
|
|
||||||
this.on('noLongerPrivate', function() {
|
|
||||||
var newSynapseData = {
|
|
||||||
mappingid: this.getMapping().id,
|
|
||||||
mappableid: this.id
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).trigger(JIT.events.newSynapse, [newSynapseData])
|
|
||||||
})
|
|
||||||
this.on('nowPrivate', function() {
|
|
||||||
$(document).trigger(JIT.events.removeSynapse, [{
|
|
||||||
mappableid: this.id
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
this.on('change:desc', Filter.checkSynapses, this)
|
this.on('change:desc', Filter.checkSynapses, this)
|
||||||
},
|
},
|
||||||
prepareLiForFilter: function() {
|
prepareLiForFilter: function() {
|
||||||
|
@ -87,6 +43,10 @@ const Synapse = Backbone.Model.extend({
|
||||||
if (mapper && (this.get('permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true
|
if (mapper && (this.get('permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true
|
||||||
else return false
|
else return false
|
||||||
},
|
},
|
||||||
|
authorizeToShow: function(mapper) {
|
||||||
|
if (this.get('permission') !== 'private' || (mapper && this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true
|
||||||
|
else return false
|
||||||
|
},
|
||||||
authorizePermissionChange: function(mapper) {
|
authorizePermissionChange: function(mapper) {
|
||||||
if (mapper && this.get('user_id') === mapper.get('id')) return true
|
if (mapper && this.get('user_id') === mapper.get('id')) return true
|
||||||
else return false
|
else return false
|
||||||
|
@ -149,9 +109,6 @@ const Synapse = Backbone.Model.extend({
|
||||||
|
|
||||||
return edge
|
return edge
|
||||||
},
|
},
|
||||||
savedEvent: function() {
|
|
||||||
Realtime.updateSynapse(this)
|
|
||||||
},
|
|
||||||
updateViews: function() {
|
updateViews: function() {
|
||||||
this.updateCardView()
|
this.updateCardView()
|
||||||
this.updateEdgeView()
|
this.updateEdgeView()
|
||||||
|
|
|
@ -19,34 +19,6 @@ const Topic = Backbone.Model.extend({
|
||||||
toJSON: function(options) {
|
toJSON: function(options) {
|
||||||
return _.omit(this.attributes, this.blacklist)
|
return _.omit(this.attributes, this.blacklist)
|
||||||
},
|
},
|
||||||
save: function(key, val, options) {
|
|
||||||
var attrs
|
|
||||||
|
|
||||||
// Handle both `"key", value` and `{key: value}` -style arguments.
|
|
||||||
if (key == null || typeof key === 'object') {
|
|
||||||
attrs = key
|
|
||||||
options = val
|
|
||||||
} else {
|
|
||||||
(attrs = {})[key] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
var newOptions = options || {}
|
|
||||||
var s = newOptions.success
|
|
||||||
|
|
||||||
var permBefore = this.get('permission')
|
|
||||||
|
|
||||||
newOptions.success = function(model, response, opt) {
|
|
||||||
if (s) s(model, response, opt)
|
|
||||||
model.trigger('saved')
|
|
||||||
|
|
||||||
if (permBefore === 'private' && model.get('permission') !== 'private') {
|
|
||||||
model.trigger('noLongerPrivate')
|
|
||||||
} else if (permBefore !== 'private' && model.get('permission') === 'private') {
|
|
||||||
model.trigger('nowPrivate')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Backbone.Model.prototype.save.call(this, attrs, newOptions)
|
|
||||||
},
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
if (this.isNew()) {
|
if (this.isNew()) {
|
||||||
this.set({
|
this.set({
|
||||||
|
@ -59,23 +31,6 @@ const Topic = Backbone.Model.extend({
|
||||||
|
|
||||||
this.on('changeByOther', this.updateCardView)
|
this.on('changeByOther', this.updateCardView)
|
||||||
this.on('change', this.updateNodeView)
|
this.on('change', this.updateNodeView)
|
||||||
this.on('saved', this.savedEvent)
|
|
||||||
this.on('nowPrivate', function() {
|
|
||||||
var removeTopicData = {
|
|
||||||
mappableid: this.id
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).trigger(JIT.events.removeTopic, [removeTopicData])
|
|
||||||
})
|
|
||||||
this.on('noLongerPrivate', function() {
|
|
||||||
var newTopicData = {
|
|
||||||
mappingid: this.getMapping().id,
|
|
||||||
mappableid: this.id
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).trigger(JIT.events.newTopic, [newTopicData])
|
|
||||||
})
|
|
||||||
|
|
||||||
this.on('change:metacode_id', Filter.checkMetacodes, this)
|
this.on('change:metacode_id', Filter.checkMetacodes, this)
|
||||||
},
|
},
|
||||||
authorizeToEdit: function(mapper) {
|
authorizeToEdit: function(mapper) {
|
||||||
|
@ -88,6 +43,10 @@ const Topic = Backbone.Model.extend({
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
authorizeToShow: function(mapper) {
|
||||||
|
if (this.get('permission') !== 'private' || (mapper && this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true
|
||||||
|
else return false
|
||||||
|
},
|
||||||
authorizePermissionChange: function(mapper) {
|
authorizePermissionChange: function(mapper) {
|
||||||
if (mapper && this.get('user_id') === mapper.get('id')) return true
|
if (mapper && this.get('user_id') === mapper.get('id')) return true
|
||||||
else return false
|
else return false
|
||||||
|
@ -135,9 +94,6 @@ const Topic = Backbone.Model.extend({
|
||||||
|
|
||||||
return node
|
return node
|
||||||
},
|
},
|
||||||
savedEvent: function() {
|
|
||||||
Realtime.updateTopic(this)
|
|
||||||
},
|
|
||||||
updateViews: function() {
|
updateViews: function() {
|
||||||
var onPageWithTopicCard = Active.Map || Active.Topic
|
var onPageWithTopicCard = Active.Map || Active.Topic
|
||||||
var node = this.get('node')
|
var node = this.get('node')
|
||||||
|
|
|
@ -36,12 +36,6 @@ const JIT = {
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
topicDrag: 'Metamaps:JIT:events:topicDrag',
|
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',
|
pan: 'Metamaps:JIT:events:pan',
|
||||||
zoom: 'Metamaps:JIT:events:zoom',
|
zoom: 'Metamaps:JIT:events:zoom',
|
||||||
animationDone: 'Metamaps:JIT:events:animationDone'
|
animationDone: 'Metamaps:JIT:events:animationDone'
|
||||||
|
|
|
@ -12,19 +12,9 @@ module.exports = {
|
||||||
LEAVE_CALL: 'LEAVE_CALL',
|
LEAVE_CALL: 'LEAVE_CALL',
|
||||||
SEND_MAPPER_INFO: 'SEND_MAPPER_INFO',
|
SEND_MAPPER_INFO: 'SEND_MAPPER_INFO',
|
||||||
SEND_COORDS: 'SEND_COORDS',
|
SEND_COORDS: 'SEND_COORDS',
|
||||||
CREATE_MESSAGE: 'CREATE_MESSAGE',
|
|
||||||
DRAG_TOPIC: 'DRAG_TOPIC',
|
DRAG_TOPIC: 'DRAG_TOPIC',
|
||||||
CREATE_TOPIC: 'CREATE_TOPIC',
|
|
||||||
UPDATE_TOPIC: 'UPDATE_TOPIC',
|
|
||||||
REMOVE_TOPIC: 'REMOVE_TOPIC',
|
|
||||||
DELETE_TOPIC: 'DELETE_TOPIC',
|
|
||||||
CREATE_SYNAPSE: 'CREATE_SYNAPSE',
|
|
||||||
UPDATE_SYNAPSE: 'UPDATE_SYNAPSE',
|
|
||||||
REMOVE_SYNAPSE: 'REMOVE_SYNAPSE',
|
|
||||||
DELETE_SYNAPSE: 'DELETE_SYNAPSE',
|
|
||||||
UPDATE_MAP: 'UPDATE_MAP',
|
|
||||||
|
|
||||||
/* EVENTS RECEIVABLE */
|
/* EVENTS RECEIVABLE FROM NODE SERVER*/
|
||||||
JUNTO_UPDATED: 'JUNTO_UPDATED',
|
JUNTO_UPDATED: 'JUNTO_UPDATED',
|
||||||
INVITED_TO_CALL: 'INVITED_TO_CALL',
|
INVITED_TO_CALL: 'INVITED_TO_CALL',
|
||||||
INVITED_TO_JOIN: 'INVITED_TO_JOIN',
|
INVITED_TO_JOIN: 'INVITED_TO_JOIN',
|
||||||
|
@ -38,16 +28,6 @@ module.exports = {
|
||||||
MAPPER_LIST_UPDATED: 'MAPPER_LIST_UPDATED',
|
MAPPER_LIST_UPDATED: 'MAPPER_LIST_UPDATED',
|
||||||
NEW_MAPPER: 'NEW_MAPPER',
|
NEW_MAPPER: 'NEW_MAPPER',
|
||||||
LOST_MAPPER: 'LOST_MAPPER',
|
LOST_MAPPER: 'LOST_MAPPER',
|
||||||
MESSAGE_CREATED: 'MESSAGE_CREATED',
|
|
||||||
TOPIC_DRAGGED: 'TOPIC_DRAGGED',
|
TOPIC_DRAGGED: 'TOPIC_DRAGGED',
|
||||||
TOPIC_CREATED: 'TOPIC_CREATED',
|
|
||||||
TOPIC_UPDATED: 'TOPIC_UPDATED',
|
|
||||||
TOPIC_REMOVED: 'TOPIC_REMOVED',
|
|
||||||
TOPIC_DELETED: 'TOPIC_DELETED',
|
|
||||||
SYNAPSE_CREATED: 'SYNAPSE_CREATED',
|
|
||||||
SYNAPSE_UPDATED: 'SYNAPSE_UPDATED',
|
|
||||||
SYNAPSE_REMOVED: 'SYNAPSE_REMOVED',
|
|
||||||
SYNAPSE_DELETED: 'SYNAPSE_DELETED',
|
|
||||||
PEER_COORDS_UPDATED: 'PEER_COORDS_UPDATED',
|
PEER_COORDS_UPDATED: 'PEER_COORDS_UPDATED',
|
||||||
MAP_UPDATED: 'MAP_UPDATED'
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import SimpleWebRTC from 'simplewebrtc'
|
||||||
import SocketIoConnection from 'simplewebrtc/socketioconnection'
|
import SocketIoConnection from 'simplewebrtc/socketioconnection'
|
||||||
|
|
||||||
import Active from '../Active'
|
import Active from '../Active'
|
||||||
|
import Cable from '../Cable'
|
||||||
import DataModel from '../DataModel'
|
import DataModel from '../DataModel'
|
||||||
import JIT from '../JIT'
|
import JIT from '../JIT'
|
||||||
import Util from '../Util'
|
import Util from '../Util'
|
||||||
|
@ -25,18 +26,8 @@ import {
|
||||||
MAPPER_LEFT_CALL,
|
MAPPER_LEFT_CALL,
|
||||||
NEW_MAPPER,
|
NEW_MAPPER,
|
||||||
LOST_MAPPER,
|
LOST_MAPPER,
|
||||||
MESSAGE_CREATED,
|
|
||||||
TOPIC_DRAGGED,
|
|
||||||
TOPIC_CREATED,
|
|
||||||
TOPIC_UPDATED,
|
|
||||||
TOPIC_REMOVED,
|
|
||||||
TOPIC_DELETED,
|
|
||||||
SYNAPSE_CREATED,
|
|
||||||
SYNAPSE_UPDATED,
|
|
||||||
SYNAPSE_REMOVED,
|
|
||||||
SYNAPSE_DELETED,
|
|
||||||
PEER_COORDS_UPDATED,
|
PEER_COORDS_UPDATED,
|
||||||
MAP_UPDATED
|
TOPIC_DRAGGED
|
||||||
} from './events'
|
} from './events'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -54,17 +45,7 @@ import {
|
||||||
peerCoordsUpdated,
|
peerCoordsUpdated,
|
||||||
newMapper,
|
newMapper,
|
||||||
lostMapper,
|
lostMapper,
|
||||||
messageCreated,
|
topicDragged
|
||||||
topicDragged,
|
|
||||||
topicCreated,
|
|
||||||
topicUpdated,
|
|
||||||
topicRemoved,
|
|
||||||
topicDeleted,
|
|
||||||
synapseCreated,
|
|
||||||
synapseUpdated,
|
|
||||||
synapseRemoved,
|
|
||||||
synapseDeleted,
|
|
||||||
mapUpdated
|
|
||||||
} from './receivable'
|
} from './receivable'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -80,17 +61,7 @@ import {
|
||||||
leaveCall,
|
leaveCall,
|
||||||
sendCoords,
|
sendCoords,
|
||||||
sendMapperInfo,
|
sendMapperInfo,
|
||||||
createMessage,
|
dragTopic
|
||||||
dragTopic,
|
|
||||||
createTopic,
|
|
||||||
updateTopic,
|
|
||||||
removeTopic,
|
|
||||||
deleteTopic,
|
|
||||||
createSynapse,
|
|
||||||
updateSynapse,
|
|
||||||
removeSynapse,
|
|
||||||
deleteSynapse,
|
|
||||||
updateMap
|
|
||||||
} from './sendable'
|
} from './sendable'
|
||||||
|
|
||||||
let Realtime = {
|
let Realtime = {
|
||||||
|
@ -123,11 +94,12 @@ let Realtime = {
|
||||||
|
|
||||||
self.socket.on('connect', function() {
|
self.socket.on('connect', function() {
|
||||||
console.log('connected')
|
console.log('connected')
|
||||||
|
if (Active.Map && Active.Mapper && Active.Map.authorizeToEdit(Active.Mapper)) {
|
||||||
|
self.checkForCall()
|
||||||
|
self.joinMap()
|
||||||
|
}
|
||||||
subscribeToEvents(self, self.socket)
|
subscribeToEvents(self, self.socket)
|
||||||
|
self.disconnected = false
|
||||||
if (!self.disconnected) {
|
|
||||||
self.startActiveMap()
|
|
||||||
} else self.disconnected = false
|
|
||||||
})
|
})
|
||||||
self.socket.on('disconnect', function() {
|
self.socket.on('disconnect', function() {
|
||||||
self.disconnected = true
|
self.disconnected = true
|
||||||
|
@ -180,6 +152,8 @@ let Realtime = {
|
||||||
config: { DOUBLE_CLICK_TOLERANCE: 200 }
|
config: { DOUBLE_CLICK_TOLERANCE: 200 }
|
||||||
})
|
})
|
||||||
self.room.videoAdded(self.handleVideoAdded)
|
self.room.videoAdded(self.handleVideoAdded)
|
||||||
|
|
||||||
|
self.startActiveMap()
|
||||||
} // if Active.Mapper
|
} // if Active.Mapper
|
||||||
},
|
},
|
||||||
addJuntoListeners: function() {
|
addJuntoListeners: function() {
|
||||||
|
@ -213,10 +187,11 @@ let Realtime = {
|
||||||
if (Active.Map && Active.Mapper) {
|
if (Active.Map && Active.Mapper) {
|
||||||
if (Active.Map.authorizeToEdit(Active.Mapper)) {
|
if (Active.Map.authorizeToEdit(Active.Mapper)) {
|
||||||
self.turnOn()
|
self.turnOn()
|
||||||
self.setupSocket()
|
self.checkForCall()
|
||||||
self.setupLocalSendables()
|
self.joinMap()
|
||||||
}
|
}
|
||||||
self.setupChat() // chat can happen on public maps too
|
self.setupChat() // chat can happen on public maps too
|
||||||
|
Cable.subscribeToMap(Active.Map.id) // people with edit rights can still see live updates
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
endActiveMap: function() {
|
endActiveMap: function() {
|
||||||
|
@ -230,6 +205,7 @@ let Realtime = {
|
||||||
ChatView.hide()
|
ChatView.hide()
|
||||||
ChatView.close()
|
ChatView.close()
|
||||||
ChatView.reset()
|
ChatView.reset()
|
||||||
|
Cable.unsubscribeFromMap()
|
||||||
},
|
},
|
||||||
turnOn: function(notify) {
|
turnOn: function(notify) {
|
||||||
var self = Realtime
|
var self = Realtime
|
||||||
|
@ -246,6 +222,7 @@ let Realtime = {
|
||||||
self.localVideo.view.$container.find('.video-cutoff').css({
|
self.localVideo.view.$container.find('.video-cutoff').css({
|
||||||
border: '4px solid ' + self.activeMapper.color
|
border: '4px solid ' + self.activeMapper.color
|
||||||
})
|
})
|
||||||
|
self.setupLocalEvents()
|
||||||
},
|
},
|
||||||
setupChat: function() {
|
setupChat: function() {
|
||||||
const self = Realtime
|
const self = Realtime
|
||||||
|
@ -254,79 +231,22 @@ let Realtime = {
|
||||||
ChatView.addMessages(new DataModel.MessageCollection(DataModel.Messages), true)
|
ChatView.addMessages(new DataModel.MessageCollection(DataModel.Messages), true)
|
||||||
ChatView.show()
|
ChatView.show()
|
||||||
},
|
},
|
||||||
setupSocket: function() {
|
setupLocalEvents: function() {
|
||||||
var self = Realtime
|
var self = Realtime
|
||||||
self.checkForCall()
|
|
||||||
self.joinMap()
|
|
||||||
},
|
|
||||||
setupLocalSendables: function() {
|
|
||||||
var self = Realtime
|
|
||||||
|
|
||||||
// local event listeners that trigger events
|
// local event listeners that trigger events
|
||||||
var sendCoords = function(event) {
|
$(document).on(JIT.events.zoom + '.map', self.positionPeerIcons)
|
||||||
|
$(document).on(JIT.events.pan + '.map', self.positionPeerIcons)
|
||||||
|
$(document).on('mousemove.map', function(event) {
|
||||||
var pixels = {
|
var pixels = {
|
||||||
x: event.pageX,
|
x: event.pageX,
|
||||||
y: event.pageY
|
y: event.pageY
|
||||||
}
|
}
|
||||||
var coords = Util.pixelsToCoords(Visualize.mGraph, pixels)
|
var coords = Util.pixelsToCoords(Visualize.mGraph, pixels)
|
||||||
self.sendCoords(coords)
|
self.sendCoords(coords)
|
||||||
}
|
})
|
||||||
$(document).on('mousemove.map', sendCoords)
|
$(document).on(JIT.events.topicDrag + '.map', function(event, positions) {
|
||||||
|
|
||||||
var zoom = function(event, e) {
|
|
||||||
if (e) {
|
|
||||||
var pixels = {
|
|
||||||
x: e.pageX,
|
|
||||||
y: e.pageY
|
|
||||||
}
|
|
||||||
var coords = Util.pixelsToCoords(Visualize.mGraph, pixels)
|
|
||||||
self.sendCoords(coords)
|
|
||||||
}
|
|
||||||
self.positionPeerIcons()
|
|
||||||
}
|
|
||||||
$(document).on(JIT.events.zoom + '.map', zoom)
|
|
||||||
|
|
||||||
$(document).on(JIT.events.pan + '.map', self.positionPeerIcons)
|
|
||||||
|
|
||||||
var dragTopic = function(event, positions) {
|
|
||||||
self.dragTopic(positions)
|
self.dragTopic(positions)
|
||||||
}
|
})
|
||||||
$(document).on(JIT.events.topicDrag + '.map', dragTopic)
|
|
||||||
|
|
||||||
var createTopic = function(event, data) {
|
|
||||||
self.createTopic(data)
|
|
||||||
}
|
|
||||||
$(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)
|
|
||||||
}
|
|
||||||
$(document).on(JIT.events.removeTopic + '.map', removeTopic)
|
|
||||||
|
|
||||||
var createSynapse = function(event, data) {
|
|
||||||
self.createSynapse(data)
|
|
||||||
}
|
|
||||||
$(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)
|
|
||||||
}
|
|
||||||
$(document).on(JIT.events.removeSynapse + '.map', removeSynapse)
|
|
||||||
|
|
||||||
var createMessage = function(event, data) {
|
|
||||||
self.createMessage(data)
|
|
||||||
}
|
|
||||||
$(document).on(ChatView.events.newMessage + '.map', createMessage)
|
|
||||||
},
|
},
|
||||||
countOthersInConversation: function() {
|
countOthersInConversation: function() {
|
||||||
var self = Realtime
|
var self = Realtime
|
||||||
|
@ -489,17 +409,7 @@ const sendables = [
|
||||||
['leaveCall', leaveCall],
|
['leaveCall', leaveCall],
|
||||||
['sendMapperInfo', sendMapperInfo],
|
['sendMapperInfo', sendMapperInfo],
|
||||||
['sendCoords', sendCoords],
|
['sendCoords', sendCoords],
|
||||||
['createMessage', createMessage],
|
['dragTopic', dragTopic]
|
||||||
['dragTopic', dragTopic],
|
|
||||||
['createTopic', createTopic],
|
|
||||||
['updateTopic', updateTopic],
|
|
||||||
['removeTopic', removeTopic],
|
|
||||||
['deleteTopic', deleteTopic],
|
|
||||||
['createSynapse', createSynapse],
|
|
||||||
['updateSynapse', updateSynapse],
|
|
||||||
['removeSynapse', removeSynapse],
|
|
||||||
['deleteSynapse', deleteSynapse],
|
|
||||||
['updateMap', updateMap]
|
|
||||||
]
|
]
|
||||||
sendables.forEach(sendable => {
|
sendables.forEach(sendable => {
|
||||||
Realtime[sendable[0]] = sendable[1](Realtime)
|
Realtime[sendable[0]] = sendable[1](Realtime)
|
||||||
|
@ -520,17 +430,7 @@ const subscribeToEvents = (Realtime, socket) => {
|
||||||
socket.on(PEER_COORDS_UPDATED, peerCoordsUpdated(Realtime))
|
socket.on(PEER_COORDS_UPDATED, peerCoordsUpdated(Realtime))
|
||||||
socket.on(NEW_MAPPER, newMapper(Realtime))
|
socket.on(NEW_MAPPER, newMapper(Realtime))
|
||||||
socket.on(LOST_MAPPER, lostMapper(Realtime))
|
socket.on(LOST_MAPPER, lostMapper(Realtime))
|
||||||
socket.on(MESSAGE_CREATED, messageCreated(Realtime))
|
|
||||||
socket.on(TOPIC_DRAGGED, topicDragged(Realtime))
|
socket.on(TOPIC_DRAGGED, topicDragged(Realtime))
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Realtime
|
export default Realtime
|
||||||
|
|
|
@ -13,7 +13,6 @@ import { ChatView } from '../Views'
|
||||||
import DataModel from '../DataModel'
|
import DataModel from '../DataModel'
|
||||||
import GlobalUI from '../GlobalUI'
|
import GlobalUI from '../GlobalUI'
|
||||||
import Control from '../Control'
|
import Control from '../Control'
|
||||||
import Map from '../Map'
|
|
||||||
import Mapper from '../Mapper'
|
import Mapper from '../Mapper'
|
||||||
import Topic from '../Topic'
|
import Topic from '../Topic'
|
||||||
import Synapse from '../Synapse'
|
import Synapse from '../Synapse'
|
||||||
|
@ -25,188 +24,8 @@ export const juntoUpdated = self => state => {
|
||||||
$(document).trigger(JUNTO_UPDATED)
|
$(document).trigger(JUNTO_UPDATED)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const synapseRemoved = self => data => {
|
/* All the following events are received through the nodejs realtime server
|
||||||
var synapse = DataModel.Synapses.get(data.mappableid)
|
and are done this way because they are transient data, not persisted to the server */
|
||||||
if (synapse) {
|
|
||||||
var edge = synapse.get('edge')
|
|
||||||
var mapping = synapse.getMapping()
|
|
||||||
if (edge.getData('mappings').length - 1 === 0) {
|
|
||||||
Control.hideEdge(edge)
|
|
||||||
}
|
|
||||||
|
|
||||||
var index = indexOf(edge.getData('synapses'), synapse)
|
|
||||||
edge.getData('mappings').splice(index, 1)
|
|
||||||
edge.getData('synapses').splice(index, 1)
|
|
||||||
if (edge.getData('displayIndex')) {
|
|
||||||
delete edge.data.$displayIndex
|
|
||||||
}
|
|
||||||
DataModel.Synapses.remove(synapse)
|
|
||||||
DataModel.Mappings.remove(mapping)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const synapseDeleted = self => data => {
|
|
||||||
synapseRemoved(self)(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const synapseCreated = self => data => {
|
|
||||||
var topic1, topic2, node1, node2, synapse, mapping, cancel, mapper
|
|
||||||
|
|
||||||
function waitThenRenderSynapse() {
|
|
||||||
if (synapse && mapping && mapper) {
|
|
||||||
topic1 = synapse.getTopic1()
|
|
||||||
node1 = topic1.get('node')
|
|
||||||
topic2 = synapse.getTopic2()
|
|
||||||
node2 = topic2.get('node')
|
|
||||||
|
|
||||||
Synapse.renderSynapse(mapping, synapse, node1, node2, false)
|
|
||||||
} else if (!cancel) {
|
|
||||||
setTimeout(waitThenRenderSynapse, 10)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mapper = DataModel.Mappers.get(data.mapperid)
|
|
||||||
if (mapper === undefined) {
|
|
||||||
Mapper.get(data.mapperid, function(m) {
|
|
||||||
DataModel.Mappers.add(m)
|
|
||||||
mapper = m
|
|
||||||
})
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
url: '/synapses/' + data.mappableid + '.json',
|
|
||||||
success: function(response) {
|
|
||||||
DataModel.Synapses.add(response)
|
|
||||||
synapse = DataModel.Synapses.get(response.id)
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
cancel = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$.ajax({
|
|
||||||
url: '/mappings/' + data.mappingid + '.json',
|
|
||||||
success: function(response) {
|
|
||||||
DataModel.Mappings.add(response)
|
|
||||||
mapping = DataModel.Mappings.get(response.id)
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
cancel = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
waitThenRenderSynapse()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const topicRemoved = self => data => {
|
|
||||||
var topic = DataModel.Topics.get(data.mappableid)
|
|
||||||
if (topic) {
|
|
||||||
var node = topic.get('node')
|
|
||||||
var mapping = topic.getMapping()
|
|
||||||
Control.hideNode(node.id)
|
|
||||||
DataModel.Topics.remove(topic)
|
|
||||||
DataModel.Mappings.remove(mapping)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const topicDeleted = self => data => {
|
|
||||||
topicRemoved(self)(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const topicCreated = self => data => {
|
|
||||||
var topic, mapping, mapper, cancel
|
|
||||||
|
|
||||||
function waitThenRenderTopic() {
|
|
||||||
if (topic && mapping && mapper) {
|
|
||||||
Topic.renderTopic(mapping, topic, false, false)
|
|
||||||
} else if (!cancel) {
|
|
||||||
setTimeout(waitThenRenderTopic, 10)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mapper = DataModel.Mappers.get(data.mapperid)
|
|
||||||
if (mapper === undefined) {
|
|
||||||
Mapper.get(data.mapperid, function(m) {
|
|
||||||
DataModel.Mappers.add(m)
|
|
||||||
mapper = m
|
|
||||||
})
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
url: '/topics/' + data.mappableid + '.json',
|
|
||||||
success: function(response) {
|
|
||||||
DataModel.Topics.add(response)
|
|
||||||
topic = DataModel.Topics.get(response.id)
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
cancel = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$.ajax({
|
|
||||||
url: '/mappings/' + data.mappingid + '.json',
|
|
||||||
success: function(response) {
|
|
||||||
DataModel.Mappings.add(response)
|
|
||||||
mapping = DataModel.Mappings.get(response.id)
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
cancel = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
waitThenRenderTopic()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const messageCreated = self => data => {
|
|
||||||
ChatView.addMessages(new DataModel.MessageCollection(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const mapUpdated = self => data => {
|
|
||||||
var map = Active.Map
|
|
||||||
var isActiveMap = map && data.mapId === map.id
|
|
||||||
if (isActiveMap) {
|
|
||||||
var couldEditBefore = map.authorizeToEdit(Active.Mapper)
|
|
||||||
var idBefore = map.id
|
|
||||||
map.fetch({
|
|
||||||
success: function(model, response) {
|
|
||||||
var idNow = model.id
|
|
||||||
var canEditNow = model.authorizeToEdit(Active.Mapper)
|
|
||||||
if (idNow !== idBefore) {
|
|
||||||
Map.leavePrivateMap() // this means the map has been changed to private
|
|
||||||
} else if (couldEditBefore && !canEditNow) {
|
|
||||||
Map.cantEditNow()
|
|
||||||
} else if (!couldEditBefore && canEditNow) {
|
|
||||||
Map.canEditNow()
|
|
||||||
} else {
|
|
||||||
model.trigger('changeByOther')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const topicUpdated = self => data => {
|
|
||||||
var topic = DataModel.Topics.get(data.topicId)
|
|
||||||
if (topic) {
|
|
||||||
var node = topic.get('node')
|
|
||||||
topic.fetch({
|
|
||||||
success: function(model) {
|
|
||||||
model.set({ node: node })
|
|
||||||
model.trigger('changeByOther')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const synapseUpdated = self => data => {
|
|
||||||
var synapse = DataModel.Synapses.get(data.synapseId)
|
|
||||||
if (synapse) {
|
|
||||||
// edge reset necessary because fetch causes model reset
|
|
||||||
var edge = synapse.get('edge')
|
|
||||||
synapse.fetch({
|
|
||||||
success: function(model) {
|
|
||||||
model.set({ edge: edge })
|
|
||||||
model.trigger('changeByOther')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const topicDragged = self => positions => {
|
export const topicDragged = self => positions => {
|
||||||
var topic
|
var topic
|
||||||
var node
|
var node
|
||||||
|
|
|
@ -17,17 +17,7 @@ import {
|
||||||
LEAVE_CALL,
|
LEAVE_CALL,
|
||||||
SEND_MAPPER_INFO,
|
SEND_MAPPER_INFO,
|
||||||
SEND_COORDS,
|
SEND_COORDS,
|
||||||
CREATE_MESSAGE,
|
DRAG_TOPIC
|
||||||
DRAG_TOPIC,
|
|
||||||
CREATE_TOPIC,
|
|
||||||
UPDATE_TOPIC,
|
|
||||||
REMOVE_TOPIC,
|
|
||||||
DELETE_TOPIC,
|
|
||||||
CREATE_SYNAPSE,
|
|
||||||
UPDATE_SYNAPSE,
|
|
||||||
REMOVE_SYNAPSE,
|
|
||||||
DELETE_SYNAPSE,
|
|
||||||
UPDATE_MAP
|
|
||||||
} from './events'
|
} from './events'
|
||||||
|
|
||||||
export const joinMap = self => () => {
|
export const joinMap = self => () => {
|
||||||
|
@ -158,7 +148,7 @@ export const inviteToJoin = self => userid => {
|
||||||
export const sendCoords = self => coords => {
|
export const sendCoords = self => coords => {
|
||||||
var map = Active.Map
|
var map = Active.Map
|
||||||
var mapper = Active.Mapper
|
var mapper = Active.Mapper
|
||||||
if (map.authorizeToEdit(mapper)) {
|
if (map && map.authorizeToEdit(mapper)) {
|
||||||
var update = {
|
var update = {
|
||||||
usercoords: coords,
|
usercoords: coords,
|
||||||
userid: Active.Mapper.id,
|
userid: Active.Mapper.id,
|
||||||
|
@ -175,72 +165,3 @@ export const dragTopic = self => positions => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateTopic = self => topic => {
|
|
||||||
var data = {
|
|
||||||
topicId: topic.id
|
|
||||||
}
|
|
||||||
self.socket.emit(UPDATE_TOPIC, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const updateSynapse = self => synapse => {
|
|
||||||
var data = {
|
|
||||||
synapseId: synapse.id
|
|
||||||
}
|
|
||||||
self.socket.emit(UPDATE_SYNAPSE, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const updateMap = self => map => {
|
|
||||||
var data = {
|
|
||||||
mapId: map.id
|
|
||||||
}
|
|
||||||
self.socket.emit(UPDATE_MAP, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createMessage = self => data => {
|
|
||||||
var message = data.attributes
|
|
||||||
message.mapid = Active.Map.id
|
|
||||||
self.socket.emit(CREATE_MESSAGE, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createTopic = self => data => {
|
|
||||||
if (Active.Map) {
|
|
||||||
data.mapperid = Active.Mapper.id
|
|
||||||
data.mapid = Active.Map.id
|
|
||||||
self.socket.emit(CREATE_TOPIC, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const deleteTopic = self => data => {
|
|
||||||
if (Active.Map) {
|
|
||||||
self.socket.emit(DELETE_TOPIC, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const removeTopic = self => data => {
|
|
||||||
if (Active.Map) {
|
|
||||||
data.mapid = Active.Map.id
|
|
||||||
self.socket.emit(REMOVE_TOPIC, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createSynapse = self => data => {
|
|
||||||
if (Active.Map) {
|
|
||||||
data.mapperid = Active.Mapper.id
|
|
||||||
data.mapid = Active.Map.id
|
|
||||||
self.socket.emit(CREATE_SYNAPSE, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const deleteSynapse = self => data => {
|
|
||||||
if (Active.Map) {
|
|
||||||
data.mapid = Active.Map.id
|
|
||||||
self.socket.emit(DELETE_SYNAPSE, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const removeSynapse = self => data => {
|
|
||||||
if (Active.Map) {
|
|
||||||
data.mapid = Active.Map.id
|
|
||||||
self.socket.emit(REMOVE_SYNAPSE, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -40,18 +40,12 @@ const Synapse = {
|
||||||
|
|
||||||
Control.selectEdge(edgeOnViz)
|
Control.selectEdge(edgeOnViz)
|
||||||
|
|
||||||
var mappingSuccessCallback = function(mappingModel, response) {
|
|
||||||
var newSynapseData = {
|
|
||||||
mappingid: mappingModel.id,
|
|
||||||
mappableid: mappingModel.get('mappable_id')
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).trigger(JIT.events.newSynapse, [newSynapseData])
|
|
||||||
}
|
|
||||||
var synapseSuccessCallback = function(synapseModel, response) {
|
var synapseSuccessCallback = function(synapseModel, response) {
|
||||||
if (Active.Map) {
|
if (Active.Map) {
|
||||||
mapping.save({ mappable_id: synapseModel.id }, {
|
mapping.save({ mappable_id: synapseModel.id }, {
|
||||||
success: mappingSuccessCallback
|
error: function(model, response) {
|
||||||
|
console.log('error saving mapping to database')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +60,9 @@ const Synapse = {
|
||||||
})
|
})
|
||||||
} else if (!synapse.isNew() && Active.Map) {
|
} else if (!synapse.isNew() && Active.Map) {
|
||||||
mapping.save(null, {
|
mapping.save(null, {
|
||||||
success: mappingSuccessCallback
|
error: function(model, response) {
|
||||||
|
console.log('error saving mapping to database')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,12 +242,6 @@ const Topic = {
|
||||||
}
|
}
|
||||||
|
|
||||||
var mappingSuccessCallback = function(mappingModel, response, topicModel) {
|
var mappingSuccessCallback = function(mappingModel, response, topicModel) {
|
||||||
var newTopicData = {
|
|
||||||
mappingid: mappingModel.id,
|
|
||||||
mappableid: mappingModel.get('mappable_id')
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).trigger(JIT.events.newTopic, [newTopicData])
|
|
||||||
// call a success callback if provided
|
// call a success callback if provided
|
||||||
if (opts.success) {
|
if (opts.success) {
|
||||||
opts.success(topicModel)
|
opts.success(topicModel)
|
||||||
|
|
|
@ -120,10 +120,10 @@ const ChatView = {
|
||||||
ChatView.render()
|
ChatView.render()
|
||||||
},
|
},
|
||||||
close: () => {
|
close: () => {
|
||||||
ChatView.mapChat.close()
|
ChatView.mapChat && ChatView.mapChat.close()
|
||||||
},
|
},
|
||||||
open: () => {
|
open: () => {
|
||||||
ChatView.mapChat.open()
|
ChatView.mapChat && ChatView.mapChat.open()
|
||||||
},
|
},
|
||||||
videoToggleClick: function() {
|
videoToggleClick: function() {
|
||||||
ChatView.videosShowing = !ChatView.videosShowing
|
ChatView.videosShowing = !ChatView.videosShowing
|
||||||
|
@ -161,7 +161,6 @@ const ChatView = {
|
||||||
m.save(null, {
|
m.save(null, {
|
||||||
success: function(model, response) {
|
success: function(model, response) {
|
||||||
self.addMessages(new DataModel.MessageCollection(model), false, true)
|
self.addMessages(new DataModel.MessageCollection(model), false, true)
|
||||||
$(document).trigger(ChatView.events.newMessage, [model])
|
|
||||||
},
|
},
|
||||||
error: function(model, response) {
|
error: function(model, response) {
|
||||||
console.log('error!', response)
|
console.log('error!', response)
|
||||||
|
@ -177,9 +176,9 @@ const ChatView = {
|
||||||
messages.models.forEach(m => ChatView.addMessage(m, isInitial, wasMe))
|
messages.models.forEach(m => ChatView.addMessage(m, isInitial, wasMe))
|
||||||
},
|
},
|
||||||
reset: () => {
|
reset: () => {
|
||||||
ChatView.mapChat.reset()
|
ChatView.mapChat && ChatView.mapChat.reset()
|
||||||
ChatView.participants.reset()
|
ChatView.participants && ChatView.participants.reset()
|
||||||
ChatView.messages.reset()
|
ChatView.messages && ChatView.messages.reset()
|
||||||
ChatView.render()
|
ChatView.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +196,6 @@ const ChatView = {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
ChatView.events = {
|
ChatView.events = {
|
||||||
newMessage: 'ChatView:newMessage',
|
|
||||||
openTray: 'ChatView:openTray',
|
openTray: 'ChatView:openTray',
|
||||||
closeTray: 'ChatView:closeTray',
|
closeTray: 'ChatView:closeTray',
|
||||||
inputFocus: 'ChatView:inputFocus',
|
inputFocus: 'ChatView:inputFocus',
|
||||||
|
|
|
@ -2,9 +2,10 @@ import Account from './Account'
|
||||||
import Active from './Active'
|
import Active from './Active'
|
||||||
import Admin from './Admin'
|
import Admin from './Admin'
|
||||||
import AutoLayout from './AutoLayout'
|
import AutoLayout from './AutoLayout'
|
||||||
import DataModel from './DataModel'
|
import Cable from './Cable'
|
||||||
import Control from './Control'
|
import Control from './Control'
|
||||||
import Create from './Create'
|
import Create from './Create'
|
||||||
|
import DataModel from './DataModel'
|
||||||
import Debug from './Debug'
|
import Debug from './Debug'
|
||||||
import Filter from './Filter'
|
import Filter from './Filter'
|
||||||
import GlobalUI, {
|
import GlobalUI, {
|
||||||
|
@ -38,9 +39,10 @@ Metamaps.Account = Account
|
||||||
Metamaps.Active = Active
|
Metamaps.Active = Active
|
||||||
Metamaps.Admin = Admin
|
Metamaps.Admin = Admin
|
||||||
Metamaps.AutoLayout = AutoLayout
|
Metamaps.AutoLayout = AutoLayout
|
||||||
Metamaps.DataModel = DataModel
|
Metamaps.Cable = Cable
|
||||||
Metamaps.Control = Control
|
Metamaps.Control = Control
|
||||||
Metamaps.Create = Create
|
Metamaps.Create = Create
|
||||||
|
Metamaps.DataModel = DataModel
|
||||||
Metamaps.Debug = Debug
|
Metamaps.Debug = Debug
|
||||||
Metamaps.Filter = Filter
|
Metamaps.Filter = Filter
|
||||||
Metamaps.GlobalUI = GlobalUI
|
Metamaps.GlobalUI = GlobalUI
|
||||||
|
|
|
@ -1,22 +1,12 @@
|
||||||
const {
|
const {
|
||||||
// server sendable, client receivable
|
// server sendable, client receivable
|
||||||
TOPIC_UPDATED,
|
|
||||||
TOPIC_DELETED,
|
|
||||||
SYNAPSE_UPDATED,
|
|
||||||
SYNAPSE_DELETED,
|
|
||||||
MAP_UPDATED,
|
|
||||||
JUNTO_UPDATED,
|
JUNTO_UPDATED,
|
||||||
|
|
||||||
// server receivable, client sendable
|
// server receivable, client sendable
|
||||||
JOIN_CALL,
|
JOIN_CALL,
|
||||||
LEAVE_CALL,
|
LEAVE_CALL,
|
||||||
JOIN_MAP,
|
JOIN_MAP,
|
||||||
LEAVE_MAP,
|
LEAVE_MAP
|
||||||
UPDATE_TOPIC,
|
|
||||||
DELETE_TOPIC,
|
|
||||||
UPDATE_SYNAPSE,
|
|
||||||
DELETE_SYNAPSE,
|
|
||||||
UPDATE_MAP
|
|
||||||
} = require('../frontend/src/Metamaps/Realtime/events')
|
} = require('../frontend/src/Metamaps/Realtime/events')
|
||||||
|
|
||||||
module.exports = function(io, store) {
|
module.exports = function(io, store) {
|
||||||
|
@ -33,25 +23,5 @@ module.exports = function(io, store) {
|
||||||
socket.on(JOIN_CALL, data => store.dispatch({ type: JOIN_CALL, payload: data }))
|
socket.on(JOIN_CALL, data => store.dispatch({ type: JOIN_CALL, payload: data }))
|
||||||
socket.on(LEAVE_CALL, () => store.dispatch({ type: LEAVE_CALL, payload: socket }))
|
socket.on(LEAVE_CALL, () => store.dispatch({ type: LEAVE_CALL, payload: socket }))
|
||||||
socket.on('disconnect', () => store.dispatch({ type: 'DISCONNECT', payload: socket }))
|
socket.on('disconnect', () => store.dispatch({ type: 'DISCONNECT', payload: socket }))
|
||||||
|
|
||||||
socket.on(UPDATE_TOPIC, function(data) {
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,14 @@ const {
|
||||||
MAPPER_LIST_UPDATED,
|
MAPPER_LIST_UPDATED,
|
||||||
NEW_MAPPER,
|
NEW_MAPPER,
|
||||||
LOST_MAPPER,
|
LOST_MAPPER,
|
||||||
MESSAGE_CREATED,
|
|
||||||
TOPIC_DRAGGED,
|
TOPIC_DRAGGED,
|
||||||
TOPIC_CREATED,
|
|
||||||
TOPIC_REMOVED,
|
|
||||||
SYNAPSE_CREATED,
|
|
||||||
SYNAPSE_REMOVED,
|
|
||||||
PEER_COORDS_UPDATED,
|
PEER_COORDS_UPDATED,
|
||||||
|
|
||||||
JOIN_MAP,
|
JOIN_MAP,
|
||||||
LEAVE_MAP,
|
LEAVE_MAP,
|
||||||
SEND_COORDS,
|
SEND_COORDS,
|
||||||
SEND_MAPPER_INFO,
|
SEND_MAPPER_INFO,
|
||||||
CREATE_MESSAGE,
|
|
||||||
DRAG_TOPIC,
|
DRAG_TOPIC,
|
||||||
CREATE_TOPIC,
|
|
||||||
REMOVE_TOPIC,
|
|
||||||
CREATE_SYNAPSE,
|
|
||||||
REMOVE_SYNAPSE
|
|
||||||
} = require('../frontend/src/Metamaps/Realtime/events')
|
} = require('../frontend/src/Metamaps/Realtime/events')
|
||||||
|
|
||||||
const { mapRoom, userMapRoom } = require('./rooms')
|
const { mapRoom, userMapRoom } = require('./rooms')
|
||||||
|
@ -74,40 +64,11 @@ module.exports = function(io, store) {
|
||||||
socket.broadcast.in(mapRoom(data.mapid)).emit(PEER_COORDS_UPDATED, peer)
|
socket.broadcast.in(mapRoom(data.mapid)).emit(PEER_COORDS_UPDATED, peer)
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on(CREATE_MESSAGE, function(data) {
|
|
||||||
var mapId = data.mapid
|
|
||||||
delete data.mapid
|
|
||||||
socket.broadcast.in(mapRoom(mapId)).emit(MESSAGE_CREATED, data)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on(DRAG_TOPIC, function(data) {
|
socket.on(DRAG_TOPIC, function(data) {
|
||||||
var mapId = data.mapid
|
var mapId = data.mapid
|
||||||
delete data.mapid
|
delete data.mapid
|
||||||
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_DRAGGED, data)
|
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_DRAGGED, data)
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on(CREATE_TOPIC, function(data) {
|
|
||||||
var mapId = data.mapid
|
|
||||||
delete data.mapid
|
|
||||||
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_CREATED, data)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on(REMOVE_TOPIC, function(data) {
|
|
||||||
var mapId = data.mapid
|
|
||||||
delete data.mapid
|
|
||||||
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_REMOVED, data)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on(CREATE_SYNAPSE, function(data) {
|
|
||||||
var mapId = data.mapid
|
|
||||||
delete data.mapid
|
|
||||||
socket.broadcast.in(mapRoom(mapId)).emit(SYNAPSE_CREATED, data)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on(REMOVE_SYNAPSE, function(data) {
|
|
||||||
var mapId = data.mapid
|
|
||||||
delete data.mapid
|
|
||||||
socket.broadcast.in(mapRoom(mapId)).emit(SYNAPSE_REMOVED, data)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue