From 713f731aafab2a690b4ad53437679f6b583d7afc Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Thu, 9 Feb 2017 22:01:09 +0000 Subject: [PATCH] follows --- app/mailers/application_mailer.rb | 4 + app/mailers/map_mailer.rb | 6 +- app/models/access_request.rb | 8 -- app/models/events/topic_updated.rb | 6 +- app/models/follow.rb | 21 ++++ app/models/follow_reason.rb | 12 ++ app/models/follow_type.rb | 6 + app/models/map.rb | 21 +++- app/models/message.rb | 8 ++ app/models/star.rb | 15 +++ app/models/synapse.rb | 14 +++ app/models/topic.rb | 23 ++++ app/models/user.rb | 4 + app/services/follow_service.rb | 35 ++++++ app/services/notification_service.rb | 113 +++++++++++++++++- app/views/map_mailer/map_activity.html.erb | 0 app/views/map_mailer/map_activity.text.erb | 0 .../map_collaborator_added.html.erb | 0 .../map_collaborator_added.text.erb | 0 app/views/map_mailer/map_message.html.erb | 5 + app/views/map_mailer/map_message.text.erb | 0 app/views/map_mailer/map_starred.html.erb | 3 + app/views/map_mailer/map_starred.text.erb | 0 app/views/map_mailer/map_updated.html.erb | 0 app/views/map_mailer/map_updated.text.erb | 0 .../map_mailer/topic_added_to_map.html.erb | 9 ++ .../map_mailer/topic_added_to_map.text.erb | 0 app/views/map_mailer/topic_connected.html.erb | 15 +++ app/views/map_mailer/topic_connected.text.erb | 0 app/views/map_mailer/topic_deleted.html.erb | 0 app/views/map_mailer/topic_deleted.text.erb | 0 .../map_mailer/topic_disconnected.html.erb | 0 .../map_mailer/topic_disconnected.text.erb | 0 app/views/map_mailer/topic_updated.html.erb | 0 app/views/map_mailer/topic_updated.text.erb | 0 config/initializers/mailboxer.rb | 26 +++- db/migrate/20170209215819_create_follows.rb | 12 ++ .../20170209215911_create_follow_reasons.rb | 14 +++ .../20170209215920_create_follow_types.rb | 22 ++++ db/schema.rb | 49 +++++++- 40 files changed, 428 insertions(+), 23 deletions(-) create mode 100644 app/models/follow.rb create mode 100644 app/models/follow_reason.rb create mode 100644 app/models/follow_type.rb create mode 100644 app/services/follow_service.rb create mode 100644 app/views/map_mailer/map_activity.html.erb create mode 100644 app/views/map_mailer/map_activity.text.erb create mode 100644 app/views/map_mailer/map_collaborator_added.html.erb create mode 100644 app/views/map_mailer/map_collaborator_added.text.erb create mode 100644 app/views/map_mailer/map_message.html.erb create mode 100644 app/views/map_mailer/map_message.text.erb create mode 100644 app/views/map_mailer/map_starred.html.erb create mode 100644 app/views/map_mailer/map_starred.text.erb create mode 100644 app/views/map_mailer/map_updated.html.erb create mode 100644 app/views/map_mailer/map_updated.text.erb create mode 100644 app/views/map_mailer/topic_added_to_map.html.erb create mode 100644 app/views/map_mailer/topic_added_to_map.text.erb create mode 100644 app/views/map_mailer/topic_connected.html.erb create mode 100644 app/views/map_mailer/topic_connected.text.erb create mode 100644 app/views/map_mailer/topic_deleted.html.erb create mode 100644 app/views/map_mailer/topic_deleted.text.erb create mode 100644 app/views/map_mailer/topic_disconnected.html.erb create mode 100644 app/views/map_mailer/topic_disconnected.text.erb create mode 100644 app/views/map_mailer/topic_updated.html.erb create mode 100644 app/views/map_mailer/topic_updated.text.erb create mode 100644 db/migrate/20170209215819_create_follows.rb create mode 100644 db/migrate/20170209215911_create_follow_reasons.rb create mode 100644 db/migrate/20170209215920_create_follow_types.rb diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 6c631e9a..828f6551 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -19,6 +19,10 @@ class ApplicationMailer < ActionMailer::Base when MAILBOXER_CODE_INVITE_TO_EDIT user_map = notification.notified_object MapMailer.invite_to_edit(user_map) + when MAILBOXER_CODE_MAP_MESSAGE + when MAILBOXER_CODE_MAP_STARRED + when MAILBOXER_CODE_TOPIC_ADDED_TO_MAP + when MAILBOXER_CODE_TOPIC_CONNECTED end end end diff --git a/app/mailers/map_mailer.rb b/app/mailers/map_mailer.rb index c14e9c65..581d6223 100644 --- a/app/mailers/map_mailer.rb +++ b/app/mailers/map_mailer.rb @@ -5,18 +5,18 @@ class MapMailer < ApplicationMailer def access_request(request) @request = request @map = request.map - mail(to: @map.user.email, subject: request.requested_text) + mail(to: @map.user.email, subject: NotificationService.get_subject_for_event(@map, 'access_request', request)) end def access_approved(request) @request = request @map = request.map - mail(to: request.user, subject: request.approved_text) + mail(to: request.user, subject: NotificationService.get_subject_for_event(@map, 'access_approved', request)) end def invite_to_edit(user_map) @inviter = user_map.map.user @map = user_map.map - mail(to: user_map.user.email, subject: @map.invited_text) + mail(to: user_map.user.email, subject: NotificationService.get_subject_for_event(@map, 'invite_to_edit', user_map)) end end diff --git a/app/models/access_request.rb b/app/models/access_request.rb index 5c39b174..a26146ff 100644 --- a/app/models/access_request.rb +++ b/app/models/access_request.rb @@ -27,14 +27,6 @@ class AccessRequest < ApplicationRecord Mailboxer::Receipt.where(notification: notification).update_all(is_read: true) end end - - def requested_text - map.name + ' - request to edit' - end - - def approved_text - map.name + ' - access approved' - end protected diff --git a/app/models/events/topic_updated.rb b/app/models/events/topic_updated.rb index d52a4298..090cfcda 100644 --- a/app/models/events/topic_updated.rb +++ b/app/models/events/topic_updated.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Events class TopicUpdated < Event - # after_create :notify_users! + #after_create :notify_users! def self.publish!(topic, user, meta) create!(kind: 'topic_updated', @@ -9,5 +9,9 @@ module Events user: user, meta: meta) end + + def notify_users! + NotificationService.notify_followers(eventable, 'topic_updated', self) + end end end diff --git a/app/models/follow.rb b/app/models/follow.rb new file mode 100644 index 00000000..76c9b300 --- /dev/null +++ b/app/models/follow.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true +class Follow < ApplicationRecord + + belongs_to :user + belongs_to :followed, polymorphic: true + has_one :follow_reason, dependent: :destroy + has_one :follow_type, dependent: :destroy + + validates :user, presence: true + validates :followed, presence: true + validates :user, uniqueness: { scope: :followed, message: 'This entity is already followed by this user' } + + after_create :add_subsettings + + private + + def add_subsettings + follow_reason = FollowReason.create!(follow: self) + follow_type = FollowType.create!(follow: self) + end +end diff --git a/app/models/follow_reason.rb b/app/models/follow_reason.rb new file mode 100644 index 00000000..baf70a6a --- /dev/null +++ b/app/models/follow_reason.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +class FollowReason < ApplicationRecord + REASONS = %w(created commented contributed followed shared_on starred).freeze + + belongs_to :follow + + validates :follow, presence: true + + def has_reason + created || commented || contributed || followed || shared_on || starred + end +end \ No newline at end of file diff --git a/app/models/follow_type.rb b/app/models/follow_type.rb new file mode 100644 index 00000000..092070e5 --- /dev/null +++ b/app/models/follow_type.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class FollowType < ApplicationRecord + belongs_to :follow + + validates :follow, presence: true +end \ No newline at end of file diff --git a/app/models/map.rb b/app/models/map.rb index 93137c70..a149a760 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -14,6 +14,8 @@ class Map < ApplicationRecord has_many :synapses, through: :synapsemappings, source: :mappable, source_type: 'Synapse' has_many :messages, as: :resource, dependent: :destroy has_many :stars, dependent: :destroy + has_many :follows, as: :followed, dependent: :destroy + has_many :followers, :through => :follows, source: :user has_many :access_requests, dependent: :destroy has_many :user_maps, dependent: :destroy @@ -37,6 +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_update :after_updated after_save :update_deferring_topics_and_synapses, if: :permission_changed? @@ -135,15 +138,25 @@ class Map < ApplicationRecord Synapse.where(defer_to_map_id: id).update(permission: permission) end - def invited_text - name + ' - invited to edit' - end - protected + + def after_created_async + 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) } ActionCable.server.broadcast 'map_' + id.to_s, type: 'mapUpdated' end + def after_updated_async + if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) } + FollowService.follow(self, updated_by, 'contributed') + # NotificationService.notify_followers(self, 'map_updated', changed_attributes) + # or better yet publish an event + end + end + handle_asynchronously :after_updated_async end diff --git a/app/models/message.rb b/app/models/message.rb index d26ce9d6..5e435968 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -6,6 +6,8 @@ class Message < ApplicationRecord delegate :name, to: :user, prefix: true after_create :after_created + after_create :after_created_async + def user_image user.image.url @@ -19,4 +21,10 @@ class Message < ApplicationRecord def after_created ActionCable.server.broadcast 'map_' + resource.id.to_s, type: 'messageCreated', message: as_json end + + def after_created_async + FollowService.follow(resource, user, 'commented') + NotificationService.notify_followers(resource, 'map_message', self) + end + handle_asynchronously :after_created_async end diff --git a/app/models/star.rb b/app/models/star.rb index a49ae2b1..75e3761c 100644 --- a/app/models/star.rb +++ b/app/models/star.rb @@ -3,4 +3,19 @@ class Star < ActiveRecord::Base belongs_to :user belongs_to :map validates :map, uniqueness: { scope: :user, message: 'You have already starred this map' } + + after_create :after_created_async + before_destroy :before_destroyed + + protected + + def after_created_async + FollowService.follow(map, user, 'starred') + NotificationService.notify_followers(map, 'map_starred', self, 'created') + end + handle_asynchronously :after_created_async + + def before_destroyed + FollowService.remove_reason(map, user, 'starred') + end end diff --git a/app/models/synapse.rb b/app/models/synapse.rb index c74d8fc4..75cb9759 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -26,7 +26,9 @@ class Synapse < ApplicationRecord } before_create :set_perm_by_defer + after_create :after_created_async after_update :after_updated + before_destroy :before_destroyed delegate :name, to: :user, prefix: true @@ -72,6 +74,12 @@ class Synapse < ApplicationRecord def set_perm_by_defer permission = defer_to_map.permission if defer_to_map end + + def after_created_async + NotificationService.notify_followers(topic1, 'topic_connected', self) + NotificationService.notify_followers(topic2, 'topic_connected', self) + end + handle_asynchronously :after_created_async def after_updated if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) } @@ -85,4 +93,10 @@ class Synapse < ApplicationRecord end end end + + def before_destroyed + # hard to know how to do this yet, because the synapse actually gets destroyed + #NotificationService.notify_followers(topic1, 'topic_disconnected', self) + #NotificationService.notify_followers(topic2, 'topic_disconnected', self) + end end diff --git a/app/models/topic.rb b/app/models/topic.rb index 676ea934..82efb8bc 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -15,12 +15,17 @@ class Topic < ApplicationRecord has_many :mappings, as: :mappable, dependent: :destroy has_many :maps, through: :mappings + has_many :follows, as: :followed, dependent: :destroy + has_many :followers, :through => :follows, source: :user belongs_to :metacode before_create :set_perm_by_defer before_create :create_metamap? + after_create :after_created_async after_update :after_updated + after_update :after_updated_async + #before_destroy :before_destroyed validates :permission, presence: true validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) } @@ -149,6 +154,12 @@ class Topic < ApplicationRecord self.link = Rails.application.routes.url_helpers .map_url(host: ENV['MAILER_DEFAULT_URL'], id: @map.id) end + + def after_created_async + FollowService.follow(self, self.user, 'created') + # notify users following the topic creator + end + handle_asynchronously :after_created_async def after_updated if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) } @@ -162,4 +173,16 @@ class Topic < ApplicationRecord end end end + + def after_updated_async + if ATTRS_TO_WATCH.any? { |k| changed_attributes.key?(k) } + FollowService.follow(self, updated_by, 'contributed') + end + end + handle_asynchronously :after_updated_async + + def before_destroyed + # hard to know how to do this yet, because the topic actually gets destroyed + #NotificationService.notify_followers(self, 'topic_deleted', ?) + end end diff --git a/app/models/user.rb b/app/models/user.rb index 915d06db..e5fadaa9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,6 +12,10 @@ class User < ApplicationRecord has_many :stars has_many :user_maps, dependent: :destroy has_many :shared_maps, through: :user_maps, source: :map + has_many :follows, as: :followed + has_many :followers, through: :follows, source: :user + + has_many :following, class_name: 'Follow' after_create :generate_code diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb new file mode 100644 index 00000000..4fa6dd9d --- /dev/null +++ b/app/services/follow_service.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true +class FollowService + + + def self.follow(entity, user, reason) + + #return unless is_tester(user) + + follow = Follow.where(followed: entity, user: user).first_or_create + if FollowReason::REASONS.include?(reason) && !follow.follow_reason.read_attribute(reason) + follow.follow_reason.update_attribute(reason, true) + end + end + + def self.unfollow(entity, user) + Follow.where(followed: entity, user: user).destroy_all + end + + def self.remove_reason(entity, user, reason) + return unless FollowReason::REASONS.include?(reason) + follow = Follow.where(followed: entity, user: user).first + if follow + follow.follow_reason.update_attribute(reason, false) + if !follow.follow_reason.has_reason + follow.destroy + end + end + end + + protected + + def is_tester(user) + %w(connorturland@gmail.com devin@callysto.com chessscholar@gmail.com solaureum@gmail.com ishanshapiro@gmail.com).include?(user.email) + end +end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index c590a5ca..9644d23b 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -22,31 +22,124 @@ class NotificationService MAILBOXER_CODE_ACCESS_REQUEST when 'invite_to_edit' MAILBOXER_CODE_INVITE_TO_EDIT + + when 'map_activity' + MAILBOXER_CODE_MAP_ACTIVITY + when 'map_collaborator_added' + MAILBOXER_CODE_MAP_COLLABORATOR_ADDED + when 'map_updated' + MAILBOXER_CODE_MAP_UPDATED + when 'map_message' + MAILBOXER_CODE_MAP_MESSAGE + when 'map_starred' + MAILBOXER_CODE_MAP_STARRED + + when 'topic_added_to_map' + MAILBOXER_CODE_TOPIC_ADDED_TO_MAP + when 'topic_connected' + MAILBOXER_CODE_TOPIC_CONNECTED + when 'topic_deleted' + MAILBOXER_CODE_TOPIC_DELETED + when 'topic_disconnected' + MAILBOXER_CODE_TOPIC_DISCONNECTED + when 'topic_updated' + MAILBOXER_CODE_TOPIC_UPDATED end end + def self.get_subject_for_event(entity, event_type, event) + case event_type + when 'access_approved' # event is an AccessRequest + entity.name + ' - access approved' + when 'access_request' # event is an AccessRequest + entity.name + ' - request to edit' + when 'invite_to_edit' # event is a UserMap + entity.name + ' - invited to edit' + + when 'map_activity' #disabled + 'placeholder' + when 'map_collaborator_added' #disabled + 'placeholder' + when 'map_updated' #disabled + 'placeholder' + when 'map_message' # event is a Message + entity.name + ' - received a chat message' + when 'map_starred' # event is a Star + entity.name + ' was starred by ' + event.user.name + + when 'topic_added_to_map' # event is an Event::TopicAddedToMap + entity.name + ' was added to map ' + event.map.name + when 'topic_connected' # event is a Synapse + 'new synapse to topic ' + entity.name + when 'topic_deleted' #disabled + 'placeholder' + when 'topic_disconnected' #disabled + 'placeholder' + when 'topic_updated' #disabled + 'placeholder' + end + end + + def self.send_for_follows(follows, entity, event_type, event) + return if follows.length == 0 + template = get_template_for_event_type(event_type) + mailboxer_code = get_mailboxer_code_for_event_type(event_type) + subject = get_subject_for_event(entity, event_type, event) + # 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: template, locals: { entity: entity, event: event }, layout: false) + follows.each{|follow| + # don't send if they've indicated disinterest in this event_type + return unless follow.follow_type.all || follow.follow_type.read_attribute(event_type) + # this handles email and in-app notifications, in the future, include push + receipt = follow.user.notify(subject, body, event, false, mailboxer_code, (follow.user.emails_allowed && follow.email), event.user) + # push could be handled with Actioncable to send transient notifications to the UI + # the receipt from the notify call could be used to link to the full notification + } + end + + def self.notify_followers(entity, event_type, event, reason_filter = nil) + follows = entity.follows + + if reason_filter.class == String && FollowReason::REASONS.include?(reason_filter) + follows = follows.joins(:follow_reason).where('follow_reasons.' + reason_filter => true) + elsif reason_filter.class == Array + # TODO: throw an error here if all the reasons aren't valid + follows = follows.joins(:follow_reason).where(reason_filter.map{|r| "follow_reasons.#{r} = 't'"}.join(' OR ')) + end + # filter out the person who took the action + follows = follows.to_a.delete_if{|f| f.user.id == event.user.id} + send_for_follows(follows, entity, event_type, event) + end + + + # TODO: refactor this def self.access_request(request) event_type = 'access_request' template = get_template_for_event_type(event_type) mailboxer_code = get_mailboxer_code_for_event_type(event_type) + subject = get_subject_for_event(request.map, event_type, request) body = renderer.render(template: template, locals: { map: request.map, request: request }, layout: false) - request.map.user.notify(request.requested_text, body, request, false, mailboxer_code, true, request.user) + request.map.user.notify(subject, body, request, false, mailboxer_code, true, request.user) end + # TODO: refactor this def self.access_approved(request) event_type = 'access_approved' template = get_template_for_event_type(event_type) mailboxer_code = get_mailboxer_code_for_event_type(event_type) + subject = get_subject_for_event(request.map, event_type, request) body = renderer.render(template: template, locals: { map: request.map }, layout: false) - request.user.notify(request.approved_text, body, request, false, mailboxer_code, true, request.map.user) + request.user.notify(subject, body, request, false, mailboxer_code, true, request.map.user) end + # TODO: refactor this def self.invite_to_edit(user_map) event_type = 'invite_to_edit' template = get_template_for_event_type(event_type) mailboxer_code = get_mailboxer_code_for_event_type(event_type) + subject = get_subject_for_event(user_map.map, event_type, user_map) body = renderer.render(template: template, locals: { map: user_map.map, inviter: user_map.map.user }, layout: false) - user_map.user.notify(user_map.map.invited_text, body, user_map, false, mailboxer_code, true, user_map.map.user) + user_map.user.notify(subject, body, user_map, false, mailboxer_code, true, user_map.map.user) end # note: this is a global function, probably called from the rails console with some html body @@ -71,6 +164,20 @@ class NotificationService when MAILBOXER_CODE_INVITE_TO_EDIT map = notification.notified_object.map 'gave you edit access to map ' + map.name + '' + when MAILBOXER_CODE_MAP_MESSAGE + map = notification.notified_object.resource + 'commented on map ' + map.name + '' + when MAILBOXER_CODE_MAP_STARRED + map = notification.notified_object.map + 'starred map ' + map.name + '' + when MAILBOXER_CODE_TOPIC_ADDED_TO_MAP + topic = notification.notified_object.eventable + map = notification.notified_object.map + 'added topic ' + topic.name + ' to map ' + map.name + '' + when MAILBOXER_CODE_TOPIC_CONNECTED + topic1 = notification.notified_object.topic1 + topic2 = notification.notified_object.topic2 + 'connected ' + topic1.name + ' to ' + topic2.name + '' when MAILBOXER_CODE_MESSAGE_FROM_DEVS notification.subject end diff --git a/app/views/map_mailer/map_activity.html.erb b/app/views/map_mailer/map_activity.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_activity.text.erb b/app/views/map_mailer/map_activity.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_collaborator_added.html.erb b/app/views/map_mailer/map_collaborator_added.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_collaborator_added.text.erb b/app/views/map_mailer/map_collaborator_added.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_message.html.erb b/app/views/map_mailer/map_message.html.erb new file mode 100644 index 00000000..621f39f8 --- /dev/null +++ b/app/views/map_mailer/map_message.html.erb @@ -0,0 +1,5 @@ +<% button_style = "background-color:#4fc059;border-radius:2px;color:white;display:inline-block;font-family:Roboto,Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;min-height:29px;line-height:29px;min-width:54px;outline:0px;padding:0 8px;text-align:center;text-decoration:none" %> +

