signum 0.3.12 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -1
  3. data/app/assets/config/signum_manifest.js +5 -0
  4. data/app/assets/stylesheets/signum/application.css +4 -0
  5. data/app/components/signum/notification/component.css +3 -0
  6. data/app/components/signum/notification/component.html.slim +2 -24
  7. data/app/components/signum/notification/component.rb +4 -0
  8. data/app/components/signum/notification_body/component.css +104 -0
  9. data/app/components/signum/notification_body/component.html.slim +41 -0
  10. data/app/components/signum/notification_body/component.rb +18 -0
  11. data/app/components/signum/notification_body/component_controller.js +41 -0
  12. data/app/components/signum/notification_drawer/component.css +7 -0
  13. data/app/components/signum/notification_drawer/component.html.slim +6 -11
  14. data/app/components/signum/notification_drawer/component.rb +3 -2
  15. data/app/components/signum/notification_drawer/component_controller.js +48 -0
  16. data/app/components/signum/notification_drawer_item/component.html.slim +2 -14
  17. data/app/components/signum/notification_drawer_item/component.rb +9 -1
  18. data/app/components/signum/notification_drawer_item/component_controller.js +30 -0
  19. data/app/javascript/signum/application.js +1 -0
  20. data/app/javascript/signum/controllers/application.js +12 -0
  21. data/app/javascript/signum/controllers/application_controller.js +4 -0
  22. data/app/javascript/signum/controllers/index.js +14 -0
  23. data/app/models/signum/signal.rb +31 -7
  24. data/config/importmap.rb +6 -0
  25. data/config/routes.rb +1 -0
  26. data/db/migrate/20230317123138_add_columns_to_signum_signal.rb +7 -0
  27. data/db/migrate/20231218095011_add_subject_to_signals.rb +5 -0
  28. data/lib/generators/signum/install_generator.rb +22 -0
  29. data/lib/generators/signum/tailwind_config_generator.rb +24 -0
  30. data/lib/generators/signum/templates/config/initializers/signum.rb +8 -0
  31. data/lib/signum/configuration.rb +60 -4
  32. data/lib/signum/engine.rb +18 -6
  33. data/lib/signum/version.rb +1 -1
  34. data/lib/signum.rb +15 -6
  35. data/lib/tasks/signum_tasks.rake +13 -0
  36. metadata +94 -8
  37. data/app/channels/signum/application_cable/channel.rb +0 -8
  38. data/app/channels/signum/application_cable/connection.rb +0 -24
  39. data/app/components/signum/notification/component.scss +0 -34
  40. data/app/components/signum/notification_drawer/component.scss +0 -7
  41. data/app/jobs/signum/send_signals_job.rb +0 -13
  42. /data/app/components/signum/notification_drawer_item/{component.scss → component.css} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd53f73e635b3003fe096e759fab32eecf11150eaf860c3e26e49b6d19850a6b
4
- data.tar.gz: 7f483ba2ac476e62ac4bcfa664e95f734ac95d3c49c914fe3d936157520f50c8
3
+ metadata.gz: 8c2d2692c406747889b91ad03f134e452024ef67230a300a58560a89c290de1a
4
+ data.tar.gz: 73032778b0e3195f582924477b1b0ba8c03fd1d9bb1c3a8cbdcf852e0085c42b
5
5
  SHA512:
6
- metadata.gz: 61f04881271d2d6225144e60703f075c6b8f12265105b25f763f330edae371ee7e07d8edbe742fea57171a5d952fa3e3d6b9b5c2944b4c51305d234d5076abd4
7
- data.tar.gz: 30284aaec38f11795f56635d9863c5220ab1b455ee554372521660746b1c685fd3d45737cce933c8e7821ce619e32dd6b12d5660b1bfae01b17647c8226bc416
6
+ metadata.gz: 657c09d536f1ae32e2b0646b195bbbf17153a060a9028f4b3f8eb254607af721df7974edea70fa81384e128f986d91dfa6ff246da327095956b947e60853f315
7
+ data.tar.gz: e9678d8723c59a0d82c652481d7d55e899932ab8417393c68588e7d63ab1a0b831b20d67bf36eb5dc7eba26e3590cfb71e33ef924bdb5aa78566be3432d5ccbd
data/README.md CHANGED
@@ -39,7 +39,36 @@ Signum.error(Current.user, text: "Houston, we have a problem!")
39
39
  Signum.success(Current.user, text: "The Eagle has landed!")
