Browse Source

feat: add notification banner, use unread gem for notification management

pull/2131/head
natdeanlewissoftwire 2 years ago
parent
commit
7716c5c680
  1. 1
      Gemfile
  2. 15
      app/components/unread_notification.html.erb
  3. 12
      app/components/unread_notification.rb
  4. 8
      app/controllers/notifications_controller.rb
  5. 7
      app/frontend/styles/_unread-notification.scss
  6. 5
      app/frontend/styles/application.scss
  7. 3
      app/models/notification.rb
  8. 2
      app/models/user.rb
  9. 9
      app/views/layouts/application.html.erb
  10. 4
      config/routes.rb
  11. 24
      db/migrate/20240108152935_unread_migration.rb
  12. 13
      db/schema.rb

1
Gemfile

@ -64,6 +64,7 @@ gem "auto_strip_attributes"
# Use sidekiq for background processing # Use sidekiq for background processing
gem "sidekiq" gem "sidekiq"
gem "sidekiq-cron" gem "sidekiq-cron"
gem "unread"
group :development, :test do group :development, :test do
# Check gems for known vulnerabilities # Check gems for known vulnerabilities

15
app/components/unread_notification.html.erb

@ -0,0 +1,15 @@
<div class="app-unread-notification">
<div class="govuk-width-container">
<br>
<div class="govuk-grid-row">
<div class="govuk-grid-column-three-quarters govuk-body">
<p class="govuk-!-font-weight-bold"><%= oldest_unread_notification.title %></p>
<%= govuk_link_to oldest_unread_notification.link_text, notification_path(oldest_unread_notification), class: "govuk-link--inverse govuk-!-font-weight-bold"%>
</div>
<p class="govuk-grid-column-one-quarter govuk-!-text-align-right ">
<%= govuk_link_to "Dismiss", notification_dismiss_path(oldest_unread_notification), class: "govuk-link--inverse"%>
</p>
</div>
<br>
</div>
</div>

12
app/components/unread_notification.rb

@ -0,0 +1,12 @@
class UnreadNotification < ViewComponent::Base
attr_reader :current_user
def initialize(current_user:)
@current_user = current_user
super
end
def oldest_unread_notification
Notification.unread_by(@current_user).first
end
end

8
app/controllers/notifications_controller.rb

@ -0,0 +1,8 @@
class NotificationsController < ApplicationController
def dismiss
Notification.find(params[:notification_id]).mark_as_read! for: current_user
redirect_to root_path
end
end

7
app/frontend/styles/_unread-notification.scss

@ -0,0 +1,7 @@
.app-unread-notification {
background-color: govuk-colour("blue");
}
.app-unread-notification p {
color: govuk-colour("white");
}

5
app/frontend/styles/application.scss

