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.
- checksums.yaml +4 -4
- data/README.md +30 -1
- data/app/assets/config/signum_manifest.js +5 -0
- data/app/assets/stylesheets/signum/application.css +4 -0
- data/app/components/signum/notification/component.css +3 -0
- data/app/components/signum/notification/component.html.slim +2 -24
- data/app/components/signum/notification/component.rb +4 -0
- data/app/components/signum/notification_body/component.css +104 -0
- data/app/components/signum/notification_body/component.html.slim +41 -0
- data/app/components/signum/notification_body/component.rb +18 -0
- data/app/components/signum/notification_body/component_controller.js +41 -0
- data/app/components/signum/notification_drawer/component.css +7 -0
- data/app/components/signum/notification_drawer/component.html.slim +6 -11
- data/app/components/signum/notification_drawer/component.rb +3 -2
- data/app/components/signum/notification_drawer/component_controller.js +48 -0
- data/app/components/signum/notification_drawer_item/component.html.slim +2 -14
- data/app/components/signum/notification_drawer_item/component.rb +9 -1
- data/app/components/signum/notification_drawer_item/component_controller.js +30 -0
- data/app/javascript/signum/application.js +1 -0
- data/app/javascript/signum/controllers/application.js +12 -0
- data/app/javascript/signum/controllers/application_controller.js +4 -0
- data/app/javascript/signum/controllers/index.js +14 -0
- data/app/models/signum/signal.rb +31 -7
- data/config/importmap.rb +6 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20230317123138_add_columns_to_signum_signal.rb +7 -0
- data/db/migrate/20231218095011_add_subject_to_signals.rb +5 -0
- data/lib/generators/signum/install_generator.rb +22 -0
- data/lib/generators/signum/tailwind_config_generator.rb +24 -0
- data/lib/generators/signum/templates/config/initializers/signum.rb +8 -0
- data/lib/signum/configuration.rb +60 -4
- data/lib/signum/engine.rb +18 -6
- data/lib/signum/version.rb +1 -1
- data/lib/signum.rb +15 -6
- data/lib/tasks/signum_tasks.rake +13 -0
- metadata +94 -8
- data/app/channels/signum/application_cable/channel.rb +0 -8
- data/app/channels/signum/application_cable/connection.rb +0 -24
- data/app/components/signum/notification/component.scss +0 -34
- data/app/components/signum/notification_drawer/component.scss +0 -7
- data/app/jobs/signum/send_signals_job.rb +0 -13
- /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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c2d2692c406747889b91ad03f134e452024ef67230a300a58560a89c290de1a
|
4
|
+
data.tar.gz: 73032778b0e3195f582924477b1b0ba8c03fd1d9bb1c3a8cbdcf852e0085c42b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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,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';
|
@@ -1,24 +1,2 @@
|
|
1
|
-
.signum-notification
|
2
|
-
.
|
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
|
-
|
3
|
-
|
4
|
-
|
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
|
-
|
7
|
-
|
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
|
-
|
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
|
-
.
|
2
|
-
|
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
|
-
|
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,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);
|
data/app/models/signum/signal.rb
CHANGED
@@ -1,13 +1,43 @@
|
|
1
1
|
module Signum
|
2
2
|
class Signal < ApplicationRecord
|
3
3
|
belongs_to :signalable, polymorphic: true
|
4
|
-
|
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
|
data/config/importmap.rb
ADDED
@@ -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
@@ -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
|
data/lib/signum/configuration.rb
CHANGED
@@ -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
|
-
|
6
|
-
|
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
|
-
|
10
|
-
|
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
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
data/lib/signum/version.rb
CHANGED
data/lib/signum.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
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:
|
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:
|
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:
|
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.
|
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:
|
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/
|
95
|
-
- app/
|
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/
|
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/
|
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/
|
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,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
|
File without changes
|