FEATURE: allows to set reminder

FEATURE: allows to set reminder

Note that reminders; as custom fields, are only editable on created event and not when creating it.

diff --git a/app/controllers/discourse_post_event/events_controller.rb b/app/controllers/discourse_post_event/events_controller.rb
index fe31606..a55727a 100644
--- a/app/controllers/discourse_post_event/events_controller.rb
+++ b/app/controllers/discourse_post_event/events_controller.rb
@@ -36,7 +36,7 @@ module DiscoursePostEvent
     end
 
     def show
-      event = Event.find(params[:id])
+      event = Event.includes(:reminders).find(params[:id])
       guardian.ensure_can_see!(event.post)
       serializer = EventSerializer.new(event, scope: guardian)
       render_json_dump(serializer)
@@ -56,6 +56,7 @@ module DiscoursePostEvent
         guardian.ensure_can_edit!(event.post)
         guardian.ensure_can_act_on_discourse_post_event!(event)
         event.update_with_params!(event_params)
+        event.update_reminders!(event_reminders_params)
         serializer = EventSerializer.new(event, scope: guardian)
         render_json_dump(serializer)
       end
@@ -131,6 +132,10 @@ module DiscoursePostEvent
 
     private
 
+    def event_reminders_params
+      Array(params.require(:event).permit(reminders: [:id, :value, :unit])[:reminders])
+    end
+
     def event_params
       allowed_custom_fields = SiteSetting.discourse_post_event_allowed_custom_fields.split('|')
 
@@ -144,7 +149,7 @@ module DiscoursePostEvent
           :status,
           :url,
           custom_fields: allowed_custom_fields,
-          raw_invitees: []
+          raw_invitees: [],
         )
     end
 
diff --git a/app/controllers/discourse_post_event/reminders_controller.rb b/app/controllers/discourse_post_event/reminders_controller.rb
new file mode 100644
index 0000000..2577c0d
--- /dev/null
+++ b/app/controllers/discourse_post_event/reminders_controller.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module DiscoursePostEvent
+  class RemindersController < DiscoursePostEventController
+    def destroy
+      event = Event.find_by(id: params[:post_id])
+      reminder = event.reminders.find_by(id: params[:id])
+      guardian.ensure_can_act_on_discourse_post_event!(event)
+      Jobs.cancel_scheduled_job(:discourse_post_event_send_reminder, reminder_id: reminder.id)
+      reminder.destroy!
+      render json: success_json
+    end
+  end
+end
diff --git a/app/models/discourse_post_event/event.rb b/app/models/discourse_post_event/event.rb
index 4ae4b81..b9b9518 100644
--- a/app/models/discourse_post_event/event.rb
+++ b/app/models/discourse_post_event/event.rb
@@ -34,34 +34,41 @@ module DiscoursePostEvent
       end
     end
 
-    after_commit :setup_starts_at_handler, on: [:create, :update]
-    def setup_starts_at_handler
-      if !transaction_include_any_action?([:create])
+    after_commit :setup_handlers, on: [:create, :update]
+    def setup_handlers
+      starts_at_changes = saved_change_to_starts_at
+      if starts_at_changes
+        new_starts_at = starts_at_changes[1]
+
         Jobs.cancel_scheduled_job(:discourse_post_event_event_started, event_id: self.id)
         Jobs.cancel_scheduled_job(:discourse_post_event_event_will_start, event_id: self.id)
-      end
 
-      if self.starts_at > Time.now
-        Jobs.enqueue_at(self.starts_at, :discourse_post_event_event_started, event_id: self.id)
+        if new_starts_at > Time.now
+          Jobs.enqueue_at(new_starts_at, :discourse_post_event_event_started, event_id: self.id)
 
-        if self.starts_at - 1.hour > Time.now
-          Jobs.enqueue_at(self.starts_at - 1.hour, :discourse_post_event_event_will_start, event_id: self.id)
+          will_start_at = new_starts_at - 1.hour
+          if will_start_at > Time.now
+            Jobs.enqueue_at(will_start_at, :discourse_post_event_event_will_start, event_id: self.id)
+          end
         end
+
+        self.refresh_reminders!
       end
-    end
 
