Skip to content
Merged
15 changes: 11 additions & 4 deletions app/controllers/admin/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ def show
end

def create
@notification = Notification.new(summary: notification_params[:summary],
notification_message: notification_params[:notification_message],
user: current_user['email'], published: true, published_at: Time.zone.now)
@notification = create_notifications
Notification.transaction do
if @notification.save
flash[:success] = 'Notification created successfully.'
Expand Down Expand Up @@ -55,6 +53,15 @@ def unpublish
private

def notification_params
params.require(:notification).permit(:summary, :notification_message)
params.require(:notification).permit(:summary, :notification_message, :stop_datetime)
end

def create_notifications
Notification.new(summary: notification_params[:summary],
notification_message: notification_params[:notification_message],
user: current_user['email'],
published: true,
published_at: Time.zone.now,
stop_datetime: notification_params[:stop_datetime])
end
end
1 change: 1 addition & 0 deletions app/controllers/v1/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class V1::NotificationsController < ApiController
def index
Notification.expire_past_due!
markdown_parser = Redcarpet::Markdown.new(CustomMarkdownRenderer)
notifications = Notification.published.first
notifications[:notification_message] = markdown_parser.render(notifications[:notification_message]) if notifications
Expand Down
20 changes: 20 additions & 0 deletions app/models/notification.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
class Notification < ApplicationRecord
validates :summary, :notification_message, presence: true
validate :stop_datetime_in_future

before_save :ensure_single_published_notification

scope :published, -> { where(published: true) }
scope :currently_active, lambda {
where(published: true)
.where('stop_datetime IS NULL OR stop_datetime > ?', Time.current)
}

def unpublish!
self.published = false
self.unpublished_at = Time.zone.now
save!
end

def self.expire_past_due!
expired = where('stop_datetime < ? AND published = ?', Time.current, true)
# We use update_all for performance to expire records in a single
# SQL query, bypassing validations for speed on every API request.
# rubocop:disable Rails/SkipsModelValidations
expired.update_all(published: false, unpublished_at: Time.zone.now)
# rubocop:enable Rails/SkipsModelValidations
end

private

def ensure_single_published_notification
return unless published_changed? && published?

Notification.where.not(id: id).where(published: true).find_each(&:unpublish!)
end

def stop_datetime_in_future
return unless stop_datetime.present? && stop_datetime < Time.current

errors.add(:stop_datetime, 'must be in the future')
end
end
2 changes: 2 additions & 0 deletions app/views/admin/notifications/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
%th.govuk-table__header Header
%th.govuk-table__header Published
%th.govuk-table__header Unpublished
%th.govuk-table__header Date time to Unpublish
%tbody.govuk-table__body
- @notifications.each do |notification|
%tr.govuk-table__row
%td.govuk-table__cell= link_to notification.summary, admin_notification_path(notification.id)
%td.govuk-table__cell= notification.published_at
%td.govuk-table__cell= notification.unpublished_at
%td.govuk-table__cell= notification.stop_datetime
29 changes: 26 additions & 3 deletions app/views/admin/notifications/new.html.haml
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
.govuk-grid-row
.govuk-grid-column-two-thirds
= link_to 'Back', admin_notifications_path, { class: 'govuk-back-link govuk-!-margin-bottom-5', title: 'Back to notifications' }

= simple_form_for [:admin, @notification] do |form|
%fieldset.govuk-fieldset
%legend.govuk-fieldset__legend.govuk-fieldset__legend--xl
%h1.govuk-fieldset__heading
Create a new notification

= form.input :summary, hide_optional: true, input_html: { value: @published_notification&.summary }
= form.input :notification_message, label: 'Notification message', hide_optional: true, wrapper: :govuk_textarea_wrapper, input_html: { rows: '10', value: @published_notification&.notification_message }
= form.input :summary,
hide_optional: true,
input_html: { value: @notification.summary || @published_notification&.summary }

= form.input :notification_message,
label: 'Notification message',
hide_optional: true,
wrapper: :govuk_textarea_wrapper,
input_html: { rows: '10', value: @notification.notification_message || @published_notification&.notification_message }

.govuk-form-group{class: ("govuk-form-group--error" if @notification.errors[:stop_datetime].any?)}
%label.govuk-label{ for: "notification_stop_datetime" }
Unpublish on

- if @notification.errors[:stop_datetime].any?
%span.govuk-error-message
%span.govuk-visually-hidden Error:
= @notification.errors[:stop_datetime].join(', ')

- current_date = @notification.stop_datetime || @published_notification&.stop_datetime
= form.datetime_local_field :stop_datetime,
class: "govuk-input",
value: current_date&.strftime("%Y-%m-%dT%H:%M")
%button.govuk-button.govuk-button--secondary{ type: "button", onclick: "document.getElementById('notification_stop_datetime').value = ''", class: "govuk-!-margin-top-1" }
Clear date

%button#markdown-preview-btn{type: "button", class: 'govuk-button'} Preview
= form.button :submit, value: 'Publish Notification', data: { disable_with: "Publish Notification" }

Expand Down
6 changes: 6 additions & 0 deletions db/migrate/20260302_add_stop_datetime_to_notifications.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddStopDatetimeToNotifications < ActiveRecord::Migration[6.0]
def change
add_column :notifications, :stop_datetime, :datetime, null: true
add_index :notifications, :stop_datetime
end
end
Loading
Loading