@ -25,7 +25,9 @@ $govuk-breakpoints: (
@import "accessible-autocomplete"; @import "accessible-autocomplete";
@import "button"; @import "button";
@import "card"; @import "card";
@import "delete-logs-table";
@import "document-list"; @import "document-list";
@import "errors";
@import "feedback"; @import "feedback";
@import "filter"; @import "filter";
@import "filter-layout"; @import "filter-layout";
@ -43,8 +45,7 @@ $govuk-breakpoints: (
@import "primary-navigation"; @import "primary-navigation";
@import "search"; @import "search";
@import "sub-navigation"; @import "sub-navigation";
@import "errors"; @import "unread-notification";
@import "delete-logs-table";
// App utilities // App utilities
.app-\!-colour-muted { .app-\!-colour-muted {

3
app/models/notification.rb

@ -0,0 +1,3 @@
class Notification < ApplicationRecord
acts_as_readable
end

2
app/models/user.rb

@ -1,4 +1,6 @@
class User < ApplicationRecord class User < ApplicationRecord
acts_as_reader
# Include default devise modules. Others available are: # Include default devise modules. Others available are:
# :omniauthable # :omniauthable
devise :database_authenticatable, :recoverable, :rememberable, devise :database_authenticatable, :recoverable, :rememberable,

9
app/views/layouts/application.html.erb

@ -101,6 +101,11 @@
end end
end %> end %>
<% if current_user.present? && current_page?("/") && Notification.unread_by(current_user).present? %>
<%= render UnreadNotification.new(current_user:) %>
<% end %>
<% feedback_link = govuk_link_to "giving us your feedback (opens in a new tab)", t("feedback_form"), rel: "noreferrer noopener", target: "_blank" %> <% feedback_link = govuk_link_to "giving us your feedback (opens in a new tab)", t("feedback_form"), rel: "noreferrer noopener", target: "_blank" %>
<%= govuk_phase_banner( <%= govuk_phase_banner(
@ -109,7 +114,7 @@
text: "This is a new service – help us improve it by #{feedback_link}".html_safe, text: "This is a new service – help us improve it by #{feedback_link}".html_safe,
) %> ) %>
<% if !current_user.nil? %> <% if current_user.present? %>
<%= render PrimaryNavigationComponent.new( <%= render PrimaryNavigationComponent.new(
items: primary_items(request.path, current_user), items: primary_items(request.path, current_user),
) %> ) %>
@ -124,7 +129,7 @@
<%= govuk_notification_banner( <%= govuk_notification_banner(
title_text: "Success", title_text: "Success",
success: true, title_heading_level: 3, success: true, title_heading_level: 3,
title_id: "swanky-notifications" title_id: "flash-notice"
) do |notification_banner| ) do |notification_banner|
notification_banner.heading(text: flash.notice.html_safe) notification_banner.heading(text: flash.notice.html_safe)
if flash[:notification_banner_body] if flash[:notification_banner_body]

4
config/routes.rb

@ -128,6 +128,10 @@ Rails.application.routes.draw do
end end
end end
resources :notifications do
get "dismiss", to: "notifications#dismiss"
end
resources :organisations do resources :organisations do
get "duplicates", to: "duplicate_logs#index" get "duplicates", to: "duplicate_logs#index"

24
db/migrate/20240108152935_unread_migration.rb

@ -0,0 +1,24 @@
class UnreadMigration < ActiveRecord::Migration[6.0]
def self.up
create_table ReadMark, force: true, options: create_options do |t|
t.references :readable, polymorphic: { null: false }
t.references :reader, polymorphic: { null: false }
t.datetime :timestamp, null: false
end
add_index ReadMark, [:reader_id, :reader_type, :readable_type, :readable_id], name: 'read_marks_reader_readable_index', unique: true
end
def self.down
drop_table ReadMark
end
def self.create_options
options = ''
if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) \
&& ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
options = 'DEFAULT CHARSET=latin1'
end
options
end
end

13
db/schema.rb

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2024_01_08_145545) do ActiveRecord::Schema[7.0].define(version: 2024_01_08_152935) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -457,6 +457,17 @@ ActiveRecord::Schema[7.0].define(version: 2024_01_08_145545) do
t.index ["old_visible_id"], name: "index_organisations_on_old_visible_id", unique: true t.index ["old_visible_id"], name: "index_organisations_on_old_visible_id", unique: true
end end
create_table "read_marks", force: :cascade do |t|
t.string "readable_type", null: false
t.bigint "readable_id"
t.string "reader_type", null: false
t.bigint "reader_id"
t.datetime "timestamp", precision: nil, null: false
t.index ["readable_type", "readable_id"], name: "index_read_marks_on_readable_type_and_readable_id"
t.index ["reader_id", "reader_type", "readable_type", "readable_id"], name: "read_marks_reader_readable_index", unique: true
t.index ["reader_type", "reader_id"], name: "index_read_marks_on_reader_type_and_reader_id"
end
create_table "sales_logs", force: :cascade do |t| create_table "sales_logs", force: :cascade do |t|
t.integer "status", default: 0 t.integer "status", default: 0
t.datetime "saledate" t.datetime "saledate"

Loading…
Cancel
Save