pg_rails 7.0.8.pre.alpha.94 → 7.0.8.pre.alpha.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e21333fd287d450bce56ad59616a460a5f6113e7f28c7d934eddc833abe756a
4
- data.tar.gz: 1dcd5fe3cf91b2ca87acaec28b2fe5959f167cac952481613ac9b1a15df4906d
3
+ metadata.gz: 4c58d9873f250d2dd6439cb23e9a78d04439050bd55834021f46f829f42ea9c6
4
+ data.tar.gz: a4796df1040075127fcb5045d0ac6841dfd27e49326c17b6189ce41343d14c97
5
5
  SHA512:
6
- metadata.gz: 01d4202326e81d7f125d17fae6ee75f39d993802d66b45ea8af9cf844206cbef1a239e819de4d4a4e289d63e31c596ec3957b69f3ba66ec13a07816be1e48d45
7
- data.tar.gz: c874ed529e846c531314eb161f1933d9d9e471735a88ecd7eeba3d046ac3f7f34bd8793c309ee154c6286a83ce16bedfbfbb196e096045f4cf8d606097300c18
6
+ metadata.gz: ff4ab5046138fc43e3e5e4ffb4e9047bc7082d7a72c67809d42af3dd35027c5eadd27755d7cec9b42cba57d9b43fa68ced6bcce4d10b3615df22af896a275eb3
7
+ data.tar.gz: 8446251043b39d5180a933cea8bd561d05f17b421951ac69654fcb358075679c0775a06bd2580f82fcd4d0497a65522039ada390cd4422debc5b76258b65a0a8
@@ -0,0 +1,49 @@
1
+ #notifications {
2
+ display: flex;
3
+ align-items: center;
4
+ flex-direction: column;
5
+ gap: 5px;
6
+ background-color: #6a2a05;
7
+ padding: 1.5em 5px;
8
+ }
9
+
10
+ #notifications-inner {
11
+ max-width: 400px;
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: 0.4em;
15
+ }
16
+ .notification {
17
+ border: 1px solid #0003;
18
+ border-radius: 2px;
19
+ position: relative;
20
+ padding: 0.3em 2.5em;
21
+ xpadding-left: 2.5em;
22
+ display: flex;
23
+ align-items: center;
24
+ background-color: white;
25
+ }
26
+ .notification:not(.unseen) {
27
+ xcolor: #646464;
28
+ }
29
+ .notification.unseen {
30
+ background-color: rgb(230, 225, 251);
31
+ }
32
+ .notification.unseen::before {
33
+ content: '';
34
+ padding: 5px;
35
+ left: 1em;
36
+ vertical-align: middle;
37
+ position: absolute;
38
+ background-color: #079510;
39
+ border-radius: 50%;
40
+ }
41
+ .notifications-unseen-mark {
42
+ border: 1px solid #ffffff9d;
43
+ //background-color: #ea3d2b !important;
44
+ background-color: #079510;
45
+ }
46
+ .notification--time {
47
+ font-size: 0.8em;
48
+ min-width: 6em;
49
+ }
@@ -1,5 +1,8 @@
1
1
  @use 'sass:color';
2
2
 
3
+ @import 'notifications';
4
+
5
+
3
6
  :root,
