Compare commits
8 commits
develop
...
feature/re
Author | SHA1 | Date | |
---|---|---|---|
|
629c811f32 | ||
|
769b57cdd2 | ||
|
223d31c4f4 | ||
|
839ff66bcf | ||
|
a6bb688d0c | ||
|
24aeebedf7 | ||
|
f8e7bf6d31 | ||
|
32700d3ac1 |
30 changed files with 259 additions and 154 deletions
|
@ -5,6 +5,23 @@ module Api
|
|||
def searchable_columns
|
||||
[]
|
||||
end
|
||||
|
||||
def update
|
||||
# hack: set the user temporarily so the model hook can reference it, then set it back
|
||||
temp = resource.user
|
||||
resource.user = current_user
|
||||
update_action
|
||||
respond_with_resource
|
||||
resourse.user = temp
|
||||
update_action
|
||||
end
|
||||
|
||||
def destroy
|
||||
# this is done so that the model hooks can use the mapping user to determine who took this action
|
||||
resource.user = current_user if current_user.present? # current_user should always be present
|
||||
destroy_action
|
||||
head :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,6 @@ class MappingsController < ApplicationController
|
|||
|
||||
if @mapping.save
|
||||
render json: @mapping, status: :created
|
||||
Events::NewMapping.publish!(@mapping, current_user)
|
||||
else
|
||||
render json: @mapping.errors, status: :unprocessable_entity
|
||||
end
|
||||
|
@ -32,26 +31,27 @@ class MappingsController < ApplicationController
|
|||
def update
|
||||
@mapping = Mapping.find(params[:id])
|
||||
authorize @mapping
|
||||
# hack: set the user temporarily so that the model hook can reference it, and then set it back
|
||||
temp = @mapping.user
|
||||
@mapping.user = current_user
|
||||
@mapping.assign_attributes(mapping_params)
|
||||
|
||||
if @mapping.update_attributes(mapping_params)
|
||||
if @mapping.save
|
||||
head :no_content
|
||||
else
|
||||
render json: @mapping.errors, status: :unprocessable_entity
|
||||
end
|
||||
# restore the original mapping creator
|
||||
@mapping.user = temp
|
||||
@mapping.save
|
||||
end
|
||||
|
||||
# DELETE /mappings/1.json
|
||||
def destroy
|
||||
@mapping = Mapping.find(params[:id])
|
||||
authorize @mapping
|
||||
|
||||
mappable = @mapping.mappable
|
||||
if mappable.defer_to_map
|
||||
mappable.permission = mappable.defer_to_map.permission
|
||||
mappable.defer_to_map_id = nil
|
||||
mappable.save
|
||||
end
|
||||
|
||||
# hack: set the user temporarily so that the model hook can reference this user who is taking the action
|
||||
@mapping.user = current_user
|
||||
@mapping.destroy
|
||||
|
||||
head :no_content
|
||||
|
|
|
@ -16,6 +16,7 @@ class MapsController < ApplicationController
|
|||
@allmessages = @map.messages.sort_by(&:created_at)
|
||||
@allstars = @map.stars
|
||||
@allrequests = @map.access_requests
|
||||
@allevents = @map.events
|
||||
end
|
||||
format.json { render json: @map }
|
||||
format.csv { redirect_to action: :export, format: :csv }
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
class Event < ApplicationRecord
|
||||
KINDS = %w(user_present_on_map conversation_started_on_map topic_added_to_map synapse_added_to_map).freeze
|
||||
KINDS = %w(user_present_on_map conversation_started_on_map
|
||||
topic_added_to_map topic_moved_on_map topic_removed_from_map
|
||||
synapse_added_to_map synapse_removed_from_map
|
||||
topic_updated synapse_updated).freeze
|
||||
|
||||
# has_many :notifications, dependent: :destroy
|
||||
belongs_to :eventable, polymorphic: true
|
||||
belongs_to :map
|
||||
belongs_to :user
|
||||
|
@ -14,18 +16,12 @@ class Event < ApplicationRecord
|
|||
validates :kind, inclusion: { in: KINDS }
|
||||
validates :eventable, presence: true
|
||||
|
||||
# def notify!(user)
|
||||
# notifications.create!(user: user)
|
||||
# end
|
||||
|
||||
def belongs_to?(this_user)
|
||||
user_id == this_user.id
|
||||
end
|
||||
|
||||
def notify_webhooks!
|
||||
# group = self.discussion.group
|
||||
map.webhooks.each { |webhook| WebhookService.publish! webhook: webhook, event: self }
|
||||
# group.webhooks.each { |webhook| WebhookService.publish! webhook: webhook, event: self }
|
||||
end
|
||||
handle_asynchronously :notify_webhooks!
|
||||
end
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::NewMapping < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(mapping, user)
|
||||
create!(kind: mapping.mappable_type == 'Topic' ? 'topic_added_to_map' : 'synapse_added_to_map',
|
||||
eventable: mapping,
|
||||
map: mapping.map,
|
||||
user: user)
|
||||
end
|
||||
end
|
12
app/models/events/synapse_added_to_map.rb
Normal file
12
app/models/events/synapse_added_to_map.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::SynapseAddedToMap < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(synapse, map, user, meta)
|
||||
create!(kind: 'synapse_added_to_map',
|
||||
eventable: synapse,
|
||||
map: map,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
12
app/models/events/synapse_removed_from_map.rb
Normal file
12
app/models/events/synapse_removed_from_map.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::SynapseRemovedFromMap < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(synapse, map, user, meta)
|
||||
create!(kind: 'synapse_removed_from_map',
|
||||
eventable: synapse,
|
||||
map: map,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
11
app/models/events/synapse_updated.rb
Normal file
11
app/models/events/synapse_updated.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::SynapseUpdated < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(synapse, user, meta)
|
||||
create!(kind: 'synapse_updated',
|
||||
eventable: synapse,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
12
app/models/events/topic_added_to_map.rb
Normal file
12
app/models/events/topic_added_to_map.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::TopicAddedToMap < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(topic, map, user, meta)
|
||||
create!(kind: 'topic_added_to_map',
|
||||
eventable: topic,
|
||||
map: map,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
12
app/models/events/topic_moved_on_map.rb
Normal file
12
app/models/events/topic_moved_on_map.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::TopicMovedOnMap < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(topic, map, user, meta)
|
||||
create!(kind: 'topic_moved_on_map',
|
||||
eventable: topic,
|
||||
map: map,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
12
app/models/events/topic_removed_from_map.rb
Normal file
12
app/models/events/topic_removed_from_map.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::TopicRemovedFromMap < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(topic, map, user, meta)
|
||||
create!(kind: 'topic_removed_from_map',
|
||||
eventable: topic,
|
||||
map: map,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
11
app/models/events/topic_updated.rb
Normal file
11
app/models/events/topic_updated.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
class Events::TopicUpdated < Event
|
||||
# after_create :notify_users!
|
||||
|
||||
def self.publish!(topic, user, meta)
|
||||
create!(kind: 'topic_updated',
|
||||
eventable: topic,
|
||||
user: user,
|
||||
meta: meta)
|
||||
end
|
||||
end
|
|
@ -14,7 +14,7 @@ class Map < ApplicationRecord
|
|||
has_many :collaborators, through: :user_maps, source: :user
|
||||
|
||||
has_many :webhooks, as: :hookable
|
||||
has_many :events, -> { includes :user }, as: :eventable, dependent: :destroy
|
||||
has_many :events, -> { includes :user }, dependent: :destroy
|
||||
|
||||
# This method associates the attribute ":image" with a file attachment
|
||||
has_attached_file :screenshot,
|
||||
|
@ -95,7 +95,8 @@ class Map < ApplicationRecord
|
|||
collaborators: editors,
|
||||
messages: messages.sort_by(&:created_at),
|
||||
stars: stars,
|
||||
requests: access_requests
|
||||
requests: access_requests,
|
||||
events: events.chronologically
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@ class Mapping < ApplicationRecord
|
|||
|
||||
delegate :name, to: :user, prefix: true
|
||||
|
||||
after_create :after_created
|
||||
after_update :after_updated
|
||||
before_destroy :before_destroyed
|
||||
|
||||
def user_image
|
||||
user.image.url
|
||||
end
|
||||
|
@ -23,4 +27,35 @@ class Mapping < ApplicationRecord
|
|||
def as_json(_options = {})
|
||||
super(methods: [:user_name, :user_image])
|
||||
end
|
||||
|
||||
def after_created
|
||||
if mappable_type == 'Topic'
|
||||
meta = {'x': xloc, 'y': yloc, 'mapping_id': id}
|
||||
Events::TopicAddedToMap.publish!(mappable, map, user, meta)
|
||||
elsif mappable_type == 'Synapse'
|
||||
Events::SynapseAddedToMap.publish!(mappable, map, user, meta)
|
||||
end
|
||||
end
|
||||
|
||||
def after_updated
|
||||
if mappable_type == 'Topic' and (xloc_changed? or yloc_changed?)
|
||||
meta = {'x': xloc, 'y': yloc, 'mapping_id': id}
|
||||
Events::TopicMovedOnMap.publish!(mappable, map, user, meta)
|
||||
end
|
||||
end
|
||||
|
||||
def before_destroyed
|
||||
if mappable.defer_to_map
|
||||
mappable.permission = mappable.defer_to_map.permission
|
||||
mappable.defer_to_map_id = nil
|
||||
mappable.save
|
||||
end
|
||||
|
||||
meta = {'mapping_id': id}
|
||||
if mappable_type == 'Topic'
|
||||
Events::TopicRemovedFromMap.publish!(mappable, map, user, meta)
|
||||
elsif mappable_type == 'Synapse'
|
||||
Events::SynapseRemovedFromMap.publish!(mappable, map, user, meta)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,8 @@ class Synapse < ApplicationRecord
|
|||
where(topic1_id: topic_id).or(where(topic2_id: topic_id))
|
||||
}
|
||||
|
||||
after_update :after_updated
|
||||
|
||||
delegate :name, to: :user, prefix: true
|
||||
|
||||
def user_image
|
||||
|
@ -39,4 +41,15 @@ class Synapse < ApplicationRecord
|
|||
def as_json(_options = {})
|
||||
super(methods: [:user_name, :user_image, :collaborator_ids])
|
||||
end
|
||||
|
||||
def after_updated
|
||||
attrs = ['desc', 'category', 'permission', 'defer_to_map_id']
|
||||
if attrs.any? {|k| changed_attributes.key?(k)}
|
||||
new = self.attributes.select {|k,v| attrs.include?(k) }
|
||||
old = changed_attributes.select {|k,v| attrs.include?(k) }
|
||||
meta = new.merge(old) # we are prioritizing the old values, keeping them
|
||||
meta['changed'] = changed_attributes.keys.select {|k| attrs.include?(k) }
|
||||
Events::SynapseUpdated.publish!(self, user, meta)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ class Topic < ApplicationRecord
|
|||
belongs_to :metacode
|
||||
|
||||
before_create :create_metamap?
|
||||
after_update :after_updated
|
||||
|
||||
validates :permission, presence: true
|
||||
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
||||
|
@ -135,4 +136,15 @@ class Topic < ApplicationRecord
|
|||
self.link = Rails.application.routes.url_helpers
|
||||
.map_url(host: ENV['MAILER_DEFAULT_URL'], id: @map.id)
|
||||
end
|
||||
|
||||
def after_updated
|
||||
attrs = ['name', 'desc', 'link', 'metacode_id', 'permission', 'defer_to_map_id']
|
||||
if attrs.any? {|k| changed_attributes.key?(k)}
|
||||
new = self.attributes.select {|k,v| attrs.include?(k) }
|
||||
old = changed_attributes.select {|k,v| attrs.include?(k) }
|
||||
meta = new.merge(old) # we are prioritizing the old values, keeping them
|
||||
meta['changed'] = changed_attributes.keys.select {|k| attrs.include?(k) }
|
||||
Events::TopicUpdated.publish!(self, user, meta)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,45 +18,14 @@ Webhooks::Slack::Base = Struct.new(:webhook, :event) do
|
|||
webhook.channel
|
||||
end
|
||||
|
||||
def attachments
|
||||
[{
|
||||
title: attachment_title,
|
||||
text: attachment_text,
|
||||
fields: attachment_fields,
|
||||
fallback: attachment_fallback
|
||||
}]
|
||||
end
|
||||
|
||||
alias_method :read_attribute_for_serialization, :send
|
||||
|
||||
private
|
||||
|
||||
# def motion_vote_field
|
||||
# {
|
||||
# title: "Vote on this proposal",
|
||||
# value: "#{proposal_link(eventable, "yes")} · " +
|
||||
# "#{proposal_link(eventable, "abstain")} · " +
|
||||
# "#{proposal_link(eventable, "no")} · " +
|
||||
# "#{proposal_link(eventable, "block")}"
|
||||
# }
|
||||
# end
|
||||
|
||||
def view_map_on_metamaps(text = nil)
|
||||
"<#{map_url(event.map)}|#{text || event.map.name}>"
|
||||
end
|
||||
|
||||
# def view_discussion_on_loomio(params = {})
|
||||
# { value: discussion_link(I18n.t(:"webhooks.slack.view_it_on_loomio"), params) }
|
||||
# end
|
||||
|
||||
# def proposal_link(proposal, position = nil)
|
||||
# discussion_link position || proposal.name, { proposal: proposal.key, position: position }
|
||||
# end
|
||||
|
||||
# def discussion_link(text = nil, params = {})
|
||||
# "<#{discussion_url(eventable.map, params)}|#{text || eventable.discussion.title}>"
|
||||
# end
|
||||
|
||||
def eventable
|
||||
@eventable ||= event.eventable
|
||||
end
|
||||
|
@ -65,12 +34,3 @@ Webhooks::Slack::Base = Struct.new(:webhook, :event) do
|
|||
@author ||= eventable.author
|
||||
end
|
||||
end
|
||||
|
||||
# webhooks:
|
||||
# slack:
|
||||
# motion_closed: "*%{name}* has closed"
|
||||
# motion_closing_soon: "*%{name}* has a proposal closing in 24 hours"
|
||||
# motion_outcome_created: "*%{author}* published an outcome in *%{name}*"
|
||||
# motion_outcome_updated: "*%{author}* updated the outcome for *%{name}*"
|
||||
# new_motion: "*%{author}* started a new proposal in *%{name}*"
|
||||
# view_it_on_loomio: "View it on Loomio"
|
||||
|
|
|
@ -3,24 +3,4 @@ class Webhooks::Slack::ConversationStartedOnMap < Webhooks::Slack::Base
|
|||
def text
|
||||
"There is a live conversation starting on map *#{event.map.name}*. #{view_map_on_metamaps('Join in!')}"
|
||||
end
|
||||
# TODO: it would be sweet if it sends it with the metacode as the icon_url
|
||||
|
||||
def attachment_fallback
|
||||
'' # {}"*#{eventable.name}*\n#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_title
|
||||
'' # proposal_link(eventable)
|
||||
end
|
||||
|
||||
def attachment_text
|
||||
'' # "#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_fields
|
||||
[{
|
||||
title: 'nothing',
|
||||
value: 'nothing'
|
||||
}] # [motion_vote_field]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,25 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
class Webhooks::Slack::SynapseAddedToMap < Webhooks::Slack::Base
|
||||
def text
|
||||
"\"*#{eventable.mappable.topic1.name}* #{eventable.mappable.desc || '->'} *#{eventable.mappable.topic2.name}*\" was added as a connection to the map *#{view_map_on_metamaps}*"
|
||||
end
|
||||
|
||||
def attachment_fallback
|
||||
'' # {}"*#{eventable.name}*\n#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_title
|
||||
'' # proposal_link(eventable)
|
||||
end
|
||||
|
||||
def attachment_text
|
||||
'' # "#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_fields
|
||||
[{
|
||||
title: 'nothing',
|
||||
value: 'nothing'
|
||||
}] # [motion_vote_field]
|
||||
connector = eventable.desc.empty? ? '->' : eventable.desc
|
||||
"\"*#{eventable.topic1.name}* #{connector} *#{eventable.topic2.name}*\" was added as a connection by *#{event.user.name}* to the map *#{view_map_on_metamaps}*"
|
||||
end
|
||||
end
|
||||
|
|
8
app/models/webhooks/slack/synapse_removed_from_map.rb
Normal file
8
app/models/webhooks/slack/synapse_removed_from_map.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
class Webhooks::Slack::SynapseRemovedFromMap < Webhooks::Slack::Base
|
||||
def text
|
||||
connector = eventable.desc.empty? ? '->' : eventable.desc
|
||||
# todo express correct directionality of arrows when desc is empty
|
||||
"\"*#{eventable.topic1.name}* #{connector} *#{eventable.topic2.name}*\" was removed by *#{event.user.name}* as a connection from the map *#{view_map_on_metamaps}*"
|
||||
end
|
||||
end
|
|
@ -1,26 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
class Webhooks::Slack::TopicAddedToMap < Webhooks::Slack::Base
|
||||
def text
|
||||
"New #{eventable.mappable.metacode.name} topic *#{eventable.mappable.name}* was added to the map *#{view_map_on_metamaps}*"
|
||||
"*#{eventable.name}* was added by *#{event.user.name}* to the map *#{view_map_on_metamaps}*"
|
||||
end
|
||||
# TODO: it would be sweet if it sends it with the metacode as the icon_url
|
||||
|
||||
def attachment_fallback
|
||||
'' # {}"*#{eventable.name}*\n#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_title
|
||||
'' # proposal_link(eventable)
|
||||
end
|
||||
|
||||
def attachment_text
|
||||
'' # "#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_fields
|
||||
[{
|
||||
title: 'nothing',
|
||||
value: 'nothing'
|
||||
}] # [motion_vote_field]
|
||||
end
|
||||
end
|
||||
|
|
6
app/models/webhooks/slack/topic_moved_on_map.rb
Normal file
6
app/models/webhooks/slack/topic_moved_on_map.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
class Webhooks::Slack::TopicMovedOnMap < Webhooks::Slack::Base
|
||||
def text
|
||||
"*#{eventable.name}* was moved by *#{event.user.name}* on the map *#{view_map_on_metamaps}*"
|
||||
end
|
||||
end
|
6
app/models/webhooks/slack/topic_removed_from_map.rb
Normal file
6
app/models/webhooks/slack/topic_removed_from_map.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
class Webhooks::Slack::TopicRemovedFromMap < Webhooks::Slack::Base
|
||||
def text
|
||||
"*#{eventable.name}* was removed by *#{event.user.name}* from the map *#{view_map_on_metamaps}*"
|
||||
end
|
||||
end
|
|
@ -3,24 +3,4 @@ class Webhooks::Slack::UserPresentOnMap < Webhooks::Slack::Base
|
|||
def text
|
||||
"Mapper *#{event.user.name}* has joined the map *#{event.map.name}*. #{view_map_on_metamaps('Map with them')}"
|
||||
end
|
||||
# TODO: it would be sweet if it sends it with the metacode as the icon_url
|
||||
|
||||
def attachment_fallback
|
||||
'' # {}"*#{eventable.name}*\n#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_title
|
||||
'' # proposal_link(eventable)
|
||||
end
|
||||
|
||||
def attachment_text
|
||||
'' # "#{eventable.description}\n"
|
||||
end
|
||||
|
||||
def attachment_fields
|
||||
[{
|
||||
title: 'nothing',
|
||||
value: 'nothing'
|
||||
}] # [motion_vote_field]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
class EventSerializer < ActiveModel::Serializer
|
||||
attributes :id, :sequence_id, :kind, :map_id, :created_at
|
||||
attributes :id, :kind, :map_id, :created_at
|
||||
|
||||
has_one :actor, serializer: Api::V2::UserSerializer, root: 'users'
|
||||
has_one :map, serializer: Api::V2::MapSerializer
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
class WebhookSerializer < ActiveModel::Serializer
|
||||
attributes :text, :username, :icon_url # , :attachments
|
||||
attributes :text, :username, :icon_url
|
||||
attribute :channel, if: :has_channel?
|
||||
|
||||
def has_channel?
|
||||
|
|
|
@ -18,5 +18,6 @@
|
|||
Metamaps.ServerData.Mappings = <%= @allmappings.to_json.html_safe %>;
|
||||
Metamaps.ServerData.Messages = <%= @allmessages.to_json.html_safe %>;
|
||||
Metamaps.ServerData.Stars = <%= @allstars.to_json.html_safe %>;
|
||||
Metamaps.ServerData.Events = <%= @allevents.to_json.html_safe %>;
|
||||
Metamaps.ServerData.VisualizeType = "ForceDirected";
|
||||
</script>
|
||||
|
|
5
db/migrate/20161214140124_add_meta_to_events.rb
Normal file
5
db/migrate/20161214140124_add_meta_to_events.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddMetaToEvents < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :events, :meta, :json
|
||||
end
|
||||
end
|
|
@ -35,6 +35,7 @@ const DataModel = {
|
|||
|
||||
Collaborators: new MapperCollection(),
|
||||
Creators: new MapperCollection(),
|
||||
Events: [],
|
||||
Mappers: new MapperCollection(),
|
||||
Mappings: new MappingCollection(),
|
||||
Maps: {
|
||||
|
@ -68,6 +69,7 @@ const DataModel = {
|
|||
|
||||
if (serverData.Collaborators) self.Collaborators = new MapperCollection(serverData.Collaborators)
|
||||
if (serverData.Creators) self.Creators = new MapperCollection(serverData.Creators)
|
||||
if (serverData.Events) self.Events = serverData.Events
|
||||
if (serverData.Mappers) self.Mappers = new MapperCollection(serverData.Mappers)
|
||||
if (serverData.Mappings) self.Mappings = new MappingCollection(serverData.Mappings)
|
||||
if (serverData.Messages) self.Messages = serverData.Messages
|
||||
|
|
|
@ -12,11 +12,13 @@ import Filter from '../Filter'
|
|||
import GlobalUI from '../GlobalUI'
|
||||
import JIT from '../JIT'
|
||||
import Loading from '../Loading'
|
||||
import Mapper from '../Mapper'
|
||||
import Realtime from '../Realtime'
|
||||
import Router from '../Router'
|
||||
import Selected from '../Selected'
|
||||
import SynapseCard from '../SynapseCard'
|
||||
import TopicCard from '../TopicCard'
|
||||
import Topic from '../Topic'
|
||||
import Visualize from '../Visualize'
|
||||
|
||||
import CheatSheet from './CheatSheet'
|
||||
|
@ -80,6 +82,7 @@ const Map = {
|
|||
DataModel.Mappings = new DataModel.MappingCollection(data.mappings)
|
||||
DataModel.Messages = data.messages
|
||||
DataModel.Stars = data.stars
|
||||
DataModel.Events = data.events
|
||||
DataModel.attachCollectionEvents()
|
||||
|
||||
var map = Active.Map
|
||||
|
@ -376,7 +379,52 @@ const Map = {
|
|||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
replay: function () {
|
||||
|
||||
function addNode(topic, meta, user_id) {
|
||||
var mapping, mapper, cancel
|
||||
mapping = new DataModel.Mapping({ id: meta.mapping_id, xloc: meta.x, yloc: meta.y })
|
||||
function waitThenRenderTopic() {
|
||||
if (mapper) {
|
||||
Topic.renderTopic(mapping, topic, false, false)
|
||||
} else if (!cancel) {
|
||||
setTimeout(waitThenRenderTopic, 10)
|
||||
}
|
||||
}
|
||||
mapper = DataModel.Mappers.get(user_id)
|
||||
if (mapper === undefined) {
|
||||
Mapper.get(user_id, function(m) {
|
||||
DataModel.Mappers.add(m)
|
||||
mapper = m
|
||||
})
|
||||
}
|
||||
|
||||
waitThenRenderTopic()
|
||||
}
|
||||
|
||||
function processEvent(event, index) {
|
||||
function complete(delay) {
|
||||
var next = DataModel.Events[index + 1]
|
||||
if (next) {
|
||||
setTimeout(function(){ processEvent(next, index + 1) }, delay)
|
||||
}
|
||||
}
|
||||
switch (event.kind) {
|
||||
case 'topic_added_to_map':
|
||||
Topic.get(event.eventable_id, function(topic) {
|
||||
addNode(topic, event.meta, event.user_id)
|
||||
complete(1000)
|
||||
})
|
||||
break;
|
||||
default:
|
||||
complete(10)
|
||||
}
|
||||
} // processEvent
|
||||
Visualize.mGraph.graph.empty()
|
||||
Visualize.mGraph.plot()
|
||||
processEvent(DataModel.Events[0], 0)
|
||||
} // replay
|
||||
}
|
||||
|
||||
export { CheatSheet, InfoBox }
|
||||
|
|
Loading…
Reference in a new issue