-    after_commit :setup_ends_at_handler, on: [:create, :update]
-    def setup_ends_at_handler
-      if !transaction_include_any_action?([:create])
+      ends_at_changes = saved_change_to_ends_at
+      if ends_at_changes
+        new_ends_at = ends_at_changes[1]
+
         Jobs.cancel_scheduled_job(:discourse_post_event_event_ended, event_id: self.id)
-      end
 
-      if self.ends_at && self.ends_at > Time.now
-        Jobs.enqueue_at(self.ends_at, :discourse_post_event_event_ended, event_id: self.id)
+        if new_ends_at && new_ends_at > Time.now
+          Jobs.enqueue_at(new_ends_at, :discourse_post_event_event_ended, event_id: self.id)
+        end
       end
     end
 
     has_many :invitees, foreign_key: :post_id, dependent: :delete_all
+    has_many :reminders, foreign_key: :post_id, dependent: :delete_all
     belongs_to :post, foreign_key: :id
 
     scope :visible, -> { where(deleted_at: nil) }
@@ -219,14 +226,12 @@ module DiscoursePostEvent
 
       if events.present?
         event_params = events.first
-
         event = post.event || DiscoursePostEvent::Event.new(id: post.id)
-
         params = {
           name: event_params[:name],
           starts_at: event_params[:start] || event.starts_at,
           ends_at: event_params[:end],
-          url: event_params[:"url"],
+          url: event_params[:url],
           status: event_params[:status].present? ? Event.statuses[event_params[:status].to_sym] : event.status,
           raw_invitees: event_params[:"allowed-groups"] ? event_params[:"allowed-groups"].split(',') : nil
         }
@@ -254,5 +259,20 @@ module DiscoursePostEvent
 
       self.publish_update!
     end
+
+    def refresh_reminders!
+      self.reminders.each(&:refresh!)
+    end
+
+    def update_reminders!(reminders)
+      reminders.each do |reminder|
+        if reminder[:id]
+          model = Reminder.find(reminder[:id])
+          model.update!(value: reminder[:value], unit: reminder[:unit])
+        else
+          model = Reminder.create!(value: reminder[:value], unit: reminder[:unit], post_id: self.id)
+        end
+      end
+    end
   end
 end
diff --git a/app/models/discourse_post_event/reminder.rb b/app/models/discourse_post_event/reminder.rb
new file mode 100644
index 0000000..f36c775
--- /dev/null
+++ b/app/models/discourse_post_event/reminder.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module DiscoursePostEvent
+  class Reminder < ActiveRecord::Base
+    self.table_name = 'discourse_post_event_reminders'
+
+    belongs_to :event, foreign_key: :post_id
+
+    def self.means
+      @means ||= Enum.new(notification: 0)
+    end
+
+    after_commit :refresh!, on: [:create, :update]
+    def refresh!
+      if transaction_include_any_action?([:update])
+        Jobs.cancel_scheduled_job(:discourse_post_event_send_reminder, reminder_id: self.id)
+      end
+
+      enqueue_at = self.event.starts_at - self.value.send(self.unit)
+      if enqueue_at > Time.now
+        Jobs.enqueue_at(enqueue_at, :discourse_post_event_send_reminder, reminder_id: self.id)
+      end
+    end
+  end
+end
diff --git a/app/serializers/discourse_post_event/event_serializer.rb b/app/serializers/discourse_post_event/event_serializer.rb
index ee4e424..b055a5b 100644
--- a/app/serializers/discourse_post_event/event_serializer.rb
+++ b/app/serializers/discourse_post_event/event_serializer.rb
@@ -22,6 +22,7 @@ module DiscoursePostEvent
     attributes :is_public
     attributes :is_private
     attributes :is_standalone
+    attributes :reminders
 
     def can_act_on_discourse_post_event
       scope.can_act_on_discourse_post_event?(object)
diff --git a/assets/javascripts/discourse/adapters/discourse-post-event-invitee.js.es6 b/assets/javascripts/discourse/adapters/discourse-post-event-invitee.js.es6
index c925805..1ba0316 100644
--- a/assets/javascripts/discourse/adapters/discourse-post-event-invitee.js.es6
+++ b/assets/javascripts/discourse/adapters/discourse-post-event-invitee.js.es6
@@ -1,68 +1,6 @@
-import { Result } from "discourse/adapters/rest";
-import { ajax } from "discourse/lib/ajax";

[... diff too long, it was truncated ...]

GitHub sha: da91f741