4
7
  [data-bs-theme=light] {
5
8
  --bs-form-invalid-color: #b50000;
@@ -0,0 +1,19 @@
1
+ class NotificationComponent < BaseComponent
2
+ def initialize(notification: nil)
3
+ @notification = notification
4
+ super
5
+ end
6
+
7
+ erb_template <<~ERB
8
+ <div class="notification d-flex justify-content-between <%= 'unseen' if @notification.unseen? %>"
9
+ id="<%= dom_id(@notification) %>" data-id="<%= @notification.id %>">
10
+ <div>
11
+ <%= @notification.message %>
12
+ </div>
13
+ <div class="notification--time text-body-tertiary text-end ms-4">
14
+ hace
15
+ <%= distance_of_time_in_words @notification.created_at, Time.zone.now %>
16
+ </div>
17
+ </div>
18
+ ERB
19
+ end
@@ -79,6 +79,11 @@ module PgEngine
79
79
  if Rollbar.configuration.enabled && Rails.application.credentials.rollbar.present?
80
80
  @rollbar_token = Rails.application.credentials.rollbar.access_token_client
81
81
  end
82
+
83
+ if Current.user.present?
84
+ @notifications = Current.user.notifications.order(id: :desc)
85
+ @unseen_notifications = @notifications.unseen.any?
86
+ end
82
87
  end
83
88
 
84
89
  def mobile_device?
@@ -0,0 +1,11 @@
1
+ module Users
2
+ class NotificationsController < ApplicationController
3
+ def mark_as_seen
4
+ # No handleo errores porque no debería fallar, y si falla
5
+ # se notifica a rollbar y al user no le pasa nada
6
+ notifications = Noticed::Notification.where(id: params[:ids].split(','))
7
+ notifications.each(&:mark_as_seen!)
8
+ head :ok
9
+ end
10
+ end
11
+ end
@@ -19,7 +19,6 @@
19
19
  #
20
20
  # fk_rails_... (email_id => emails.id)
21
21
  #
22
- # generado con pg_rails
23
22
 
24
23
  class EmailLog < ApplicationRecord
25
24
  audited
@@ -38,6 +38,7 @@ class User < ApplicationRecord
38
38
 
39
39
  has_many :user_accounts
40
40
  has_many :accounts, through: :user_accounts
41
+ has_many :notifications, as: :recipient, class_name: 'Noticed::Notification'
41
42
 
42
43
  validates :nombre, :apellido, presence: true
43
44
 
@@ -0,0 +1,2 @@
1
+ class ApplicationNotifier < Noticed::Event
2
+ end
@@ -0,0 +1,28 @@
1
+ # To deliver this notification:
2
+ #
3
+ # SimpleUserNotifier.with(message: "New post").deliver(User.all, enqueue_job: false)
4
+
5
+ class SimpleUserNotifier < ApplicationNotifier
6
+ # Add your delivery methods
7
+ #
8
+ # deliver_by :email do |config|
9
+ # config.mailer = "UserMailer"
10
+ # config.method = "new_post"
11
+ # end
12
+ #
13
+ # bulk_deliver_by :slack do |config|
14
+ # config.url = -> { Rails.application.credentials.slack_webhook_url }
15
+ # end
16
+ #
17
+ # deliver_by :custom do |config|
18
+ # config.class = "MyDeliveryMethod"
19
+ # end
20
+ notification_methods do
21
+ def message
22
+ params[:message]
23
+ end
24
+ end
25
+ # Add required params
26
+ #
27
+ required_param :message
28
+ end
@@ -10,4 +10,7 @@ if defined?(AnyCable::Rails)
10
10
  AnyCable::Rails::Rack.middleware.use Warden::Manager do |config|
11
11
  Devise.warden_config = config
12
12
  end
13
+
14
+ # Lo dejo comentado porque no sé si hará falta
15
+ # AnyCable::Rails.extend_adapter!(ActionCable.server.pubsub) unless AnyCable::Rails.enabled?
13
16
  end
@@ -10,6 +10,9 @@ Rails.application.routes.draw do
10
10
  confirmations: 'users/confirmations',
11
11
  registrations: 'users/registrations'
12
12
  }, failure_app: PgEngine::DeviseFailureApp
13
+ namespace :users, path: 'u' do
14
+ post 'notifications/mark_as_seen', to: 'notifications#mark_as_seen'
15
+ end
13
16
  namespace :admin, path: 'a' do
14
17
  pg_resource(:emails)
15
18
  pg_resource(:email_logs) do
