start streaming
This commit is contained in:
parent
68f0e91259
commit
2fe9936312
15 changed files with 146 additions and 4 deletions
1
Gemfile
1
Gemfile
|
@ -44,6 +44,7 @@ group :test do
|
|||
end
|
||||
|
||||
group :development, :test do
|
||||
gem 'puma'
|
||||
gem 'better_errors'
|
||||
gem 'binding_of_caller'
|
||||
gem 'pry-byebug'
|
||||
|
|
|
@ -167,6 +167,7 @@ GEM
|
|||
pry (~> 0.10)
|
||||
pry-rails (0.3.4)
|
||||
pry (>= 0.9.10)
|
||||
puma (2.15.3)
|
||||
pundit (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
pundit_extra (0.3.0)
|
||||
|
@ -298,6 +299,7 @@ DEPENDENCIES
|
|||
pg
|
||||
pry-byebug
|
||||
pry-rails
|
||||
puma
|
||||
pundit
|
||||
pundit_extra
|
||||
rack-attack
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
//= require jquery
|
||||
//= require jquery-ui
|
||||
//= require jquery_ujs
|
||||
//= require action_cable
|
||||
//= require_directory ./lib
|
||||
//= require ./webpacked/metamaps.bundle
|
||||
//= 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
|
20
app/channels/application_cable/connection.rb
Normal file
20
app/channels/application_cable/connection.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
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
|
||||
verified_user
|
||||
else
|
||||
reject_unauthorized_connection
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
7
app/channels/topic_channel.rb
Normal file
7
app/channels/topic_channel.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class TopicChannel < ApplicationCable::Channel
|
||||
# Called when the consumer has successfully
|
||||
# become a subscriber of this channel.
|
||||
def subscribed
|
||||
stream_from "topic_#{params[:id]}"
|
||||
end
|
||||
end
|
|
@ -22,6 +22,7 @@ class Synapse < ApplicationRecord
|
|||
where(topic1_id: topic_id).or(where(topic2_id: topic_id))
|
||||
}
|
||||
|
||||
after_create :after_created
|
||||
after_update :after_updated
|
||||
|
||||
delegate :name, to: :user, prefix: true
|
||||
|
@ -42,6 +43,35 @@ class Synapse < ApplicationRecord
|
|||
super(methods: [:user_name, :user_image, :collaborator_ids])
|
||||
end
|
||||
|
||||
def after_created
|
||||
filteredSynapse = {
|
||||
id: id,
|
||||
permission: permission,
|
||||
user_id: user_id,
|
||||
collaborator_ids: collaborator_ids
|
||||
}
|
||||
filteredTopic1 = {
|
||||
id: topic1_id,
|
||||
permission: topic1.permission,
|
||||
user_id: topic1.user_id,
|
||||
collaborator_ids: topic1.collaborator_ids
|
||||
}
|
||||
filteredTopic2 = {
|
||||
id: topic2_id,
|
||||
permission: topic2.permission,
|
||||
user_id: topic2.user_id,
|
||||
collaborator_ids: topic2.collaborator_ids
|
||||
}
|
||||
data = {
|
||||
synapse: filteredSynapse,
|
||||
topic1: filteredTopic1,
|
||||
topic2: filteredTopic2
|
||||
}
|
||||
# include the filtered topics here too
|
||||
ActionCable.server.broadcast 'topic_' + topic1_id.to_s, type: 'newSynapse', data: data
|
||||
ActionCable.server.broadcast 'topic_' + topic2_id.to_s, type: 'newSynapse', data: data
|
||||
end
|
||||
|
||||
def after_updated
|
||||
attrs = ['desc', 'category', 'permission', 'defer_to_map_id']
|
||||
if attrs.any? {|k| changed_attributes.key?(k)}
|
||||
|
|
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
|
||||
Metamaps::Application.routes.draw do
|
||||
use_doorkeeper
|
||||
mount ActionCable.server => '/cable'
|
||||
|
||||
root to: 'main#home', via: :get
|
||||
get 'request', to: 'main#requestinvite', as: :request
|
||||
|
|
50
frontend/src/Metamaps/Cable.js
Normal file
50
frontend/src/Metamaps/Cable.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* global $, ActionCable */
|
||||
|
||||
import Active from './Active'
|
||||
import DataModel from './DataModel'
|
||||
|
||||
const Cable = {
|
||||
topicSubs: {},
|
||||
init: () => {
|
||||
let self = Cable
|
||||
self.cable = ActionCable.createConsumer()
|
||||
},
|
||||
subAllTopics: () => {
|
||||
let self = Cable
|
||||
DataModel.Topics.models.forEach(topic => self.subTopic(topic.id))
|
||||
},
|
||||
subTopic: id => {
|
||||
let self = Cable
|
||||
self.topicSubs[id] = self.cable.subscriptions.create({
|
||||
channel: 'TopicChannel',
|
||||
id: id
|
||||
}, {
|
||||
received: event => self[event.type](event.data)
|
||||
})
|
||||
},
|
||||
unsubTopic: id => {
|
||||
let self = Cable
|
||||
self.topicSubs[id] && self.topicSubs[id].unsubscribe()
|
||||
delete self.topicSubs[id]
|
||||
},
|
||||
unsubAllTopics: () => {
|
||||
let self = Cable
|
||||
Object.keys(self.topicSubs).forEach(id => {
|
||||
self.topicSubs[id].unsubscribe()
|
||||
})
|
||||
self.topicSubs = {}
|
||||
},
|
||||
// begin event functions
|
||||
newSynapse: data => {
|
||||
console.log(data)
|
||||
const m = Active.Mapper
|
||||
const s = new DataModel.Synapse(data.synapse)
|
||||
const t1 = new DataModel.Topic(data.topic1)
|
||||
const t2 = new DataModel.Topic(data.topic2)
|
||||
if (t1.authorizeToShow(m) && t2.authorizeToShow(m) && s.authorizeToShow(m)) {
|
||||
console.log('authorized')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Cable
|
|
@ -87,6 +87,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
|
||||
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) {
|
||||
if (mapper && this.get('user_id') === mapper.get('id')) return true
|
||||
else return false
|
||||
|
|
|
@ -88,6 +88,10 @@ const Topic = Backbone.Model.extend({
|
|||
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) {
|
||||
if (mapper && this.get('user_id') === mapper.get('id')) return true
|
||||
else return false
|
||||
|
|
|
@ -640,14 +640,14 @@ const JIT = {
|
|||
}
|
||||
},
|
||||
// this will just be used to patch the ForceDirected graphsettings with the few things which actually differ
|
||||
background: {
|
||||
/*background: {
|
||||
levelDistance: 200,
|
||||
numberOfCircles: 4,
|
||||
CanvasStyles: {
|
||||
strokeStyle: '#333',
|
||||
lineWidth: 1.5
|
||||
}
|
||||
},
|
||||
},*/
|
||||
levelDistance: 200
|
||||
},
|
||||
onMouseEnter: function(edge) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import $jit from '../patched/JIT'
|
|||
|
||||
import Active from './Active'
|
||||
import AutoLayout from './AutoLayout'
|
||||
import Cable from './Cable'
|
||||
import Create from './Create'
|
||||
import DataModel from './DataModel'
|
||||
import Filter from './Filter'
|
||||
|
@ -43,6 +44,8 @@ const Topic = {
|
|||
DataModel.Synapses = new DataModel.SynapseCollection(data.synapses)
|
||||
DataModel.attachCollectionEvents()
|
||||
|
||||
DataModel.Topics.models.forEach(topic => Cable.subTopic(topic.id))
|
||||
|
||||
document.title = Active.Topic.get('name') + ' | Metamaps'
|
||||
|
||||
// set filter mapper H3 text
|
||||
|
@ -78,6 +81,7 @@ const Topic = {
|
|||
TopicCard.hideCard()
|
||||
SynapseCard.hideCard()
|
||||
Filter.close()
|
||||
Cable.unsubAllTopics()
|
||||
}
|
||||
},
|
||||
centerOn: function(nodeid, callback) {
|
||||
|
|
|
@ -2,9 +2,10 @@ import Account from './Account'
|
|||
import Active from './Active'
|
||||
import Admin from './Admin'
|
||||
import AutoLayout from './AutoLayout'
|
||||
import DataModel from './DataModel'
|
||||
import Cable from './Cable'
|
||||
import Control from './Control'
|
||||
import Create from './Create'
|
||||
import DataModel from './DataModel'
|
||||
import Debug from './Debug'
|
||||
import Filter from './Filter'
|
||||
import GlobalUI, {
|
||||
|
@ -38,9 +39,10 @@ Metamaps.Account = Account
|
|||
Metamaps.Active = Active
|
||||
Metamaps.Admin = Admin
|
||||
Metamaps.AutoLayout = AutoLayout
|
||||
Metamaps.DataModel = DataModel
|
||||
Metamaps.Cable = Cable
|
||||
Metamaps.Control = Control
|
||||
Metamaps.Create = Create
|
||||
Metamaps.DataModel = DataModel
|
||||
Metamaps.Debug = Debug
|
||||
Metamaps.Filter = Filter
|
||||
Metamaps.GlobalUI = GlobalUI
|
||||
|
@ -106,6 +108,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
JIT.prepareVizData()
|
||||
GlobalUI.showDiv('#infovis')
|
||||
}
|
||||
|
||||
if (Active.Topic) Cable.subAllTopics()
|
||||
})
|
||||
|
||||
export default Metamaps
|
||||
|
|
Loading…
Reference in a new issue