signum 0.3.12 → 0.4.8

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.
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