@@ -0,0 +1,37 @@
1
+ # This migration comes from noticed (originally 20231215190233)
2
+ class CreateNoticedTables < ActiveRecord::Migration[6.1]
3
+ def change
4
+ primary_key_type, foreign_key_type = primary_and_foreign_key_types
5
+ create_table :noticed_events, id: primary_key_type do |t|
6
+ t.string :type
7
+ t.belongs_to :record, polymorphic: true, type: foreign_key_type
8
+ if t.respond_to?(:jsonb)
9
+ t.jsonb :params
10
+ else
11
+ t.json :params
12
+ end
13
+
14
+ t.timestamps
15
+ end
16
+
17
+ create_table :noticed_notifications, id: primary_key_type do |t|
18
+ t.string :type
19
+ t.belongs_to :event, null: false, type: foreign_key_type
20
+ t.belongs_to :recipient, polymorphic: true, null: false, type: foreign_key_type
21
+ t.datetime :read_at
22
+ t.datetime :seen_at
23
+
24
+ t.timestamps
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def primary_and_foreign_key_types
31
+ config = Rails.configuration.generators
32
+ setting = config.options[config.orm][:primary_key_type]
33
+ primary_key_type = setting || :primary_key
34
+ foreign_key_type = setting || :bigint
35
+ [primary_key_type, foreign_key_type]
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ # This migration comes from noticed (originally 20240129184740)
2
+ class AddNotificationsCountToNoticedEvent < ActiveRecord::Migration[6.1]
3
+ def change
4
+ add_column :noticed_events, :notifications_count, :integer
5
+ end
6
+ end
@@ -0,0 +1,36 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'Notifications' do
4
+ subject do
5
+ visit '/'
6
+ end
7
+
8
+ let(:user) { create :user }
9
+
10
+ before do
11
+ driven_by ENV['DRIVER']&.to_sym || :selenium_chrome_headless_iphone
12
+ login_as user
13
+ end
14
+
15
+ context 'no notifications' do
16
+ it do
17
+ subject
18
+ expect(page).to have_no_css('.notifications-unseen-mark')
19
+ end
20
+ end
21
+
22
+ context 'with unseen notifications' do
23
+ before do
24
+ SimpleUserNotifier.with(message: 'probandooo').deliver(User.all)
25
+ end
26
+
27
+ it do
28
+ subject
29
+ expect(page).to have_css('.notifications-unseen-mark')
30
+ find('.bi-bell-fill').click
31
+ expect(page).to have_no_css('.notifications-unseen-mark', wait: 5)
32
+ end
33
+ end
34
+
35
+ pending 'with read notifications'
36
+ end
@@ -7,6 +7,7 @@ import FadeinOnloadController from './fadein_onload_controller'
7
7
  import ClearTimeoutController from './clear_timeout_controller'
8
8
  import SwitcherController from './switcher_controller'
9
9
  import FiltrosController from './filtros_controller'
10
+ import NotificationsController from './notifications_controller'
10
11
 
11
12
  application.register('navbar', NavbarController)
12
13
  application.register('nested', NestedController)
@@ -15,5 +16,6 @@ application.register('fadein_onload', FadeinOnloadController)
15
16
  application.register('clear-timeout', ClearTimeoutController)
16
17
  application.register('switcher', SwitcherController)
17
18
  application.register('filtros', FiltrosController)
19
+ application.register('notifications', NotificationsController)
18
20
 
19
21
  // TODO: testear con capybara todo lo que se pueda
@@ -0,0 +1,46 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import { post } from '@rails/request.js'
3
+ import { Rollbar } from 'rollbar'
4
+
5
+ // Connects to data-controller="notifications"
6
+ export default class extends Controller {
7
+ timeoutId = null
8
+
9
+ connect () {
10
+ this.element.addEventListener('shown.bs.collapse', event => {
11
+ this.timeoutId = setTimeout(() => {
12
+ this.markAsSeen()
13
+ }, 2000)
14
+ document.addEventListener('turbo:load', () => { this.cancelTimeout() })
15
+ })
16
+ this.element.addEventListener('hide.bs.collapse', event => {
17
+ clearTimeout(this.timeoutId)
18
+ })
19
+ }
20
+
21
+ async markAsSeen () {
22
+ const ids = []
23
+ document.querySelectorAll('.notification')
24
+ .forEach((e) => { ids.push(e.dataset.id) })
25
+ const response = await post('/u/notifications/mark_as_seen',
26
+ { query: { ids }, responseKind: 'turbo-stream' })
27
+
28
+ if (response.ok) {
29
+ document.querySelectorAll('.notification.unseen').forEach(
30
+ (notif) => {
31
+ notif.classList.remove('unseen')
32
+ }
33
+ )
34
+ document.querySelector('.notifications-unseen-mark').remove()
35
+ } else {
36
+ const text = await response.text
37
+ Rollbar.error('Error marking as seen: ', text)
38
+ }
39
+ }
40
+
41
+ cancelTimeout () {
42
+ if (this.timeoutId) {
43
+ clearTimeout(this.timeoutId)
44
+ }
45
+ }
46
+ }
@@ -1,7 +1,8 @@
1
1
  <nav class="navbar navbar-expand-<%= @breakpoint_navbar_expand %>" data-bs-theme="dark">
