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

Sign up to get free protection for your applications and to get access to all the features.
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