40
40
  ```
41
41
 
42
- Above we used the `Current.user` as the user to signal to.
42
+ You can make a signal sticky, keeping it on the screen until you click it away:
43
+ ```ruby
44
+ s = Signum.signal(Current.user, text: "Hello World New", sticky: true, title: "Sticky")
45
+ ```
46
+
47
+ You can add icons:
48
+ ```ruby
49
+ s = Signum.signal(Current.user, text: "Hello World New", title: "Icon", icon:'fa-regular fa-t-rex')
50
+ ```
51
+
52
+ Buttons and links:
53
+ ```ruby
54
+ s = Signum.success(Current.user, text: "Hello World New", title: "Link1", metadata: {buttons:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}], links:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}, {title: "Amazon", url: "http://www.amazon.com"}]})
55
+ s = Signum.signal(Current.user, text: "Hello World New", title: "Link2", metadata: {buttons:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}], links:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}, {title: "Amazon", url: "http://www.amazon.com"}]}, icon: 'fa-regular fa-t-rex')
56
+ s = Signum.signal(Current.user, text: "Hello World New", title: "Link2", metadata: {buttons:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}], links:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}, {title: "Amazon", url: "http://www.amazon.com"},{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}, {title: "Amazon", url: "http://www.amazon.com"},{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}, {title: "Amazon", url: "http://www.amazon.com"}]})
57
+ ```
58
+
59
+ You can also show a progressbar, this is based on count and total. Setting the count to total completes the progressbar.
60
+ ```ruby
61
+ s = Signum.success(Current.user, text: "Hello World New", title: "this is test title", metadata: {buttons:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}], links:[{title: "Google", url:"http://www.google.com"}, {title: "Apple", url: "http://www.apple.com"}, {title: "Amazon", url: "http://www.amazon.com"}]}, count: 75, total: 150)
62
+ ```
63
+
64
+ You can also attach attachments
65
+ ```ruby
66
+ attachment = {io: File.open("notes.txt"),
67
+ content_type: "text/plain", filename: "notes.txt"}
68
+ s = Signum.success(Current.user, text: "Hello World New", title: "this is test title", attachments: [attachment])
69
+ ```
70
+
71
+ Signum returns you the signal object. You can update these signals and they will be rebroadcasted again.
43
72
 
44
73
  ## Contributing
45
74
 
@@ -0,0 +1,5 @@
1
+ //= link_tree ../images
2
+ //= link_directory ../../javascript/signum .js
3
+ //= link_directory ../../javascript/signum/controllers .js
4
+ //= link_tree ../../components .js
5
+ //= link_tree ../../../vendor/javascript .js
@@ -0,0 +1,4 @@
1
+ @import '../../../components/signum/notification/component.css';
2
+ @import '../../../components/signum/notification_body/component.css';
3
+ @import '../../../components/signum/notification_drawer/component.css';
4
+ @import '../../../components/signum/notification_drawer_item/component.css';
@@ -0,0 +1,3 @@
1
+ .signum-notification {
2
+ @apply pointer-events-auto flex flex-wrap w-full divide-x divide-y divide-gray-200 max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5;
3
+ }
@@ -1,24 +1,2 @@
1
- .signum-notification.hidden data-notification-timeout=@data[:timeout] data-controller="notification"
2
- .p-4
3
- .flex.items-start
4
- .flex-shrink-0
5
- - if @signal.kind == "success"
6
- svg.signum-notification-icon-success[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"]
7
- path[stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"]
8
- - elsif @signal.kind == "error"
9
- svg.signum-notification-icon-error[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor"]
10
- path[stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z"]
11
- - else
12
- svg.svg.signum-notification-icon-info[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"]
13
- path[stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"]
14
- .ml-3.w-0.flex-1.pt-0.5
15
- p.signum-notification-title
16
- = sanitize @signal.title
17
- p.signum-notification-body
18
- = sanitize @signal.text
19
- .ml-4.flex.flex-shrink-0
20
- button.signum-notification-button-close[type="button" data-action="notification#close"]
21
- span.sr-only
22
- | Close
23
- svg.h-5.w-5[xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" aria-hidden="true"]
24
- path[d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"]
1
+ .signum-notification
2
+ = render(Signum::NotificationBody::Component.new(signal, data))
@@ -7,10 +7,14 @@
7
7
  module Signum
8
8
  module Notification
9
9
  class Component < ViewComponent::Base
10
+ attr_reader :signal, :data
11
+
10
12
  def initialize(signal, data: nil)
11
13
  @signal = signal
12
14
  @data = data.nil? ? {} : data.deep_symbolize_keys
15
+
13
16
  @data[:timeout] ||= 5
17
+ @data[:type] ||= :balloon
14
18
  end
15
19
  end
16
20
  end
@@ -0,0 +1,104 @@
1
+ .signum-notification-body {
2
+ @apply flex flex-col w-full divide-y;
3
+
4
+ &__mb {
5
+ // main body
6
+ @apply flex basis-full divide-x;
7
+
8
+ &__bc {
9
+ //body container
10
+ @apply flex grow py-4 px-2 overflow-hidden;
11
+
12
+ &__ic {
13
+ //icon container
14
+ @apply grow-0 pl-2 pr-3;
15
+
16
+ svg.info
17
+ {
18
+ //icon info
19
+ @apply text-sky-400;
20
+ }
21
+
22
+ svg.success{
23
+ //icon success
24
+ @apply text-green-400;
25
+ }
26
+
27
+ svg.error{
28
+ //icon error
29
+ @apply text-red-400;
30
+ }
31
+
32
+ svg.warning{
33
+ //icon warning
34
+ @apply text-orange-400;
35
+ }
36
+ }
37
+
38
+ &__mc {
39
+ //main container
40
+ @apply grow text-left break-words overflow-hidden;
41
+
42
+ &__ti {
43
+ // title
44
+ @apply text-[0.81rem] font-medium text-gray-900;
45
+ }
46
+
47
+ &__tx {
48
+ //text
49
+ @apply text-xs text-gray-500 mt-1;
50
+ }
51
+
52
+ &__lkc {
53
+ //links container
54
+ @apply flex flex-wrap mt-3;
55
+
56
+ &__lk {
57
+ //link
58
+ @apply rounded-md text-xs font-medium text-gray-700 hover:text-gray-500 focus:outline-none mr-2;
59
+ }
60
+ }
61
+
62
+ &__attc {
63
+ //attachments links container
64
+ @apply flex flex-wrap mt-3;
65
+
66
+ &__att {
67
+ //attachment link
68
+ @apply rounded-md text-xs font-medium text-gray-700 hover:text-gray-500 focus:outline-none mr-2;
69
+ }
70
+ }
71
+ }
72
+
73
+ &__bcc {
74
+ //close button container
75
+ @apply grow-0 m-1;
76
+
77
+ &__b {
78
+ //button
79
+ @apply text-gray-400 hover:text-gray-500 cursor-pointer;
80
+ }
81
+ }
82
+ }
83
+
84
+ &__bmc {
85
+ //buttons main container
86
+ @apply flex grow-0 flex-col divide-y divide-gray-200;
87
+
88
+ &__bc {
89
+ //buttons container
90
+ @apply flex flex-1;
91
+
92
+ &__b {
93
+ //button
94
+ @apply flex w-full items-center justify-center text-xs font-medium text-gray-700 hover:text-gray-500 focus:outline-none px-4 py-3;
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ &__pbc {
101
+ //progress bar container
102
+ @apply basis-full p-1;
103
+ }
104
+ }
@@ -0,0 +1,41 @@
1
+ .signum-notification-body data-controller="signum-notification-body" data-signum-notification-body-type-value=data[:type] data-signum-notification-body-timeout-value=data[:timeout] data-signum-notification-body-sticky-value="#{signal.sticky.present? ? signal.sticky.to_s : 'false'}" data-signum-notification-body-signal-state-value="#{signal.state}" data-signum-notification-body-signal-id-value="#{signal.id}" id="notification_#{data[:type]}_#{signal.signalable_id}_#{signal.id}"
2
+ .signum-notification-body__mb
3
+ .signum-notification-body__mb__bc
4
+ .signum-notification-body__mb__bc__ic
5
+ - if signal.icon.present?
6
+ = "<i class='#{signal.kind} #{signal.icon}' ></i>".html_safe
7
+ .signum-notification-body__mb__bc__mc
8
+ - if signal.title.present?
9
+ p.signum-notification-body__mb__bc__mc__ti
10
+ = sanitize signal.title
11
+ - if signal.text.present?
12
+ p.signum-notification-body__mb__bc__mc__tx
13
+ = sanitize signal.text
14
+ - if signal.metadata.present? && signal.metadata["links"].present?
15
+ .signum-notification-body__mb__bc__mc__lkc
16
+ - signal.metadata["links"].each do | link |
17
+ a.signum-notification-body__mb__bc__mc__lkc__lk href="#{link["url"]}" target="_blank"
18
+ i.fas.fa-link
19
+ =< link["title"]
20
+ - if signal.attachments.attached?
21
+ .signum-notification-body__mb__bc__mc__attc
22
+ - signal.attachments.each do | attachment |
23
+ a.signum-notification-body__mb__bc__mc__attc__att href="#{url_for(attachment)}" target="_blank"
24
+ i.fas.fa-paperclip-vertical
25
+ =< attachment.blob.filename
26
+ .signum-notification-body__mb__bc__bcc
27
+ a.signum-notification-body__mb__bc__bcc__b[data-action="signum-notification-body#close"]
28
+ span.sr-only
29
+ | Close
30
+ svg.h-5.w-5[xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" aria-hidden="true"]
31
+ path[d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"]
32
+ - if signal.metadata.present? && signal.metadata["buttons"].present?
33
+ .signum-notification-body__mb__bmc
34
+ - signal.metadata["buttons"].each do | button |
35
+ .signum-notification-body__mb__bmc__bc
36
+ a.signum-notification-body__mb__bmc__bc__b href="#{button["url"]}" target="_blank"
37
+ = button["title"]
38
+ - if signal.count.present?
39
+ - percentage = signal.total.present? ? signal.count.fdiv(signal.total) * 100 : signal.count
40
+ .signum-notification-body__pbc
41
+ = sts.progress_bar percentage, size: :small, label: false
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @param type [String] Classic notification type `error`, `alert` and `info` + custom `success`
4
+ # @param data [String, Hash] `String` for backward compatibility,
5
+ # `Hash` for the new functionality `{title: '', body: '', timeout: 5, countdown: false, action: { url: '', method: '', name: ''}}`.
6
+ # The `title` attribute for `Hash` is mandatory.
7
+ module Signum
8
+ module NotificationBody
9
+ class Component < ViewComponent::Base
10
+ attr_reader :signal, :data
11
+
12
+ def initialize(signal, data)
13
+ @signal = signal
14
+ @data = data.nil? ? {} : data.deep_symbolize_keys
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ import ApplicationController from "signum/controllers/application_controller"
2
+
3
+ export default class extends ApplicationController {
4
+ static values = { type: String, timeout: Number, sticky: Boolean, signalId: String, signalState: String }
5
+ connect() {
6
+ if (this.typeValue == "balloon" && !this.stickyValue) {
7
+ this.timeoutId = setTimeout(() => {
8
+ this.close()
9
+ }, this.timeoutValue * 1000 + 500)
10
+ }
11
+ }
12
+
13
+ close(event) {
14
+ setTimeout(() => {
15
+ this.element?.parentElement?.remove()
16
+ if (event) {
17
+ this.markClose()
18
+ }
19
+ }, 300)
20
+ }
21
+
22
+ markClose() {
23
+ fetch("/signal/close", {
24
+ method: "POST",
25
+ headers: {
26
+ "Content-Type": "application/json",
27
+ },
28
+ body: JSON.stringify({ id: this.signalIdValue }),
29
+ })
30
+ .then((res) => {
31
+ const niE = new CustomEvent("nd-item-activity", {
32
+ bubbles: true,
33
+ detail: "closed",
34
+ })
35
+ window.dispatchEvent(niE)
36
+ })
37
+ .catch((err) => {
38
+ console.log(err)
39
+ })
40
+ }
41
+ }
@@ -0,0 +1,7 @@
1
+ .signum-notification-drawer-button {
2
+ @apply w-8 h-8 bg-white m-0 rounded-full text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:bg-gray-900 dark:border-gray-700;
3
+ }
4
+
5
+ .signum-notification-drawer-tray {
6
+ @apply bg-gray-50 w-full max-w-sm absolute right-0 z-10 mx-1 w-1/3 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 overflow-y-auto max-h-[75vh];
7
+ }
@@ -1,12 +1,7 @@
1
- div.text-left[data-controller="notification-drawer" data-action="mouseover->notification-drawer#show mouseleave->notification-drawer#hide"]
2
- button.signum-notification-drawer-button
3
- svg.w-6.h-6.hidden[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor" data-notification-drawer-target="alertbellicon"]
4
- path[stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5"]
1
+ div.text-left[data-controller="signum-notification-drawer" data-action="mouseover->signum-notification-drawer#show mouseleave->signum-notification-drawer#hide"]
2
+ button.signum-notification-drawer-button
3
+ = "<i class='hidden #{Signum.config.icons[:unread_main]}' data-signum-notification-drawer-target='alertbellicon'></i>".html_safe
4
+ = "<i class='#{Signum.config.icons[:read_main]}' data-signum-notification-drawer-target='bellicon'></i>".html_safe
5
5
 
6
- svg.w-6.h-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor" data-notification-drawer-target="bellicon"]
7
- path[stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0"]
8
-
9
- .signum-notification-drawer-tray.hidden[data-notification-drawer-target="submenu" id="#{@notification_container_id}"]
10
- - if @signals.present?
11
- - @signals.each do |signal|
12
- = render(Signum::NotificationDrawerItem::Component.new(signal))
6
+ .signum-notification-drawer-tray.hidden[data-signum-notification-drawer-target="submenu" id="#{Signum.config.drawer_notifications_container_id.call}"]
7
+ = render(Signum::NotificationDrawerItem::Component.with_collection(signals))
@@ -1,9 +1,10 @@
1
1
  module Signum
2
2
  module NotificationDrawer
3
3
  class Component < ViewComponent::Base
4
- def initialize(signals, notification_container_id)
4
+ attr_reader :signals
5
+
6
+ def initialize(signals)
5
7
  @signals = signals
6
- @notification_container_id = notification_container_id
7
8
  end
8
9
  end
9
10
  end
@@ -0,0 +1,48 @@
1
+ import ApplicationController from "signum/controllers/application_controller"
2
+
3
+ export default class extends ApplicationController {
4
+ static targets = ["alertbellicon", "bellicon", "submenu", "item"]
5
+
6
+ connect() {
7
+ this.bounditemActivity = this.itemActivity.bind(this)
8
+ window.addEventListener("nd-item-activity", this.bounditemActivity)
9
+
10
+ setTimeout(() => {
11
+ this.manageBellIcon()
12
+ }, 300)
13
+ }
14
+
15
+ disconnect() {
16
+ window.removeEventListener("nd-item-activity", this.bounditemActivity)
17
+ }
18
+
19
+ show(event) {
20
+ if (this.submenuTarget.children.length > 0) {
21
+ this.submenuTarget.classList.remove("hidden")
22
+ } else {
23
+ this.submenuTarget.classList.add("hidden")
24
+ }
25
+ }
26
+
27
+ hide(event) {
28
+ this.submenuTarget.classList.add("hidden")
29
+ }
30
+
31
+ itemActivity(event) {
32
+ this.manageBellIcon()
33
+
34
+ if (this.submenuTarget.children.length == 0) {
35
+ this.hide(event)
36
+ }
37
+ }
38
+
39
+ manageBellIcon() {
40
+ if (this.submenuTarget.children.length > 0) {
41
+ this.alertbelliconTarget.classList.remove("hidden")
42
+ this.belliconTarget.classList.add("hidden")
43
+ } else {
44
+ this.alertbelliconTarget.classList.add("hidden")
45
+ this.belliconTarget.classList.remove("hidden")
46
+ }
47
+ }
48
+ }
@@ -1,14 +1,2 @@
1
- .py-1.hover:bg-gray-50[data-controller="notification-drawer-item" data-action="click->notification-drawer-item#markRead" data-notification-drawer-target="item" class=('font-bold' if @signal.state != 'closed') data-notification-drawer-item-signal-state-value="#{@signal.state}" data-notification-drawer-item-signal-id-value="#{@signal.id}"]
2
- .flex.items-center.px-4.py-2.text-sm.text-gray-500
3
- .w-6.h-6.mr-1
4
- - if @signal.kind == "success"
5
- svg.signum-notification-icon-success[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"]
6
- path[stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"]
7
- - elsif @signal.kind == "error"
8
- svg.signum-notification-icon-error[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor"]
9
- path[stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z"]
10
- - else
11
- svg.signum-notification-icon-info[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"]
12
- path[stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"]
13
- p
14
- = sanitize @signal.text
1
+ .hover:bg-gray-50 data-controller="signum-notification-drawer-item" data-signum-notification-drawer-target="item" data-signum-notification-drawer-item-signal-state-value="#{signal.state}" data-signum-notification-drawer-item-signal-id-value="#{signal.id}" id="notification_#{data[:type]}_parent_#{signal.signalable_id}_#{signal.id}"
2
+ = render(Signum::NotificationBody::Component.new(signal, data))
@@ -1,8 +1,16 @@
1
1
  module Signum
2
2
  module NotificationDrawerItem
3
3
  class Component < ViewComponent::Base
4
- def initialize(signal)
4
+ attr_reader :signal, :data
5
+
6
+ with_collection_parameter :signal
7
+
8
+ def initialize(signal:, data: nil)
5
9
  @signal = signal
10
+ @data = data.nil? ? {} : data.deep_symbolize_keys
11
+
12
+ @data[:timeout] ||= 5
13
+ @data[:type] ||= :drawer_item
6
14
  end
7
15
  end
8
16
  end
@@ -0,0 +1,30 @@
1
+ import ApplicationController from "signum/controllers/application_controller"
2
+
3
+ export default class extends ApplicationController {
4
+ static targets = []
5
+ static values = {
6
+ signalId: String,
7
+ signalState: String,
8
+ }
9
+
10
+ connect() {
11
+ const niE = new CustomEvent("nd-item-activity", {
12
+ bubbles: true,
13
+ detail: "added",
14
+ })
15
+ window.dispatchEvent(niE)
16
+ if (this.signalStateValue == "broadcasted") {
17
+ fetch("/signal/show", {
18
+ method: "POST",
19
+ headers: {
20
+ "Content-Type": "application/json",
21
+ },
22
+ body: JSON.stringify({ id: this.signalIdValue }),
23
+ })
24
+ .then((res) => {})
25
+ .catch((err) => {
26
+ console.log(err)
27
+ })
28
+ }
29
+ }
30
+ }
@@ -0,0 +1 @@
1
+ import "signum/controllers"
@@ -0,0 +1,12 @@
1
+ import { Application } from '@hotwired/stimulus'
2
+
3
+ let application
4
+ if (window.Stimulus) {
5
+ application = window.Stimulus
6
+ } else {
7
+ application = Application.start()
8
+ application.debug = false
9
+ window.Stimulus = application
10
+ }
11
+
12
+ export { application }
@@ -0,0 +1,4 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ export default class ApplicationController extends Controller {
4
+ }
@@ -0,0 +1,14 @@
1
+ import { application } from "signum/controllers/application"
2
+
3
+ // Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
4
+ // import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
5
+ // lazyLoadControllersFrom("signum/controllers", application)
6
+
7
+ import NotificationBodyController from "signum/components/notification_body/component_controller";
8
+ application.register("signum-notification-body", NotificationBodyController);
9
+
10
+ import NotificationDrawerController from "signum/components/notification_drawer/component_controller";
11
+ application.register("signum-notification-drawer", NotificationDrawerController);
12
+
13
+ import NotificationDrawerItemController from "signum/components/notification_drawer_item/component_controller";
14
+ application.register("signum-notification-drawer-item", NotificationDrawerItemController);
@@ -1,13 +1,43 @@
1
1
  module Signum
2
2
  class Signal < ApplicationRecord
3
3
  belongs_to :signalable, polymorphic: true
4
- after_commit :signal
4
+ belongs_to :subjectable, polymorphic: true, optional: true
5
+
6
+ has_many_attached :attachments
7
+
8
+ after_create_commit :broadcast_create
9
+ after_update_commit :broadcast_update
10
+
11
+ def broadcast_create
12
+ broadcast! if can_broadcast?
13
+
14
+ broadcast_prepend_to(:signals, target: Signum.config.balloon_notifications_container_id.call,
15
+ html: ApplicationController.render(Signum::Notification::Component.new(self)))
16
+
17
+ broadcast_prepend_to(:signals, target: Signum.config.drawer_notifications_container_id.call,
18
+ html: ApplicationController.render(Signum::NotificationDrawerItem::Component.new(signal: self)))
19
+ end
20
+
21
+ def broadcast_update
22
+ return if saved_change_to_state? && (broadcasted? || shown?)
23
+
24
+ if saved_change_to_state? && closed?
25
+ broadcast_remove_to(:signals, target: "notification_drawer_item_parent_#{signalable_id}_#{id}")
26
+ return
27
+ end
28
+
29
+ broadcast_replace_to(:signals, target: "notification_balloon_#{signalable_id}_#{id}",
30
+ html: ApplicationController.render(Signum::NotificationBody::Component.new(self, { type: :balloon, timeout: 5 })))
31
+ broadcast_replace_to(:signals, target: "notification_drawer_item_#{signalable_id}_#{id}",
32
+ html: ApplicationController.render(Signum::NotificationBody::Component.new(self, { type: :drawer_item, timeout: 5 })))
33
+ end
5
34
 
6
35
  validates :text, presence: true
7
36
 
8
37
  scope :pending, -> { with_state(:pending) }
9
38
  scope :shown, -> { with_state(:shown) }
10
39
  scope :closed, -> { with_state(:closed) }
40
+ scope :unclosed_sticky, ->(signalable) { without_state(:closed).where(signalable: signalable, sticky: true) }
11
41
 
12
42
  state_machine initial: :pending do
13
43
  state :pending
@@ -28,11 +58,5 @@ module Signum
28
58
  transition any => :closed
29
59
  end
30
60
  end
31
-
32
- private
33
-
34
- def signal
35
- Signum::SendSignalsJob.perform_later(self) if pending?
36
- end
37
61
  end
38
62
  end
@@ -0,0 +1,6 @@
1
+ pin "@hotwired/stimulus", to: "@hotwired--stimulus.js" # @3.2.2
2
+
3
+ pin "signum", to: "signum/application.js"
4
+
5
+ pin_all_from Signum::Engine.root.join("app/javascript/signum/controllers"), under: "signum/controllers", to: "signum/controllers"
6
+ pin_all_from Signum::Engine.root.join("app/components/signum"), under: "signum/components", to: "signum"
data/config/routes.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  Signum::Engine.routes.draw do
2
2
  post 'signal/show', to: 'signal#show'
3
3
  post 'signal/close', to: 'signal#close'
4
+ post 'signal/open_stickies', to: 'signal#open_stickies'
4
5
  end
@@ -0,0 +1,7 @@
1
+ class AddColumnsToSignumSignal < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :signum_signals, :metadata, :jsonb
4
+ add_column :signum_signals, :total, :integer
5
+ add_column :signum_signals, :count, :integer
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class AddSubjectToSignals < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_reference :signum_signals, :subjectable, type: :uuid, polymorphic: true, null: true
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ module Signum
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ def create_initializer_file
6
+ template "config/initializers/signum.rb"
7
+ end
8
+
9
+ def add_route
10
+ return if Rails.application.routes.routes.detect { |route| route.app.app == Signum::Engine }
11
+ route %(mount Signum::Engine => "/signum")
12
+ end
13
+
14
+ def copy_migrations
15
+ rake "signum:install:migrations"
16
+ end
17
+
18
+ def tailwindcss_config
19
+ rake "signum:tailwindcss:config"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Signum
4
+ module Generators
5
+ class TailwindConfigGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('../templates', __dir__)
7
+ desc 'Configures tailwind.config.js and application.tailwindcss.css'
8
+
9
+ def add_content_to_tailwind_config
10
+ inject_into_file "config/tailwind.config.js", before: "],\n theme: {" do
11
+ " // Signum content\n" +
12
+ %w[/app/views/**/* /app/helpers/**/* /app/controllers/**/* /app/components/**/* /app/javascript/**/*.js /app/assets/**/*.css].map { |path| " \"#{Signum::Engine.root}#{path}\"" }.join(",\n") +
13
+ ",\n "
14
+ end
15
+ end
16
+
17
+ def add_content_application_tailwind_css
18
+ inject_into_file "app/assets/stylesheets/application.tailwind.css", before: "@tailwind base;" do
19
+ "@import '#{Signum::Engine.root}/app/assets/stylesheets/signum/application.css';\n"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ Signum.setup do |config|
4
+ config.hide_after = 60_000 if Rails.env.test?
5
+ config.current_user = -> { Current.user }
6
+ config.drawer_notifications_container_id = -> { "drawer_notifications_#{Current.user.id}" }
7
+ config.balloon_notifications_container_id = -> { "notifications_#{Current.user.id}" }
8
+ end
@@ -1,13 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signum
4
+ module Options
5
+ module ClassMethods
6
+ def option(name, default: nil)
7
+ attr_accessor(name)
8
+
9
+ schema[name] = default
10
+ end
11
+
12
+ def schema
13
+ @schema ||= {}
14
+ end
15
+ end
16
+
17
+ def set_defaults!
18
+ self.class.schema.each do |name, default|
19
+ instance_variable_set("@#{name}", default)
20
+ end
21
+ end
22
+
23
+ def self.included(cls)
24
+ cls.extend(ClassMethods)
25
+ end
26
+ end
27
+
4
28
  class Configuration
5
- attr_accessor :hide_after
6
- attr_accessor :user_model_name
29
+ include Options
30
+
31
+ option :logger, default: Rails.logger
32
+ option :user_model_name, default: 'User'
33
+ option :hide_after, default: 3000
34
+ option :base_controller, default: '::ApplicationController'
35
+ option :base_service, default: '::ApplicationService'
36
+ option :base_service_context, default: '::ApplicationContext'
37
+ option :current_user, default: -> {}
38
+ option :drawer_notifications_container_id, default: -> {}
39
+ option :balloon_notifications_container_id, default: -> {}
40
+ option :icons,
41
+ default: { info: 'fa-solid fa-circle-info fa-lg',
42
+ error: 'fa-solid fa-square-xmark fa-lg',
43
+ success: 'fa-solid fa-circle-check fa-lg',
44
+ warning: 'fa-solid fa-triangle-exclamation fa-lg',
45
+ unread_main: 'fa-solid fa-bell-ring',
46
+ read_main: 'fa-solid fa-bell' }
7
47
 
8
48
  def initialize
9
- @user_model_name = "User"
10
- @hide_after = 3000
49
+ set_defaults!
50
+ end
51
+ end
52
+
53
+ module Configurable
54
+ attr_writer :config
55
+
56
+ def config
57
+ @config ||= Configuration.new
58
+ end
59
+
60
+ def configure
61
+ yield(config)
62
+ end
63
+ alias setup configure
64
+
65
+ def reset_config!
66
+ @config = Configuration.new
11
67
  end
12
68
  end
13
69
  end
data/lib/signum/engine.rb CHANGED
@@ -1,13 +1,25 @@
1
+ require 'slim'
2
+ require 'tailwindcss-rails'
3
+ require "importmap-rails"
4
+ require "turbo-rails"
5
+ require "stimulus-rails"
6
+
1
7
  module Signum
2
8
  class Engine < ::Rails::Engine
3
9
  isolate_namespace Signum
4
10
 
5
- initializer :append_migrations do |app|
6
- unless app.root.to_s.match? root.to_s
7
- config.paths['db/migrate'].expanded.each do |expanded_path|
8
- app.config.paths['db/migrate'] << expanded_path
9
- end
10
- end
11
+ initializer 'signum.assets' do |app|
12
+ app.config.assets.paths << root.join("app/javascript")
13
+ app.config.assets.paths << root.join("app/components")
14
+ app.config.assets.paths << root.join("vendor/javascript")
15
+ app.config.assets.precompile += %w[signum_manifest]
16
+ end
17
+
18
+ initializer 'signum.importmap', before: "importmap" do |app|
19
+ app.config.importmap.paths << root.join("config/importmap.rb")
20
+ app.config.importmap.cache_sweepers << root.join("app/javascript")
21
+ app.config.importmap.cache_sweepers << root.join("app/components")
22
+ app.config.importmap.cache_sweepers << root.join("vendor/javascript")
11
23
  end
12
24
  end
13
25
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signum
4
- VERSION = '0.3.12'
4
+ VERSION = "0.4.8"
5
5
  end
data/lib/signum.rb CHANGED
@@ -1,6 +1,6 @@
1
- require "signum/engine"
2
- require "signum/active_record_helpers"
3
- require "signum/configuration"
1
+ require 'signum/engine'
2
+ require 'signum/active_record_helpers'
3
+ require 'signum/configuration'
4
4
 
5
5
  module Signum
6
6
  class Error < StandardError
@@ -26,8 +26,10 @@ module Signum
26
26
 
27
27
  if signalable_receiver.is_a?(Signum.config.user_model_name.constantize)
28
28
  signalable_receiver.signals.create!(options)
29
+
29
30
  elsif signalable_receiver.respond_to?(:each)
30
31
  signalable_receiver.each { |signalable| signal(signalable, options) }
32
+ nil
31
33
  end
32
34
  end
33
35
 
@@ -35,21 +37,28 @@ module Signum
35
37
  def info(signalable, options)
36
38
  return unless signalable
37
39
 
38
- signal(signalable, options.merge(kind: "info"))
40
+ signal(signalable, options.merge(kind: 'info', icon: Signum.config.icons[:info]))
39
41
  end
40
42
 
41
43
  # Signal about an error
42
44
  def error(signalable, options)
43
45
  return unless signalable
44
46
 
45
- signal(signalable, options.merge(kind: "error"))
47
+ signal(signalable, options.merge(kind: 'error', icon: Signum.config.icons[:error]))
46
48
  end
47
49
 
48
50
  # Signal about something that went sucessfully
49
51
  def success(signalable, options)
50
52
  return unless signalable
51
53
 
52
- signal(signalable, options.merge(kind: "success"))
54
+ signal(signalable, options.merge(kind: 'success', icon: Signum.config.icons[:success]))
55
+ end
56
+
57
+ # Signal about something that could go wrong
58
+ def warning(signalable, options)
59
+ return unless signalable
60
+
61
+ signal(signalable, options.merge(kind: 'warning', icon: Signum.config.icons[:warning]))
53
62
  end
54
63
  end
55
64
 
@@ -0,0 +1,13 @@
1
+ namespace :signum do
2
+ namespace :tailwindcss do
3
+ desc "Configure your Tailwind CSS"
4
+ task :config do
5
+ Rails::Generators.invoke("signum:tailwind_config", ["--force"])
6
+ end
7
+ end
8
+ end
9
+
10
+ if Rake::Task.task_defined?("tailwindcss:build")
11
+ Rake::Task["tailwindcss:build"].enhance(["signum:tailwindcss:config"])
12
+ Rake::Task["tailwindcss:watch"].enhance(["signum:tailwindcss:config"])
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.12
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom de Grunt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-02 00:00:00.000000000 Z
11
+ date: 2024-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -80,6 +80,76 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: slim-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: tailwindcss-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: importmap-rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: turbo-rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: stimulus-rails
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
83
153
  description: Rails engine with replacement for flash messages, Signum allows for messages
84
154
  from background jobs.
85
155
  email:
@@ -91,33 +161,49 @@ files:
91
161
  - MIT-LICENSE
92
162
  - README.md
93
163
  - Rakefile
94
- - app/channels/signum/application_cable/channel.rb
95
- - app/channels/signum/application_cable/connection.rb
164
+ - app/assets/config/signum_manifest.js
165
+ - app/assets/stylesheets/signum/application.css
166
+ - app/components/signum/notification/component.css
96
167
  - app/components/signum/notification/component.html.slim
97
168
  - app/components/signum/notification/component.rb
98
- - app/components/signum/notification/component.scss
169
+ - app/components/signum/notification_body/component.css
170
+ - app/components/signum/notification_body/component.html.slim
171
+ - app/components/signum/notification_body/component.rb
172
+ - app/components/signum/notification_body/component_controller.js
173
+ - app/components/signum/notification_drawer/component.css
99
174
  - app/components/signum/notification_drawer/component.html.slim
100
175
  - app/components/signum/notification_drawer/component.rb
101
- - app/components/signum/notification_drawer/component.scss
176
+ - app/components/signum/notification_drawer/component_controller.js
177
+ - app/components/signum/notification_drawer_item/component.css
102
178
  - app/components/signum/notification_drawer_item/component.html.slim
103
179
  - app/components/signum/notification_drawer_item/component.rb
104
- - app/components/signum/notification_drawer_item/component.scss
180
+ - app/components/signum/notification_drawer_item/component_controller.js
105
181
  - app/controllers/signum/api_controller.rb
106
182
  - app/controllers/signum/application_controller.rb
107
183
  - app/controllers/signum/signal_controller.rb
108
184
  - app/helpers/signum/application_helper.rb
185
+ - app/javascript/signum/application.js
186
+ - app/javascript/signum/controllers/application.js
187
+ - app/javascript/signum/controllers/application_controller.js
188
+ - app/javascript/signum/controllers/index.js
109
189
  - app/jobs/signum/application_job.rb
110
- - app/jobs/signum/send_signals_job.rb
111
190
  - app/mailers/signum/application_mailer.rb
112
191
  - app/models/signum/application_record.rb
113
192
  - app/models/signum/signal.rb
193
+ - config/importmap.rb
114
194
  - config/routes.rb
115
195
  - db/migrate/20201125175035_create_signum_signals.rb
196
+ - db/migrate/20230317123138_add_columns_to_signum_signal.rb
197
+ - db/migrate/20231218095011_add_subject_to_signals.rb
198
+ - lib/generators/signum/install_generator.rb
199
+ - lib/generators/signum/tailwind_config_generator.rb
200
+ - lib/generators/signum/templates/config/initializers/signum.rb
116
201
  - lib/signum.rb
117
202
  - lib/signum/active_record_helpers.rb
118
203
  - lib/signum/configuration.rb
119
204
  - lib/signum/engine.rb
120
205
  - lib/signum/version.rb
206
+ - lib/tasks/signum_tasks.rake
121
207
  homepage: https://github.com/entdec/signum
122
208
  licenses:
123
209
  - MIT
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Signum
4
- module ApplicationCable
5
- class Channel < ActionCable::Channel::Base
6
- end
7
- end
8
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Signum
4
- module ApplicationCable
5
- class Connection < ActionCable::Connection::Base
6
- identified_by :current_user
7
-
8
- def connect
9
- self.current_user = find_verified_user
10
- logger.add_tags 'ActionCable', current_user.name
11
- end
12
-
13
- private
14
-
15
- def find_verified_user
16
- if verified_user = env['warden'].user
17
- verified_user
18
- else
19
- reject_unauthorized_connection
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,34 +0,0 @@
1
- .signum-notification{
2
- @apply pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 mt-1;
3
- }
4
-
5
- .signum-notification-icon{
6
- @apply h-6 w-6;
7
- }
8
-
9
- .signum-notification-icon-success{
10
- @extend .signum-notification-icon;
11
- @apply text-green-400;
12
- }
13
-
14
- .signum-notification-icon-error{
15
- @extend .signum-notification-icon;
16
- @apply text-red-400;
17
- }
18
-
19
- .signum-notification-icon-info{
20
- @extend .signum-notification-icon;
21
- @apply text-sky-400;
22
- }
23
-
24
- .signum-notification-title{
25
- @apply text-sm font-medium text-gray-900;
26
- }
27
-
28
- .signum-notification-body{
29
- @apply mt-1 text-sm text-gray-500;
30
- }
31
-
32
- .signum-notification-button-close{
33
- @apply inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2;
34
- }
@@ -1,7 +0,0 @@
1
- .signum-notification-drawer-button{
2
- @apply w-8 h-8 bg-white m-0 rounded-full text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:bg-gray-900 dark:border-gray-700
3
- }
4
-
5
- .signum-notification-drawer-tray{
6
- @apply absolute right-0 z-10 mx-1 w-1/3 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 overflow-y-auto max-h-screen
7
- }
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Signum
4
- class SendSignalsJob < ApplicationJob
5
- def perform(signal)
6
- signal.broadcast!
7
- Turbo::StreamsChannel.broadcast_prepend_to(:signals, target: "notifications_#{signal.signalable_id}",
8
- html: ApplicationController.render(Signum::Notification::Component.new(signal)))
9
- Turbo::StreamsChannel.broadcast_prepend_to(:signals, target: "drawer_notifications_#{signal.signalable_id}",
10
- html: ApplicationController.render(Signum::NotificationDrawerItem::Component.new(signal)))
11
- end
12
- end
13
- end