2
2
  <div class="container-fluid">
3
3
  <% unless @sidebar == false %>
4
- <button data-controller="navbar" data-action="navbar#expandNavbar" class="btn btn-outline-light me-2 d-none d-<%= @breakpoint_navbar_expand %>-inline-block">
4
+ <button data-controller="navbar" data-action="navbar#expandNavbar"
5
+ class="btn btn-outline-light me-2 d-none d-<%= @breakpoint_navbar_expand %>-inline-block">
5
6
  <i class="bi <%= @navbar_chevron_class %>"></i>
6
7
  </button>
7
8
 
@@ -9,12 +10,43 @@
9
10
  <% @navbar.extensiones.each do |extension| %>
10
11
  <%= extension %>
11
12
  <% end %>
13
+ <% if Current.user.present? %>
14
+ <button type="button" class="btn btn-primary btn-sm position-relative"
15
+ data-bs-toggle="collapse" data-bs-target="#notifications-collapse">
16
+ <i class="bi-bell-fill fs-5 text-light"></i>
17
+ <% if @unseen_notifications %>
18
+ <span class="position-absolute p-1 xbg-danger bg-gradient rounded-circle start-50 notifications-unseen-mark">
19
+ </span>
20
+ <% end %>
21
+ </button>
22
+ <% end %>
12
23
  <%= @navbar.logo if @navbar.logo.present? %>
13
- <button class="btn btn-outline-light d-inline-block d-<%= @breakpoint_navbar_expand %>-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
24
+ <button class="btn btn-outline-light d-inline-block d-<%= @breakpoint_navbar_expand %>-none"
25
+ type="button"
26
+ data-bs-toggle="offcanvas"
27
+ data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
14
28
  <i class="bi bi-list"></i>
15
29
  </button>
16
30
  </div>
17
31
  </nav>
32
+ <div class="collapse" id="notifications-collapse" data-controller="notifications">
33
+ <div id="notifications">
34
+ <div id="notifications-inner">
35
+ <% if @notifications&.any? %>
36
+ <%= render NotificationComponent.with_collection(@notifications) if @notifications&.any? %>
37
+ <% else %>
38
+ <span class="text-light">
39
+ No hay notificaciones
40
+ </span>
41
+ <% end %>
42
+ <div class="text-center">
43
+ <button type="button" class="btn btn-link text-light btn-sm" data-bs-toggle="collapse" data-bs-target="#notifications-collapse">
44
+ <i class="bi-chevron-up fs-3"></i>
45
+ </button>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
18
50
 
19
51
  <style type="text/css" media="(max-width: 767px)">