<%= event.user.name %> added a chat message to map <%= entity.name %>

+

<%= event.message %>

+ +<%= link_to 'Go to Map', map_url(entity), style: button_style %> \ No newline at end of file diff --git a/app/views/map_mailer/map_message.text.erb b/app/views/map_mailer/map_message.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_starred.html.erb b/app/views/map_mailer/map_starred.html.erb new file mode 100644 index 00000000..ac051536 --- /dev/null +++ b/app/views/map_mailer/map_starred.html.erb @@ -0,0 +1,3 @@ +<% button_style = "background-color:#4fc059;border-radius:2px;color:white;display:inline-block;font-family:Roboto,Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;min-height:29px;line-height:29px;min-width:54px;outline:0px;padding:0 8px;text-align:center;text-decoration:none" %> +

<%= event.user.name %> starred map <%= entity.name %>

+<%= link_to 'Go to Map', map_url(entity), style: button_style %> \ No newline at end of file diff --git a/app/views/map_mailer/map_starred.text.erb b/app/views/map_mailer/map_starred.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_updated.html.erb b/app/views/map_mailer/map_updated.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/map_updated.text.erb b/app/views/map_mailer/map_updated.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_added_to_map.html.erb b/app/views/map_mailer/topic_added_to_map.html.erb new file mode 100644 index 00000000..8c61fc64 --- /dev/null +++ b/app/views/map_mailer/topic_added_to_map.html.erb @@ -0,0 +1,9 @@ +<% button_style = "background-color:#4fc059;border-radius:2px;color:white;display:inline-block;font-family:Roboto,Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;min-height:29px;line-height:29px;min-width:54px;outline:0px;padding:0 8px;text-align:center;text-decoration:none" %> +

