Merge branch 'develop'
This commit is contained in:
commit
44753dbfe1
27 changed files with 186 additions and 81 deletions
|
@ -455,19 +455,6 @@
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
.takeScreenshot {
|
||||
margin-bottom: 5px;
|
||||
border-radius: 2px;
|
||||
background-image: url(<%= asset_path 'screenshot_sprite.png' %>);
|
||||
display: none;
|
||||
}
|
||||
.takeScreenshot:hover {
|
||||
background-position: -32px 0;
|
||||
}
|
||||
.canEditMap .takeScreenshot {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.zoomExtents {
|
||||
margin-bottom:5px;
|
||||
border-radius: 2px;
|
||||
|
@ -478,7 +465,7 @@
|
|||
background-position: -32px 0;
|
||||
}
|
||||
|
||||
.zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .takeScreenshot:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .notificationsIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder,
|
||||
.zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .notificationsIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder,
|
||||
.mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove, .chat-button:hover .tooltips, .importDialog:hover .tooltipsUnder, .starMap:hover .tooltipsAbove, .openMetacodeSwitcher:hover .tooltipsAbove, .pinCarousel:not(.isPinned):hover .tooltipsAbove.helpPin, .pinCarousel.isPinned:hover .tooltipsAbove.helpUnpin {
|
||||
display: block;
|
||||
}
|
||||
|
@ -609,7 +596,7 @@
|
|||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .takeScreenshot div:after, .chat-button div.tooltips::after {
|
||||
.zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .chat-button div.tooltips::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 57%;
|
||||
|
|
|
@ -3,6 +3,7 @@ module Api
|
|||
module V2
|
||||
class UsersController < RestfulController
|
||||
def current
|
||||
raise Pundit::NotAuthorizedError if current_user.nil?
|
||||
@user = current_user
|
||||
authorize @user
|
||||
show # delegate to the normal show function
|
||||
|
|
|
@ -23,11 +23,12 @@ class UsersController < ApplicationController
|
|||
if user_params[:password] == '' && user_params[:password_confirmation] == ''
|
||||
# not trying to change the password
|
||||
if @user.update_attributes(user_params.except(:password, :password_confirmation))
|
||||
update_follow_settings(@user, params[:settings])
|
||||
@user.image = nil if params[:remove_image] == '1'
|
||||
@user.save
|
||||
sign_in(@user, bypass: true)
|
||||
respond_to do |format|
|
||||
format.html { redirect_to root_url, notice: 'Account updated!' }
|
||||
format.html { redirect_to root_url, notice: 'Settings updated' }
|
||||
end
|
||||
else
|
||||
sign_in(@user, bypass: true)
|
||||
|
@ -40,11 +41,12 @@ class UsersController < ApplicationController
|
|||
correct_pass = @user.valid_password?(params[:current_password])
|
||||
|
||||
if correct_pass && @user.update_attributes(user_params)
|
||||
update_follow_settings(@user, params[:settings])
|
||||
@user.image = nil if params[:remove_image] == '1'
|
||||
@user.save
|
||||
sign_in(@user, bypass: true)
|
||||
respond_to do |format|
|
||||
format.html { redirect_to root_url, notice: 'Account updated!' }
|
||||
format.html { redirect_to root_url, notice: 'Settings updated' }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
|
@ -104,9 +106,16 @@ class UsersController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def update_follow_settings(user, settings)
|
||||
user.settings.follow_topic_on_created = settings[:follow_topic_on_created]
|
||||
user.settings.follow_topic_on_contributed = settings[:follow_topic_on_contributed]
|
||||
user.settings.follow_map_on_created = settings[:follow_map_on_created]
|
||||
user.settings.follow_map_on_contributed = settings[:follow_map_on_contributed]
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(
|
||||
:name, :email, :image, :password, :password_confirmation, :emails_allowed
|
||||
:name, :email, :image, :password, :password_confirmation, :emails_allowed, :settings
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,7 +39,7 @@ class Map < ApplicationRecord
|
|||
# Validate the attached image is image/jpg, image/png, etc
|
||||
validates_attachment_content_type :screenshot, content_type: %r{\Aimage/.*\Z}
|
||||
|
||||
after_create :after_created_async
|
||||
after_create :after_created
|
||||
after_update :after_updated
|
||||
after_save :update_deferring_topics_and_synapses, if: :permission_changed?
|
||||
|
||||
|
@ -140,11 +140,10 @@ class Map < ApplicationRecord
|
|||
|
||||
protected
|
||||
|
||||
def after_created_async
|
||||
def after_created
|
||||
FollowService.follow(self, self.user, 'created')
|
||||
# notify users following the map creator
|
||||
end
|
||||
handle_asynchronously :after_created_async
|
||||
|
||||
def after_updated
|
||||
return unless ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) }
|
||||
|
|
|
@ -62,6 +62,12 @@ class User < ApplicationRecord
|
|||
maps: following.where(followed_type: 'Map').to_a.map(&:followed_id)
|
||||
}
|
||||
end
|
||||
if (_options[:follow_settings])
|
||||
json['follow_topic_on_created'] = settings.follow_topic_on_created == "1"
|
||||
json['follow_topic_on_contributed'] = settings.follow_topic_on_contributed == "1"
|
||||
json['follow_map_on_created'] = settings.follow_map_on_created == "1"
|
||||
json['follow_map_on_contributed'] = settings.follow_map_on_contributed == "1"
|
||||
end
|
||||
if (_options[:email])
|
||||
json['email'] = email
|
||||
end
|
||||
|
@ -126,9 +132,23 @@ class User < ApplicationRecord
|
|||
stars.where(map_id: map.id).exists?
|
||||
end
|
||||
|
||||
def has_map_open(map)
|
||||
latestEvent = Event.where(map: map, user: self)
|
||||
.where(kind: ['user_present_on_map', 'user_not_present_on_map'])
|
||||
.order(:created_at)
|
||||
.last
|
||||
latestEvent && latestEvent.kind == 'user_present_on_map'
|
||||
end
|
||||
|
||||
def has_map_with_synapse_open(synapse)
|
||||
synapse.maps.any?{|map| has_map_open(map)}
|
||||
end
|
||||
|
||||
def settings
|
||||
# make sure we always return a UserPreference instance
|
||||
self[:settings] = UserPreference.new if self[:settings].nil?
|
||||
if not self[:settings].respond_to?(:follow_topic_on_created)
|
||||
self[:settings].initialize_follow_settings
|
||||
end
|
||||
self[:settings]
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
class UserPreference
|
||||
attr_accessor :metacodes, :metacode_focus
|
||||
attr_accessor :metacodes, :metacode_focus, :follow_topic_on_created, :follow_topic_on_contributed,
|
||||
:follow_map_on_created, :follow_map_on_contributed
|
||||
|
||||
def initialize
|
||||
array = []
|
||||
|
@ -16,5 +17,13 @@ class UserPreference
|
|||
end
|
||||
@metacodes = array
|
||||
@metacode_focus = array[0]
|
||||
initialize_follow_settings
|
||||
end
|
||||
|
||||
def initialize_follow_settings
|
||||
@follow_topic_on_created = false
|
||||
@follow_topic_on_contributed = false
|
||||
@follow_map_on_created = false
|
||||
@follow_map_on_contributed = false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,50 +13,49 @@ module Api
|
|||
@embeds ||= (scope[:embeds] || []).select { |e| self.class.embeddable.keys.include?(e) }
|
||||
end
|
||||
|
||||
# self.embeddable might look like this:
|
||||
# creator: { attr: :first_creator, serializer: UserSerializer }
|
||||
# contributors: { serializer: UserSerializer}
|
||||
# This method will remove the :attr key if the underlying attribute name
|
||||
# is different than the name provided in the final json output. All other keys
|
||||
# in the hash will be passed to the ActiveModel::Serializer `attribute` method
|
||||
# directly (e.g. serializer in the examples will be passed).
|
||||
#
|
||||
# This setup means if you passed this self.embeddable config and sent no
|
||||
# ?embed= query param with your API request, you would get the regular attributes
|
||||
# plus creator_id and contributor_ids. If you passed ?embed=creator,contributors
|
||||
# then instead of an id and an array of ids, you would get a serialized user
|
||||
# (the first_creator) and an array of serialized users (the contributors).
|
||||
# Here's an example object that could be passed in self.embeddable: {
|
||||
# creator: {
|
||||
# serializer: UserSerializer,
|
||||
# },
|
||||
# collaborators: {
|
||||
# serializer: UserSerializer
|
||||
# },
|
||||
# topic: {},
|
||||
# synapses: {}
|
||||
# }
|
||||
# The key has to be in embeddable or it won't show in the response, and the serializer is
|
||||
# only needed if the key doesn't match a serializer
|
||||
def self.embed_dat
|
||||
embeddable.each_pair do |key, opts|
|
||||
attr = opts.delete(:attr) || key
|
||||
if attr.to_s.pluralize == attr.to_s
|
||||
attribute("#{attr.to_s.singularize}_ids".to_sym,
|
||||
opts.merge(unless: -> { embeds.include?(key) })) do
|
||||
Pundit.policy_scope(scope[:current_user], object.send(attr))&.map(&:id) || []
|
||||
is_plural = key.to_s.pluralize == key.to_s
|
||||
id_key = key.to_s.singularize + (is_plural ? '_ids' : '_id')
|
||||
serializer = opts.delete(:serializer) || "Api::V2::#{key.to_s.singularize.camelize}Serializer".constantize
|
||||
if is_plural
|
||||
attribute(id_key.to_sym, opts.merge(unless: -> { embeds.include?(key) })) do
|
||||
Pundit.policy_scope(scope[:current_user], object.send(key))&.map(&:id) || []
|
||||
end
|
||||
has_many(attr, opts.merge(if: -> { embeds.include?(key) })) do
|
||||
list = Pundit.policy_scope(scope[:current_user], object.send(attr)) || []
|
||||
child_serializer = "Api::V2::#{attr.to_s.singularize.camelize}Serializer".constantize
|
||||
has_many(key, opts.merge(if: -> { embeds.include?(key) })) do
|
||||
list = Pundit.policy_scope(scope[:current_user], object.send(key)) || []
|
||||
resource = ActiveModelSerializers::SerializableResource.new(
|
||||
list,
|
||||
each_serializer: child_serializer,
|
||||
each_serializer: serializer,
|
||||
scope: scope.merge(embeds: [])
|
||||
)
|
||||
resource.as_json
|
||||
# resource.as_json will return e.g. { users: [ ... ] } for collaborators
|
||||
# since we can't get the :users key, convert to an array and use .first.second to get the needed values
|
||||
resource&.as_json&.to_a&.first&.second
|
||||
end
|
||||
else
|
||||
id_opts = opts.merge(key: "#{key}_id")
|
||||
attribute("#{attr}_id".to_sym,
|
||||
id_opts.merge(unless: -> { embeds.include?(key) }))
|
||||
attribute(key, opts.merge(if: -> { embeds.include?(key) })) do |serializer|
|
||||
object = serializer.object.send(key)
|
||||
child_serializer = "Api::V2::#{object.class.name}Serializer".constantize
|
||||
attribute(id_key.to_sym, opts.merge(unless: -> { embeds.include?(key) }))
|
||||
attribute(key, opts.merge(if: -> { embeds.include?(key) })) do |parent_serializer|
|
||||
object = parent_serializer.object.send(key)
|
||||
next nil if object.nil?
|
||||
resource = ActiveModelSerializers::SerializableResource.new(
|
||||
object,
|
||||
serializer: child_serializer,
|
||||
serializer: serializer,
|
||||
scope: scope.merge(embeds: [])
|
||||
)
|
||||
resource.as_json
|
||||
resource&.as_json&.to_a&.first&.second
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ module Api
|
|||
def self.embeddable
|
||||
{
|
||||
user: {},
|
||||
source: {},
|
||||
source: { serializer: MapSerializer },
|
||||
topics: {},
|
||||
synapses: {},
|
||||
mappings: {},
|
||||
|
|
|
@ -14,7 +14,7 @@ module Api
|
|||
def self.embeddable
|
||||
{
|
||||
user: {},
|
||||
updated_by: {},
|
||||
updated_by: { serializer: UserSerializer },
|
||||
map: {}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -3,7 +3,9 @@ class FollowService
|
|||
class << self
|
||||
def follow(entity, user, reason)
|
||||
|
||||
return unless is_tester(user)
|
||||
return unless user && is_tester(user)
|
||||
|
||||
return if (reason == 'created' || reason == 'contributed') && !should_auto_follow(entity, user, reason)
|
||||
|
||||
follow = Follow.where(followed: entity, user: user).first_or_create
|
||||
if FollowReason::REASONS.include?(reason) && !follow.follow_reason.read_attribute(reason)
|
||||
|
@ -28,8 +30,20 @@ class FollowService
|
|||
|
||||
protected
|
||||
|
||||
def is_tester(user)
|
||||
%w(connorturland@gmail.com devin@callysto.com chessscholar@gmail.com solaureum@gmail.com ishanshapiro@gmail.com).include?(user.email)
|
||||
def should_auto_follow(entity, user, reason)
|
||||
if entity.class == Topic
|
||||
if reason == 'created'
|
||||
return user.settings.follow_topic_on_created == '1'
|
||||
elsif reason == 'contributed'
|
||||
return user.settings.follow_topic_on_contributed == '1'
|
||||
end
|
||||
elsif entity.class == Map
|
||||
if reason == 'created'
|
||||
return user.settings.follow_map_on_created == '1'
|
||||
elsif reason == 'contributed'
|
||||
return user.settings.follow_map_on_contributed == '1'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,6 +34,14 @@ class NotificationService
|
|||
# we'll prbly want to put the body into the actual loop so we can pass the current user in as a local
|
||||
body = renderer.render(template: settings[:template], locals: { entity: entity, event: event }, layout: false)
|
||||
follows.each{|follow|
|
||||
case event_type
|
||||
when TOPIC_ADDED_TO_MAP
|
||||
next unless TopicPolicy.new(follow.user, entity).show? && MapPolicy.new(follow.user, event.map).show?
|
||||
next if follow.user.has_map_open(event.map)
|
||||
when TOPIC_CONNECTED_1, TOPIC_CONNECTED_2
|
||||
next unless SynapsePolicy.new(follow.user, event).show?
|
||||
next if follow.user.has_map_with_synapse_open(event)
|
||||
end
|
||||
# this handles email and in-app notifications, in the future, include push
|
||||
follow.user.notify(settings[:subject], body, event, false, event_type, follow.user.emails_allowed, event.user)
|
||||
# push could be handled with Actioncable to send transient notifications to the UI
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<ul>
|
||||
<li class="accountListItem accountSettings">
|
||||
<div class="accountIcon"></div>
|
||||
<%= link_to "Account", edit_user_url(account) %>
|
||||
<%= link_to "Settings", edit_user_url(account) %>
|
||||
</li>
|
||||
<% if account.admin %>
|
||||
<li class="accountListItem accountAdmin">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<%= render :partial => 'shared/metacodeBgColors' %>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
<% if current_user %>
|
||||
Metamaps.ServerData.ActiveMapper = <%= current_user.to_json({follows: true, email: true}).html_safe %>
|
||||
Metamaps.ServerData.ActiveMapper = <%= current_user.to_json({follows: true, email: true, follow_settings: true}).html_safe %>
|
||||
<% else %>
|
||||
Metamaps.ServerData.ActiveMapper = null
|
||||
<% end %>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<div class="mapControls mapElement">
|
||||
<div class="takeScreenshot mapControl"><div class="tooltips">Capture Screenshot</div></div>
|
||||
<div class="zoomExtents mapControl"><div class="tooltips">Center View</div></div>
|
||||
<div class="zoomIn mapControl"><div class="tooltips">Zoom In</div></div>
|
||||
<div class="zoomOut mapControl"><div class="tooltips">Zoom Out</div></div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<% content_for :mobile_title, "Account Settings" %>
|
||||
<div id="yield">
|
||||
<%= form_for @user, url: user_url, :html =>{ :multipart => true, :class => "edit_user centerGreyForm"} do |form| %>
|
||||
<h3>Edit Account</h3>
|
||||
<h3>Edit Settings</h3>
|
||||
<div class="userImage">
|
||||
<div class="userImageDiv" onclick="Metamaps.Account.toggleChangePicture()">
|
||||
<%= image_tag @user.image.url(:ninetysix), :size => "84x84" %>
|
||||
|
@ -45,6 +45,26 @@
|
|||
<%= form.check_box :emails_allowed, class: 'inline' %>
|
||||
Send Metamaps notifications to my email.
|
||||
<% end %>
|
||||
<% if is_tester(@user) %>
|
||||
<%= fields_for :settings, @user.settings do |settings| %>
|
||||
<%= settings.label :follow_topic_on_created, class: 'firstFieldText' do %>
|
||||
<%= settings.check_box :follow_topic_on_created, class: 'inline' %>
|
||||
Auto-follow topics you create.
|
||||
<% end %>
|
||||
<%= settings.label :follow_topic_on_contributed, class: 'firstFieldText' do %>
|
||||
<%= settings.check_box :follow_topic_on_contributed, class: 'inline' %>
|
||||
Auto-follow topics you edit.
|
||||
<% end %>
|
||||
<%= settings.label :follow_map_on_created, class: 'firstFieldText' do %>
|
||||
<%= settings.check_box :follow_map_on_created, class: 'inline' %>
|
||||
Auto-follow maps you create.
|
||||
<% end %>
|
||||
<%= settings.label :follow_map_on_contributed, class: 'firstFieldText' do %>
|
||||
<%= settings.check_box :follow_map_on_contributed, class: 'inline' %>
|
||||
Auto-follow maps you edit.
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="changePass" onclick="Metamaps.Account.showPass()">Change Password</div>
|
||||
<div class="toHide">
|
||||
|
|
3
config/initializers/internal_testers.rb
Normal file
3
config/initializers/internal_testers.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
def is_tester(user)
|
||||
user && %w(connorturland@gmail.com devin@callysto.com chessscholar@gmail.com solaureum@gmail.com ishanshapiro@gmail.com).include?(user.email)
|
||||
end
|
|
@ -123,10 +123,14 @@ const Control = {
|
|||
const authorized = Active.Map.authorizeToEdit(Active.Mapper)
|
||||
|
||||
if (!authorized) {
|
||||
GlobalUI.notifyUser('Cannot edit Public map.')
|
||||
GlobalUI.notifyUser('Cannot edit this map.')
|
||||
return
|
||||
}
|
||||
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
|
||||
for (let i = l - 1; i >= 0; i -= 1) {
|
||||
const node = Selected.Nodes[i]
|
||||
Control.removeNode(node.id)
|
||||
|
@ -139,10 +143,14 @@ const Control = {
|
|||
var node = Visualize.mGraph.graph.getNode(nodeid)
|
||||
|
||||
if (!authorized) {
|
||||
GlobalUI.notifyUser('Cannot edit Public map.')
|
||||
GlobalUI.notifyUser('Cannot edit this map.')
|
||||
return
|
||||
}
|
||||
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
|
||||
var topic = node.getData('topic')
|
||||
var mapping = node.getData('mapping')
|
||||
mapping.destroy()
|
||||
|
@ -284,10 +292,14 @@ const Control = {
|
|||
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
|
||||
|
||||
if (!authorized) {
|
||||
GlobalUI.notifyUser('Cannot edit Public map.')
|
||||
GlobalUI.notifyUser('Cannot edit this map.')
|
||||
return
|
||||
}
|
||||
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
|
||||
for (let i = l - 1; i >= 0; i -= 1) {
|
||||
const edge = Selected.Edges[i]
|
||||
Control.removeEdge(edge)
|
||||
|
@ -300,10 +312,14 @@ const Control = {
|
|||
var authorized = Active.Map.authorizeToEdit(Active.Mapper)
|
||||
|
||||
if (!authorized) {
|
||||
GlobalUI.notifyUser('Cannot edit Public map.')
|
||||
GlobalUI.notifyUser('Cannot edit this map.')
|
||||
return
|
||||
}
|
||||
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
|
||||
if (edge.getData('mappings').length - 1 === 0) {
|
||||
Control.hideEdge(edge)
|
||||
}
|
||||
|
|
|
@ -17,14 +17,16 @@ const Mapper = Backbone.Model.extend({
|
|||
</li>`
|
||||
},
|
||||
followMap: function(id) {
|
||||
this.get('follows').maps.push(id)
|
||||
const idIndex = this.get('follows').maps.indexOf(id)
|
||||
if (idIndex < 0) this.get('follows').maps.push(id)
|
||||
},
|
||||
unfollowMap: function(id) {
|
||||
const idIndex = this.get('follows').maps.indexOf(id)
|
||||
if (idIndex > -1) this.get('follows').maps.splice(idIndex, 1)
|
||||
},
|
||||
followTopic: function(id) {
|
||||
this.get('follows').topics.push(id)
|
||||
const idIndex = this.get('follows').topics.indexOf(id)
|
||||
if (idIndex < 0) this.get('follows').topics.push(id)
|
||||
},
|
||||
unfollowTopic: function(id) {
|
||||
const idIndex = this.get('follows').topics.indexOf(id)
|
||||
|
|
|
@ -99,6 +99,9 @@ const CreateMap = {
|
|||
success: function(model) {
|
||||
// push the new map onto the collection of 'my maps'
|
||||
DataModel.Maps.Mine.add(model)
|
||||
if (Active.Mapper.get('follow_map_on_created')) {
|
||||
Active.Mapper.followMap(model.id)
|
||||
}
|
||||
|
||||
GlobalUI.clearNotify()
|
||||
$('#wrapper').append(outdent`
|
||||
|
|
|
@ -27,7 +27,7 @@ const ImportDialog = {
|
|||
onFileAdded: PasteInput.handleFile,
|
||||
exampleImageUrl: serverData['import-example.png'],
|
||||
downloadScreenshot: ImportDialog.downloadScreenshot,
|
||||
onExport: format => {
|
||||
onExport: format => () => {
|
||||
window.open(`${window.location.pathname}/export.${format}`, '_blank')
|
||||
}
|
||||
}), $('.importDialogWrapper').get(0))
|
||||
|
|
|
@ -59,8 +59,6 @@ const JIT = {
|
|||
}
|
||||
$('.zoomExtents').click(zoomExtents)
|
||||
|
||||
$('.takeScreenshot').click(Map.exportImage)
|
||||
|
||||
self.topicDescImage = new Image()
|
||||
self.topicDescImage.src = serverData['topic_description_signifier.png']
|
||||
|
||||
|
@ -979,6 +977,9 @@ const JIT = {
|
|||
}
|
||||
|
||||
if (checkWhetherToSave()) {
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
mapping = node.getData('mapping')
|
||||
mapping.save({
|
||||
xloc: node.getPos().x,
|
||||
|
|
|
@ -253,11 +253,6 @@ const Map = {
|
|||
DataModel.Mappers.add(Active.Mapper)
|
||||
}
|
||||
},
|
||||
exportImage: function() {
|
||||
Map.uploadMapScreenshot()
|
||||
Map.offerScreenshotDownload()
|
||||
GlobalUI.notifyUser('Note: this button is going away. Check the map card or the import box for setting the map thumbnail or downloading a screenshot.')
|
||||
},
|
||||
offerScreenshotDownload: () => {
|
||||
const canvas = Map.getMapCanvasForScreenshots()
|
||||
const filename = Map.getMapScreenshotFilename(Active.Map)
|
||||
|
|
|
@ -42,6 +42,11 @@ const Synapse = {
|
|||
var synapseSuccessCallback = function(synapseModel, response) {
|
||||
if (Active.Map) {
|
||||
mapping.save({ mappable_id: synapseModel.id }, {
|
||||
success: function(model, response) {
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
},
|
||||
error: function(model, response) {
|
||||
console.log('error saving mapping to database')
|
||||
}
|
||||
|
@ -59,6 +64,11 @@ const Synapse = {
|
|||
})
|
||||
} else if (!synapse.isNew() && Active.Map) {
|
||||
mapping.save(null, {
|
||||
success: function(model, response) {
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
},
|
||||
error: function(model, response) {
|
||||
console.log('error saving mapping to database')
|
||||
}
|
||||
|
|
|
@ -242,12 +242,18 @@ const Topic = {
|
|||
}
|
||||
|
||||
var mappingSuccessCallback = function(mappingModel, response, topicModel) {
|
||||
if (Active.Mapper.get('follow_map_on_contributed')) {
|
||||
Active.Mapper.followMap(Active.Map.id)
|
||||
}
|
||||
// call a success callback if provided
|
||||
if (opts.success) {
|
||||
opts.success(topicModel)
|
||||
}
|
||||
}
|
||||
var topicSuccessCallback = function(topicModel, response) {
|
||||
if (Active.Mapper.get('follow_topic_on_created')) {
|
||||
Active.Mapper.followTopic(topicModel.id)
|
||||
}
|
||||
if (Active.Map) {
|
||||
mapping.save({ mappable_id: topicModel.id }, {
|
||||
success: function(model, response) {
|
||||
|
|
|
@ -9,7 +9,11 @@ class Attachments extends Component {
|
|||
|
||||
return (
|
||||
<div className="attachments">
|
||||
<EmbedlyLink link={link} authorizedToEdit={authorizedToEdit} updateTopic={updateTopic} />
|
||||
<EmbedlyLink topicId={topic.id}
|
||||
link={link}
|
||||
authorizedToEdit={authorizedToEdit}
|
||||
updateTopic={updateTopic}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class EmbedlyLink extends Component {
|
|||
}
|
||||
|
||||
render = () => {
|
||||
const { link, authorizedToEdit } = this.props
|
||||
const { link, authorizedToEdit, topicId } = this.props
|
||||
const { linkEdit } = this.state
|
||||
const hasAttachment = !!link
|
||||
|
||||
|
@ -55,7 +55,7 @@ class EmbedlyLink extends Component {
|
|||
{linkEdit && <div id="addLinkReset" onClick={this.resetLink}></div>}
|
||||
</div>
|
||||
</div>
|
||||
{link && <Card link={link} />}
|
||||
{link && <Card key={topicId} link={link} />}
|
||||
{authorizedToEdit && (
|
||||
<div id="linkremove"
|
||||
style={{ display: hasAttachment ? 'block' : 'none' }}
|
||||
|
@ -68,6 +68,7 @@ class EmbedlyLink extends Component {
|
|||
}
|
||||
|
||||
EmbedlyLink.propTypes = {
|
||||
topicId: PropTypes.number,
|
||||
link: PropTypes.string,
|
||||
authorizedToEdit: PropTypes.bool,
|
||||
updateTopic: PropTypes.func
|
||||
|
|
|
@ -12,7 +12,6 @@ const plugins = [
|
|||
const externals = ["bindings"] // work around bindings.js error
|
||||
|
||||
if (NODE_ENV === 'production') {
|
||||
plugins.push(new webpack.optimize.DedupePlugin())
|
||||
plugins.push(new webpack.optimize.UglifyJsPlugin({
|
||||
compress: { warnings: false }
|
||||
}))
|
||||
|
|
Loading…
Reference in a new issue