20
52
  .navbar .navbar-brand {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.0.8-alpha.94'
4
+ VERSION = '7.0.8-alpha.96'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.8.pre.alpha.94
4
+ version: 7.0.8.pre.alpha.96
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-10 00:00:00.000000000 Z
11
+ date: 2024-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -542,6 +542,20 @@ dependencies:
542
542
  - - "~>"
543
543
  - !ruby/object:Gem::Version
544
544
  version: 3.12.1
545
+ - !ruby/object:Gem::Dependency
546
+ name: noticed
547
+ requirement: !ruby/object:Gem::Requirement
548
+ requirements:
549
+ - - "~>"
550
+ - !ruby/object:Gem::Version
551
+ version: '2.3'
552
+ type: :runtime
553
+ prerelease: false
554
+ version_requirements: !ruby/object:Gem::Requirement
555
+ requirements:
556
+ - - "~>"
557
+ - !ruby/object:Gem::Version
558
+ version: '2.3'
545
559
  - !ruby/object:Gem::Dependency
546
560
  name: vcr
547
561
  requirement: !ruby/object:Gem::Requirement
@@ -968,6 +982,7 @@ files:
968
982
  - pg_engine/app/assets/images/plantita.png
969
983
  - pg_engine/app/assets/javascripts/active_admin.js
970
984
  - pg_engine/app/assets/stylesheets/active_admin.scss
985
+ - pg_engine/app/assets/stylesheets/notifications.scss
971
986
  - pg_engine/app/assets/stylesheets/pg_rails_b5.scss
972
987
  - pg_engine/app/components/alert_component.html.slim
973
988
  - pg_engine/app/components/alert_component.rb
@@ -975,6 +990,7 @@ files:
975
990
  - pg_engine/app/components/base_component.rb
976
991
  - pg_engine/app/components/flash_container_component.rb
977
992
  - pg_engine/app/components/internal_error_component.rb
993
+ - pg_engine/app/components/notification_component.rb
978
994
  - pg_engine/app/controllers/admin/accounts_controller.rb
979
995
  - pg_engine/app/controllers/admin/email_logs_controller.rb
980
996
  - pg_engine/app/controllers/admin/emails_controller.rb
@@ -988,6 +1004,7 @@ files:
988
1004
  - pg_engine/app/controllers/public/mensaje_contactos_controller.rb
989
1005
  - pg_engine/app/controllers/public/webhooks_controller.rb
990
1006
  - pg_engine/app/controllers/users/confirmations_controller.rb
1007
+ - pg_engine/app/controllers/users/notifications_controller.rb
991
1008
  - pg_engine/app/controllers/users/registrations_controller.rb
992
1009
  - pg_engine/app/decorators/account_decorator.rb
993
1010
  - pg_engine/app/decorators/email_decorator.rb
@@ -1020,6 +1037,8 @@ files:
1020
1037
  - pg_engine/app/models/pg_engine/base_record.rb
1021
1038
  - pg_engine/app/models/user.rb
1022
1039
  - pg_engine/app/models/user_account.rb
1040
+ - pg_engine/app/notifiers/application_notifier.rb
1041
+ - pg_engine/app/notifiers/simple_user_notifier.rb
1023
1042
  - pg_engine/app/policies/account_policy.rb
1024
1043
  - pg_engine/app/policies/email_log_policy.rb
1025
1044
  - pg_engine/app/policies/email_policy.rb
@@ -1081,6 +1100,8 @@ files:
1081
1100
  - pg_engine/db/migrate/20240506194106_create_emails.rb
1082
1101
  - pg_engine/db/migrate/20240517174821_pg_trgm.rb
1083
1102
  - pg_engine/db/migrate/20240523183651_create_email_logs.rb
1103
+ - pg_engine/db/migrate/20240611000219_create_noticed_tables.noticed.rb
1104
+ - pg_engine/db/migrate/20240611000220_add_notifications_count_to_noticed_event.noticed.rb
1084
1105
  - pg_engine/db/seeds.rb
1085
1106
  - pg_engine/lib/pg_engine.rb
1086
1107
  - pg_engine/lib/pg_engine/configuracion.rb
@@ -1141,6 +1162,7 @@ files:
1141
1162
  - pg_engine/spec/system/alerts_spec.rb
1142
1163
  - pg_engine/spec/system/destroy_spec.rb
1143
1164
  - pg_engine/spec/system/login_spec.rb
1165
+ - pg_engine/spec/system/noticed_spec.rb
1144
1166
  - pg_engine/spec/system/send_mail_spec.rb
1145
1167
  - pg_engine/spec/system/signup_spec.rb
1146
1168
  - pg_layout/app/assets/stylesheets/animations.scss
@@ -1161,6 +1183,7 @@ files:
1161
1183
  - pg_layout/app/javascript/controllers/index.js
1162
1184
  - pg_layout/app/javascript/controllers/navbar_controller.js
1163
1185
  - pg_layout/app/javascript/controllers/nested_controller.js
1186
+ - pg_layout/app/javascript/controllers/notifications_controller.js
1164
1187
  - pg_layout/app/javascript/controllers/pg_form_controller.js
1165
1188
  - pg_layout/app/javascript/controllers/switcher_controller.js
1166
1189
  - pg_layout/app/javascript/utils/cookies.js