+ <%= event.user.name %> + added topic <%= entity.name %> + to map <%= event.map.name %> +

+ +<%= link_to 'Go to Topic', topic_url(entity), style: button_style %> +<%= link_to 'Go to Map', map_url(event.map), style: button_style %> \ No newline at end of file diff --git a/app/views/map_mailer/topic_added_to_map.text.erb b/app/views/map_mailer/topic_added_to_map.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_connected.html.erb b/app/views/map_mailer/topic_connected.html.erb new file mode 100644 index 00000000..d190d878 --- /dev/null +++ b/app/views/map_mailer/topic_connected.html.erb @@ -0,0 +1,15 @@ +<% button_style = "background-color:#4fc059;border-radius:2px;color:white;display:inline-block;font-family:Roboto,Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;min-height:29px;line-height:29px;min-width:54px;outline:0px;padding:0 8px;text-align:center;text-decoration:none" %> + +<% topic1 = entity %> +<% topic2 = (entity.id == event.topic1_id ? event.topic2 : event.topic1) %> + +

+ <%= event.user.name %> + connected topic <%= topic1.name %> + to topic <%= topic2.name %> + <% if event.desc %> + with the description "<%= event.desc %>". + <% end %> +

+ +<%= link_to 'View the connection', topic_url(topic1), style: button_style %> \ No newline at end of file diff --git a/app/views/map_mailer/topic_connected.text.erb b/app/views/map_mailer/topic_connected.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_deleted.html.erb b/app/views/map_mailer/topic_deleted.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_deleted.text.erb b/app/views/map_mailer/topic_deleted.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_disconnected.html.erb b/app/views/map_mailer/topic_disconnected.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_disconnected.text.erb b/app/views/map_mailer/topic_disconnected.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_updated.html.erb b/app/views/map_mailer/topic_updated.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/map_mailer/topic_updated.text.erb b/app/views/map_mailer/topic_updated.text.erb new file mode 100644 index 00000000..e69de29b diff --git a/config/initializers/mailboxer.rb b/config/initializers/mailboxer.rb index cc0b520c..8409132a 100644 --- a/config/initializers/mailboxer.rb +++ b/config/initializers/mailboxer.rb @@ -7,11 +7,31 @@ # notification_code: MAILBOXER_CODE_ACCESS_REQUEST # }, # which would imply that this is an access request to Map.find(1) -MAILBOXER_CODE_ACCESS_REQUEST = 'ACCESS_REQUEST' -MAILBOXER_CODE_ACCESS_APPROVED = 'ACCESS_APPROVED' -MAILBOXER_CODE_INVITE_TO_EDIT = 'INVITE_TO_EDIT' MAILBOXER_CODE_MESSAGE_FROM_DEVS = 'MESSAGE_FROM_DEVS' +# these ones are old and can't change without a migration +MAILBOXER_CODE_ACCESS_APPROVED = 'ACCESS_APPROVED' +MAILBOXER_CODE_ACCESS_REQUEST = 'ACCESS_REQUEST' +MAILBOXER_CODE_INVITE_TO_EDIT = 'INVITE_TO_EDIT' + +# these ones are new +# this one's a catch all for edits ON the map +MAILBOXER_CODE_MAP_ACTIVITY = 'MAP_ACTIVITY' +# MAILBOXER_CODE_MAP_ADDED_TO_MAP = 'MAP_ADDED_TO_MAP' +MAILBOXER_CODE_MAP_COLLABORATOR_ADDED = 'MAP_COLLABORATOR_ADDED' +# BOTHER WITH MAP_COLLABORATOR_REMOVED ? +MAILBOXER_CODE_MAP_UPDATED = 'MAP_UPDATED' # this refers to the map object itself: name, desc, permission, etc +# ADD MAP_FORKED +MAILBOXER_CODE_MAP_MESSAGE = 'MAP_MESSAGE' +MAILBOXER_CODE_MAP_STARRED = 'MAP_STARRED' + +MAILBOXER_CODE_TOPIC_ADDED_TO_MAP = 'TOPIC_ADDED_TO_MAP' +MAILBOXER_CODE_TOPIC_CONNECTED = 'TOPIC_CONNECTED' +MAILBOXER_CODE_TOPIC_DELETED = 'TOPIC_DELETED' +MAILBOXER_CODE_TOPIC_DISCONNECTED = 'TOPIC_DISCONNECTED' +MAILBOXER_CODE_TOPIC_UPDATED = 'TOPIC_UPDATED' +# BOTHER WITH TOPIC_REMOVED_FROM_MAP ? + Mailboxer.setup do |config| # Configures if your application uses or not email sending for Notifications and Messages config.uses_emails = true diff --git a/db/migrate/20170209215819_create_follows.rb b/db/migrate/20170209215819_create_follows.rb new file mode 100644 index 00000000..2999a643 --- /dev/null +++ b/db/migrate/20170209215819_create_follows.rb @@ -0,0 +1,12 @@ +class CreateFollows < ActiveRecord::Migration[5.0] + def change + create_table :follows do |t| + t.references :user, index: true + t.boolean :email, default: true + t.boolean :app, default: true + t.boolean :push, default: true + t.references :followed, polymorphic: true, index: true + t.timestamps + end + end +end diff --git a/db/migrate/20170209215911_create_follow_reasons.rb b/db/migrate/20170209215911_create_follow_reasons.rb new file mode 100644 index 00000000..3f29af06 --- /dev/null +++ b/db/migrate/20170209215911_create_follow_reasons.rb @@ -0,0 +1,14 @@ +class CreateFollowReasons < ActiveRecord::Migration[5.0] + def change + create_table :follow_reasons do |t| + t.references :follow, index: true + t.boolean :created + t.boolean :contributed + t.boolean :commented + t.boolean :followed + t.boolean :shared_on + t.boolean :starred + t.timestamps + end + end +end diff --git a/db/migrate/20170209215920_create_follow_types.rb b/db/migrate/20170209215920_create_follow_types.rb new file mode 100644 index 00000000..9bf1353a --- /dev/null +++ b/db/migrate/20170209215920_create_follow_types.rb @@ -0,0 +1,22 @@ +class CreateFollowTypes < ActiveRecord::Migration[5.0] + def change + create_table :follow_types do |t| + t.references :follow, index: true + t.boolean :all, default: true + t.boolean :acccess_approved + t.boolean :access_request + t.boolean :invite_to_edit + t.boolean :map_activity + t.boolean :map_collaborator_added + t.boolean :map_message + t.boolean :map_starred + t.boolean :map_updated + t.boolean :topic_added_to_map + t.boolean :topic_connected + t.boolean :topic_deleted + t.boolean :topic_disconnected + t.boolean :topic_updated + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index a2fc31b1..235ab552 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170208161305) do +ActiveRecord::Schema.define(version: 20170209215920) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -67,6 +67,53 @@ ActiveRecord::Schema.define(version: 20170208161305) do t.index ["user_id"], name: "index_events_on_user_id", using: :btree end + create_table "follow_reasons", force: :cascade do |t| + t.integer "follow_id" + t.boolean "created" + t.boolean "contributed" + t.boolean "commented" + t.boolean "followed" + t.boolean "shared_on" + t.boolean "starred" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["follow_id"], name: "index_follow_reasons_on_follow_id", using: :btree + end + + create_table "follow_types", force: :cascade do |t| + t.integer "follow_id" + t.boolean "all", default: true + t.boolean "acccess_approved" + t.boolean "access_request" + t.boolean "invite_to_edit" + t.boolean "map_activity" + t.boolean "map_collaborator_added" + t.boolean "map_message" + t.boolean "map_starred" + t.boolean "map_updated" + t.boolean "topic_added_to_map" + t.boolean "topic_connected" + t.boolean "topic_deleted" + t.boolean "topic_disconnected" + t.boolean "topic_updated" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["follow_id"], name: "index_follow_types_on_follow_id", using: :btree + end + + create_table "follows", force: :cascade do |t| + t.integer "user_id" + t.boolean "email", default: true + t.boolean "app", default: true + t.boolean "push", default: true + t.string "followed_type" + t.integer "followed_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["followed_type", "followed_id"], name: "index_follows_on_followed_type_and_followed_id", using: :btree + t.index ["user_id"], name: "index_follows_on_user_id", using: :btree + end + create_table "in_metacode_sets", force: :cascade do |t| t.integer "metacode_id" t.integer "metacode_set_id"