pg_rails 7.0.8.pre.alpha.93 → 7.0.8.pre.alpha.95
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/pg_engine/app/assets/stylesheets/notifications.scss +49 -0
- data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +3 -0
- data/pg_engine/app/components/notification_component.rb +19 -0
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +5 -0
- data/pg_engine/app/controllers/users/notifications_controller.rb +11 -0
- data/pg_engine/app/models/email_log.rb +0 -1
- data/pg_engine/app/models/user.rb +1 -0
- data/pg_engine/app/notifiers/application_notifier.rb +2 -0
- data/pg_engine/app/notifiers/simple_user_notifier.rb +28 -0
- data/pg_engine/config/initializers/anycable.rb +3 -0
- data/pg_engine/config/routes.rb +3 -0
- data/pg_engine/db/migrate/20240611000219_create_noticed_tables.noticed.rb +37 -0
- data/pg_engine/db/migrate/20240611000220_add_notifications_count_to_noticed_event.noticed.rb +6 -0
- data/pg_engine/spec/system/noticed_spec.rb +36 -0
- data/pg_layout/app/javascript/controllers/index.js +2 -0
- data/pg_layout/app/javascript/controllers/notifications_controller.js +46 -0
- data/pg_layout/app/views/pg_layout/_navbar.html.erb +34 -2
- data/pg_rails/lib/version.rb +1 -1
- data/pg_rails/scss/pg_rails.scss +5 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f8a869085b05c79395519bbd89206705710f949f49304c41f015030c12a125e
|
4
|
+
data.tar.gz: 8f1ff6c3b0f428c6b4d7b4b5b9f91b7b5979d9d491a7ca553918abf8fe5de462
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fd90973e9c75ed200bdbce2a95cf3d4ef34e47aa9c5ba48105dc8aa34ab8c934eff9f01d4dd7ba735b111968a17dc4c8f24e38294ca71d28c8aec8dd18d62a3
|
7
|
+
data.tar.gz: e3dd8ddc322319711e8471b2d9ee5e329d2291c0e2b6ae5cadb023506f53dc960bf7a746349623b9ac38a51a0266ea71fccc9c142e2ad14342548badd9b9c826
|
@@ -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
|
+
}
|
@@ -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
|
@@ -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
|
data/pg_engine/config/routes.rb
CHANGED
@@ -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,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"
|
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"
|
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 {
|
data/pg_rails/lib/version.rb
CHANGED
data/pg_rails/scss/pg_rails.scss
CHANGED
@@ -11,12 +11,16 @@ $teal: #20c997 !default;
|
|
11
11
|
$cyan: #0dcaf0 !default;
|
12
12
|
|
13
13
|
// Overriding some of the default colours
|
14
|
+
$yellow: #ffb401;
|
14
15
|
$orange: #e35b17;
|
15
16
|
$red: #a70101;
|
16
17
|
|
17
|
-
$warning: $
|
18
|
+
$warning: $yellow;
|
18
19
|
$info: #87accc;
|
19
20
|
|
21
|
+
$warning-text-emphasis: $orange;
|
22
|
+
$danger-text-emphasis: #910303;
|
23
|
+
|
20
24
|
$font-size-base: 0.9rem;
|
21
25
|
$enable-validation-icons: false;
|
22
26
|
$focus-ring-width: .05rem;
|
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.
|
4
|
+
version: 7.0.8.pre.alpha.95
|
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-
|
11
|
+
date: 2024-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -968,6 +968,7 @@ files:
|
|
968
968
|
- pg_engine/app/assets/images/plantita.png
|
969
969
|
- pg_engine/app/assets/javascripts/active_admin.js
|
970
970
|
- pg_engine/app/assets/stylesheets/active_admin.scss
|
971
|
+
- pg_engine/app/assets/stylesheets/notifications.scss
|
971
972
|
- pg_engine/app/assets/stylesheets/pg_rails_b5.scss
|
972
973
|
- pg_engine/app/components/alert_component.html.slim
|
973
974
|
- pg_engine/app/components/alert_component.rb
|
@@ -975,6 +976,7 @@ files:
|
|
975
976
|
- pg_engine/app/components/base_component.rb
|
976
977
|
- pg_engine/app/components/flash_container_component.rb
|
977
978
|
- pg_engine/app/components/internal_error_component.rb
|
979
|
+
- pg_engine/app/components/notification_component.rb
|
978
980
|
- pg_engine/app/controllers/admin/accounts_controller.rb
|
979
981
|
- pg_engine/app/controllers/admin/email_logs_controller.rb
|
980
982
|
- pg_engine/app/controllers/admin/emails_controller.rb
|
@@ -988,6 +990,7 @@ files:
|
|
988
990
|
- pg_engine/app/controllers/public/mensaje_contactos_controller.rb
|
989
991
|
- pg_engine/app/controllers/public/webhooks_controller.rb
|
990
992
|
- pg_engine/app/controllers/users/confirmations_controller.rb
|
993
|
+
- pg_engine/app/controllers/users/notifications_controller.rb
|
991
994
|
- pg_engine/app/controllers/users/registrations_controller.rb
|
992
995
|
- pg_engine/app/decorators/account_decorator.rb
|
993
996
|
- pg_engine/app/decorators/email_decorator.rb
|
@@ -1020,6 +1023,8 @@ files:
|
|
1020
1023
|
- pg_engine/app/models/pg_engine/base_record.rb
|
1021
1024
|
- pg_engine/app/models/user.rb
|
1022
1025
|
- pg_engine/app/models/user_account.rb
|
1026
|
+
- pg_engine/app/notifiers/application_notifier.rb
|
1027
|
+
- pg_engine/app/notifiers/simple_user_notifier.rb
|
1023
1028
|
- pg_engine/app/policies/account_policy.rb
|
1024
1029
|
- pg_engine/app/policies/email_log_policy.rb
|
1025
1030
|
- pg_engine/app/policies/email_policy.rb
|
@@ -1081,6 +1086,8 @@ files:
|
|
1081
1086
|
- pg_engine/db/migrate/20240506194106_create_emails.rb
|
1082
1087
|
- pg_engine/db/migrate/20240517174821_pg_trgm.rb
|
1083
1088
|
- pg_engine/db/migrate/20240523183651_create_email_logs.rb
|
1089
|
+
- pg_engine/db/migrate/20240611000219_create_noticed_tables.noticed.rb
|
1090
|
+
- pg_engine/db/migrate/20240611000220_add_notifications_count_to_noticed_event.noticed.rb
|
1084
1091
|
- pg_engine/db/seeds.rb
|
1085
1092
|
- pg_engine/lib/pg_engine.rb
|
1086
1093
|
- pg_engine/lib/pg_engine/configuracion.rb
|
@@ -1141,6 +1148,7 @@ files:
|
|
1141
1148
|
- pg_engine/spec/system/alerts_spec.rb
|
1142
1149
|
- pg_engine/spec/system/destroy_spec.rb
|
1143
1150
|
- pg_engine/spec/system/login_spec.rb
|
1151
|
+
- pg_engine/spec/system/noticed_spec.rb
|
1144
1152
|
- pg_engine/spec/system/send_mail_spec.rb
|
1145
1153
|
- pg_engine/spec/system/signup_spec.rb
|
1146
1154
|
- pg_layout/app/assets/stylesheets/animations.scss
|
@@ -1161,6 +1169,7 @@ files:
|
|
1161
1169
|
- pg_layout/app/javascript/controllers/index.js
|
1162
1170
|
- pg_layout/app/javascript/controllers/navbar_controller.js
|
1163
1171
|
- pg_layout/app/javascript/controllers/nested_controller.js
|
1172
|
+
- pg_layout/app/javascript/controllers/notifications_controller.js
|
1164
1173
|
- pg_layout/app/javascript/controllers/pg_form_controller.js
|
1165
1174
|
- pg_layout/app/javascript/controllers/switcher_controller.js
|
1166
1175
|
- pg_layout/app/javascript/utils/cookies.js
|