solid_errors 0.4.3 → 0.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a881ce47539838e01f1c118484b72ca112c5dd5abd87452113d3f74c4539746
4
- data.tar.gz: 25c83eacccc50d1c54461ded048dab4b89a86bad71d6963e292af3e6f1cc49b2
3
+ metadata.gz: ef3e4cca2bd412b918d7b7c36b3e754d79fefbc06e754a54fd58d5b04ef02a79
4
+ data.tar.gz: 1ca69a12aa28386778c66d7cd9114c06d20fbce1f846bf78391cfcad6796ff63
5
5
  SHA512:
6
- metadata.gz: 0adf72d51727ed89a8d8cc27d9145cbfc4e95e7d16d951a5c3849405ab957d6633ffdf84787c492cfb10a37efaf674ed75480404a18640e46e56498c1179b307
7
- data.tar.gz: beaedce40a2d77577b2c8dc27fc0dd228f39c8d6090510a55538e92a144e845ec781f01d5bc093405c2d493c8d41f470ada4502eaee2582d7ba5c8c80c2ead84
6
+ metadata.gz: 1d5313d9fd88ce1d75bbd1faf09bd47bca8caaafd61ea7930f982e02b117957b11b077406c5c8109531d7d718a37ee344b136f9fbf483fe371271951ee137b55
7
+ data.tar.gz: cd5a876a317307109b4660e39b11be2e80b6fa2b7a5a33db00c3edac84bcf27d0a3dc777a2a3f49837411e4a3168483f2c57656bc18e6d24903d5106400a697c
data/README.md CHANGED
@@ -69,6 +69,54 @@ Please consult the [official guides](https://guides.rubyonrails.org/error_report
69
69
 
70
70
  There are intentionally few features; you can view and resolve errors. That’s it. The goal is to provide a simple, lightweight, and performant solution for tracking exceptions in your Rails application. If you need more features, you should probably use a 3rd party service like [Honeybadger](https://www.honeybadger.io/), whose MIT-licensed [Ruby agent gem](https://github.com/honeybadger-io/honeybadger-ruby) provided a couple of critical pieces of code for this project.
71
71
 
72
+ ### Manually reporting an Error
73
+
74
+ Errors can be added to Solid Errors via the [Rails error reporter](https://guides.rubyonrails.org/error_reporting.html).
75
+
76
+ There are [three ways](https://guides.rubyonrails.org/error_reporting.html#using-the-error-reporter) you can use the error reporter:
77
+
78
+ `Rails.error.handle` will report any error raised within the block. It will then swallow the error, and the rest of your code outside the block will continue as normal.
79
+
80
+ ```ruby
81
+ result = Rails.error.handle do
82
+ 1 + '1' # raises TypeError
83
+ end
84
+ result # => nil
85
+ 1 + 1 # This will be executed
86
+ ```
87
+
88
+ `Rails.error.record` will report errors to all registered subscribers and then re-raise the error, meaning that the rest of your code won't execute.
89
+
90
+ ```ruby
91
+ Rails.error.record do
92
+ 1 + '1' # raises TypeError
93
+ end
94
+ 1 + 1 # This won't be executed
95
+ ```
96
+
97
+ You can also manually report errors by calling `Rails.error.report`:
98
+
99
+ ```ruby
100
+ begin
101
+ # code
102
+ rescue StandardError => e
103
+ Rails.error.report(e)
104
+ end
105
+ ```
106
+
107
+ All 3 reporting APIs (`#handle`, `#record`, and `#report`) support the following options, which are then passed along to all registered subscribers:
108
+
109
+ * `handled`: a Boolean to indicate if the error was handled. This is set to `true` by default. `#record` sets this to `false`.
110
+ * `severity`: a Symbol describing the severity of the error. Expected values are: `:error`, `:warning`, and `:info`. `#handle` sets this to `:warning`, while `#record` sets it to `:error`.
111
+ * `context`: a Hash to provide more context about the error, like request or user details
112
+ * `source`: a String about the source of the error. The default source is `"application"`. Errors reported by internal libraries may set other sources; the Redis cache library may use "redis_cache_store.active_support", for instance. Your subscriber can use the source to ignore errors you aren't interested in.
113
+
114
+ ```ruby
115
+ Rails.error.handle(context: { user_id: user.id }, severity: :info) do
116
+ # ...
117
+ end
118
+ ```
119
+
72
120
  ### Configuration
73
121
 
74
122
  You can configure Solid Errors via the Rails configuration object, under the `solid_errors` key. Currently, 6 configuration options are available:
@@ -2,14 +2,16 @@ module SolidErrors
2
2
  class ErrorsController < ApplicationController
3
3
  around_action :force_english_locale!
4
4
 
5
- before_action :set_error, only: %i[show update]
5
+ before_action :set_error, only: %i[show update destroy]
6
+
7
+ helper_method :error_scope
6
8
 
7
9
  # GET /errors
8
10
  def index
9
11
  errors_table = Error.arel_table
10
12
  occurrences_table = Occurrence.arel_table
11
-
12
- @errors = Error.unresolved
13
+ query_scope = error_scope.resolved? ? Error.resolved : Error.unresolved
14
+ @errors = query_scope
13
15
  .joins(:occurrences)
14
16
  .select(errors_table[Arel.star],
15
17
  occurrences_table[:created_at].maximum.as("recent_occurrence"),
@@ -30,6 +32,16 @@ module SolidErrors
30
32
  redirect_to errors_path, notice: "Error marked as resolved."
31
33
  end
32
34
 
35
+ # DELETE /errors/1
36
+ def destroy
37
+ if @error.resolved?
38
+ @error.destroy
39
+ redirect_to errors_path(scope: :resolved), notice: "Error deleted."
40
+ else
41
+ redirect_to error_path(@error), alert: "You must resolve the error before deleting it."
42
+ end
43
+ end
44
+
33
45
  private
34
46
 
35
47
  # Only allow a list of trusted parameters through.
@@ -44,5 +56,9 @@ module SolidErrors
44
56
  def force_english_locale!(&action)
45
57
  I18n.with_locale(:en, &action)
46
58
  end
59
+
60
+ def error_scope
61
+ ActiveSupport::StringInquirer.new(params[:scope] || "unresolved")
62
+ end
47
63
  end
48
64
  end
@@ -6,7 +6,7 @@ module SolidErrors
6
6
  @error = occurrence.error
7
7
 
8
8
  mail(
9
- subject: "#{@error.emoji} #{@error.exception_class}",
9
+ subject: "#{@error.severity_emoji} #{@error.exception_class}",
10
10
  from: SolidErrors.email_from,
11
11
  to: SolidErrors.email_to
12
12
  )
@@ -12,6 +12,14 @@ module SolidErrors
12
12
  warning: "bg-yellow-100 text-yellow-800",
13
13
  info: "bg-blue-100 text-blue-800"
14
14
  }
15
+ STATUS_TO_EMOJI = {
16
+ resolved: "✅",
17
+ unresolved: "⏳"
18
+ }
19
+ STATUS_TO_BADGE_CLASSES = {
20
+ resolved: "bg-green-100 text-green-800",
21
+ unresolved: "bg-violet-100 text-violet-800"
22
+ }
15
23
 
16
24
  has_many :occurrences, class_name: "SolidErrors::Occurrence", dependent: :destroy
17
25
 
@@ -22,12 +30,28 @@ module SolidErrors
22
30
  scope :resolved, -> { where.not(resolved_at: nil) }
23
31
  scope :unresolved, -> { where(resolved_at: nil) }
24
32
 
25
- def emoji
33
+ def severity_emoji
26
34
  SEVERITY_TO_EMOJI[severity.to_sym]
27
35
  end
28
36
 
29
- def badge_classes
37
+ def severity_badge_classes
30
38
  "px-2 inline-flex text-sm font-semibold rounded-md #{SEVERITY_TO_BADGE_CLASSES[severity.to_sym]}"
31
39
  end
40
+
41
+ def status
42
+ resolved? ? :resolved : :unresolved
43
+ end
44
+
45
+ def status_emoji
46
+ STATUS_TO_EMOJI[status]
47
+ end
48
+
49
+ def status_badge_classes
50
+ "px-2 inline-flex text-sm font-semibold rounded-md #{STATUS_TO_BADGE_CLASSES[status]}"
51
+ end
52
+
53
+ def resolved?
54
+ resolved_at.present?
55
+ end
32
56
  end
33
57
  end
@@ -617,6 +617,10 @@
617
617
  margin-bottom: 0.75rem
618
618
  }
619
619
 
620
+ .mb-6{
621
+ margin-bottom: 1.5rem
622
+ }
623
+
620
624
  .ml-6{
621
625
  margin-left: 1.5rem
622
626
  }
@@ -629,6 +633,10 @@
629
633
  margin-top: 1rem
630
634
  }
631
635
 
636
+ .-mb-px {
637
+ margin-bottom: -1px;
638
+ }
639
+
632
640
  .inline-block{
633
641
  display: inline-block
634
642
  }
@@ -743,6 +751,12 @@
743
751
  margin-bottom: calc(1.5rem * var(--tw-space-y-reverse))
744
752
  }
745
753
 
754
+ .space-x-8 > :not([hidden]) ~ :not([hidden]) {
755
+ --tw-space-x-reverse: 0;
756
+ margin-right: calc(2rem * var(--tw-space-x-reverse));
757
+ margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
758
+ }
759
+
746
760
  .divide-y > :not([hidden]) ~ :not([hidden]){
747
761
  --tw-divide-y-reverse: 0;
748
762
  border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
@@ -770,6 +784,10 @@
770
784
  border-radius: 0.25rem
771
785
  }
772
786
 
787
+ .rounded-md{
788
+ border-radius: 0.375rem
789
+ }
790
+
773
791
  .rounded-lg{
774
792
  border-radius: 0.5rem
775
793
  }
@@ -787,6 +805,10 @@
787
805
  border-bottom-width: 1px
788
806
  }
789
807
 
808
+ .border-b-2 {
809
+ border-bottom-width: 2px;
810
+ }
811
+
790
812
  .border-black{
791
813
  --tw-border-opacity: 1;
792
814
  border-color: rgb(0 0 0 / var(--tw-border-opacity))
@@ -802,6 +824,15 @@
802
824
  border-color: rgb(209 213 219 / var(--tw-border-opacity))
803
825
  }
804
826
 
827
+ .border-red-500{
828
+ --tw-border-opacity: 1;
829
+ border-color: rgb(239 68 68 / var(--tw-border-opacity))
830
+ }
831
+
832
+ .border-transparent {
833
+ border-color: transparent;
834
+ }
835
+
805
836
  .bg-gray-100{
806
837
  --tw-bg-opacity: 1;
807
838
  background-color: rgb(243 244 246 / var(--tw-bg-opacity))
@@ -848,6 +879,11 @@
848
879
  padding-right: 0px
849
880
  }
850
881
 
882
+ .px-1 {
883
+ padding-left: 0.25rem;
884
+ padding-right: 0.25rem;
885
+ }
886
+
851
887
  .px-2{
852
888
  padding-left: 0.5rem;
853
889
  padding-right: 0.5rem
@@ -916,10 +952,6 @@
916
952
  padding-top: 1.75rem
917
953
  }
918
954
 
919
- .rounded-md{
920
- border-radius: 0.375rem
921
- }
922
-
923
955
  .text-left{
924
956
  text-align: left
925
957
  }
@@ -931,7 +963,7 @@
931
963
  .text-right{
932
964
  text-align: right
933
965
  }
934
-
966
+
935
967
  .text-black{
936
968
  --tw-text-opacity: 1;
937
969
  color: rgb(0 0 0 / var(--tw-text-opacity))
@@ -987,6 +1019,16 @@
987
1019
  background-color: rgb(254 249 195 / var(--tw-bg-opacity))
988
1020
  }
989
1021
 
1022
+ .bg-green-100{
1023
+ --tw-bg-opacity: 1;
1024
+ background-color: rgb(220 252 231 / var(--tw-bg-opacity))
1025
+ }
1026
+
1027
+ .bg-violet-100{
1028
+ --tw-bg-opacity: 1;
1029
+ background-color: rgb(237 233 254 / var(--tw-bg-opacity))
1030
+ }
1031
+
990
1032
  .text-blue-400{
991
1033
  --tw-text-opacity: 1;
992
1034
  color: rgb(96 165 250 / var(--tw-text-opacity))
@@ -1037,6 +1079,16 @@
1037
1079
  color: rgb(133 77 14 / var(--tw-text-opacity))
1038
1080
  }
1039
1081
 
1082
+ .text-green-800{
1083
+ --tw-text-opacity: 1;
1084
+ color: rgb(22 101 52 / var(--tw-text-opacity))
1085
+ }
1086
+
1087
+ .text-violet-800{
1088
+ --tw-text-opacity: 1;
1089
+ color: rgb(91 33 182 / var(--tw-text-opacity))
1090
+ }
1091
+
1040
1092
  .text-white{
1041
1093
  --tw-text-opacity: 1;
1042
1094
  color: rgb(255 255 255 / var(--tw-text-opacity))
@@ -1046,6 +1098,14 @@
1046
1098
  text-decoration-line: underline
1047
1099
  }
1048
1100
 
1101
+ .uppercase{
1102
+ text-transform: uppercase
1103
+ }
1104
+
1105
+ .whitespace-pre-wrap{
1106
+ white-space: pre-wrap
1107
+ }
1108
+
1049
1109
  .transition-opacity{
1050
1110
  transition-property: opacity;
1051
1111
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
@@ -1082,6 +1142,11 @@
1082
1142
  --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity))
1083
1143
  }
1084
1144
 
1145
+ .hover\:ring-red-200:hover{
1146
+ --tw-ring-opacity: 1;
1147
+ --tw-ring-color: rgb(254 202 202 / var(--tw-ring-opacity))
1148
+ }
1149
+
1085
1150
  .hover\:bg-black:hover{
1086
1151
  --tw-bg-opacity: 1;
1087
1152
  background-color: rgb(0 0 0 / var(--tw-bg-opacity))
@@ -1092,6 +1157,16 @@
1092
1157
  color: rgb(255 255 255 / var(--tw-text-opacity))
1093
1158
  }
1094
1159
 
1160
+ .hover\:text-gray-700:hover {
1161
+ --tw-text-opacity: 1;
1162
+ color: rgb(55 65 81 / var(--tw-text-opacity));
1163
+ }
1164
+
1165
+ .hover\:border-gray-300:hover {
1166
+ --tw-border-opacity: 1;
1167
+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
1168
+ }
1169
+
1095
1170
  @media (min-width: 640px){
1096
1171
  .sm\:mx-0{
1097
1172
  margin-left: 0px;
@@ -1,6 +1,6 @@
1
1
  <html>
2
2
  <head>
3
- <title>Solid Errors | <%= @error.emoji %> <%= @error.exception_class %></title>
3
+ <title>Solid Errors | <%= @error.severity_emoji %> <%= @error.exception_class %></title>
4
4
  <%= render "layouts/solid_errors/style" %>
5
5
  </head>
6
6
  <body>
@@ -1,16 +1,13 @@
1
1
  <div class="inline-flex items-center justify-start flex-wrap gap-3 whitespace-nowrap">
2
- <%= link_to errors_path, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-gray-100 text-initial border-gray-300 hover:ring-gray-200 hover:ring-8" do %>
2
+ <%= link_to errors_path(scope: error.resolved? ? :resolved : :unresolved), class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-gray-100 text-initial border-gray-300 hover:ring-gray-200 hover:ring-8" do %>
3
3
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
4
4
  <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
5
5
  </svg>
6
6
  <span>Back to errors</span>
7
7
  <% end %>
8
-
9
- <%= button_to error_path(error), method: :patch, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-transparent text-blue-500 border-blue-500 hover:ring-blue-200 hover:ring-8", params: { error: { resolved_at: Time.now } } do %>
10
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
11
- <path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0"/>
12
- <path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0z"/>
13
- </svg>
14
- <span>Resolve Error<span class="sr-only"> #<%= error.id %></span></span>
8
+ <% if error.resolved? %>
9
+ <%= render 'solid_errors/errors/delete_button', error: error %>
10
+ <% else %>
11
+ <%= render 'solid_errors/errors/resolve_button', error: error %>
15
12
  <% end %>
16
13
  </div>
@@ -0,0 +1,7 @@
1
+ <%# locals: (error:) -%>
2
+ <%= button_to error_path(error), method: :delete, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-transparent text-red-500 border-red-500 hover:ring-red-200 hover:ring-8" do %>
3
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="bi bi-trash3" fill="currentColor" viewBox="0 0 16 16">
4
+ <path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5M11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47M8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5"/>
5
+ </svg>
6
+ <span>Delete <span class="sr-only">, Error #<%= error.id %></span></span>
7
+ <% end %>
@@ -3,7 +3,7 @@
3
3
  <%= tag.section id: dom_id(error), class: "space-y-6" do %>
4
4
  <div class="flex justify-between items-center">
5
5
  <%= tag.h1 class: "font-bold flex items-center text-2xl gap-2" do %>
6
- <%= error.emoji %>
6
+ <%= error.severity_emoji %>
7
7
  <code><%= error.exception_class %></code>
8
8
  from
9
9
  <em><code><%= error.source %></code></em>
@@ -14,9 +14,31 @@
14
14
  </small>
15
15
  </div>
16
16
 
17
- <pre class=""><%= error.message %></pre>
17
+ <pre class="whitespace-pre-wrap"><%= error.message %></pre>
18
18
 
19
19
  <dl class="flex-1 grid grid-cols-2 gap-x-4">
20
+ <div class="flex items-center justify-between flex-wrap gap-x-2">
21
+ <dt class="font-bold">
22
+ <%= SolidErrors::Error.human_attribute_name(:severity) %>
23
+ </dt>
24
+ <dd class="inline-flex items-center gap-1">
25
+ <%= error.severity_emoji %>
26
+ <span class="<%= error.severity_badge_classes %>">
27
+ <%= error.severity %>
28
+ </span>
29
+ </dd>
30
+ </div>
31
+ <div class="flex items-center justify-between flex-wrap gap-x-2">
32
+ <dt class="font-bold">
33
+ <%= SolidErrors::Error.human_attribute_name(:status) %>
34
+ </dt>
35
+ <dd class="inline-flex items-center gap-1">
36
+ <%= error.status_emoji %>
37
+ <span class="<%= error.status_badge_classes %>">
38
+ <%= error.status %>
39
+ </span>
40
+ </dd>
41
+ </div>
20
42
  <div class="flex items-center justify-between flex-wrap gap-x-2">
21
43
  <dt class="font-bold">
22
44
  <%= SolidErrors::Error.human_attribute_name(:first_seen) %>
@@ -41,14 +63,6 @@
41
63
  </abbr>
42
64
  </dd>
43
65
  </div>
44
- <div class="flex items-center justify-between flex-wrap gap-x-2">
45
- <dt class="font-bold">
46
- <%= SolidErrors::Error.human_attribute_name(:occurrences) %>
47
- </dt>
48
- <dd class="inline-flex items-center gap-1">
49
- <%= error.occurrences.size %>
50
- </dd>
51
- </div>
52
66
  <div class="flex items-center justify-between flex-wrap gap-x-2">
53
67
  <dt class="font-bold">
54
68
  <%= SolidErrors::Error.human_attribute_name(:exception_class) %>
@@ -57,17 +71,6 @@
57
71
  <code><%= error.exception_class %></code>
58
72
  </dd>
59
73
  </div>
60
- <div class="flex items-center justify-between flex-wrap gap-x-2">
61
- <dt class="font-bold">
62
- <%= SolidErrors::Error.human_attribute_name(:severity) %>
63
- </dt>
64
- <dd class="inline-flex items-center gap-1">
65
- <%= error.emoji %>
66
- <span class="<%= error.badge_classes %>">
67
- <%= error.severity %>
68
- </span>
69
- </dd>
70
- </div>
71
74
  <div class="flex items-center justify-between flex-wrap gap-x-2">
72
75
  <dt class="font-bold">
73
76
  <%= SolidErrors::Error.human_attribute_name(:source) %>
@@ -0,0 +1,8 @@
1
+ <%# locals: (error:) -%>
2
+ <%= button_to error_path(error), method: :patch, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-transparent text-blue-500 border-blue-500 hover:ring-blue-200 hover:ring-8", params: { error: { resolved_at: Time.now } } do %>
3
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
4
+ <path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0"/>
5
+ <path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0z"/>
6
+ </svg>
7
+ <span>Resolve <span class="sr-only">, Error #<%= error.id %></span></span>
8
+ <% end %>
@@ -1,7 +1,8 @@
1
+ <%# locals: (error:) -%>
1
2
  <tr class="even:bg-gray-50 align-top">
2
3
  <td scope="col" class="whitespace-wrap py-4 pl-4 pr-3 font-medium text-gray-900 sm:pl-3">
3
4
  <div>
4
- <%= error.emoji %>
5
+ <%= error.severity_emoji %>
5
6
  <%= link_to error_path(error), class: "text-blue-400 underline inline-flex items-baseline gap-1" do %>
6
7
  <strong><code><%= error.exception_class %></code></strong>
7
8
  <% end %>
@@ -20,12 +21,10 @@
20
21
  </abbr>
21
22
  </td>
22
23
  <td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-3">
23
- <%= button_to error_path(error), method: :patch, class: "inline-flex items-center justify-center gap-2 font-medium cursor-pointer border rounded-lg py-3 px-5 bg-transparent text-blue-500 border-blue-500 hover:ring-blue-200 hover:ring-8", params: { error: { resolved_at: Time.now } } do %>
24
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
25
- <path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0"/>
26
- <path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0z"/>
27
- </svg>
28
- <span>Resolve<span class="sr-only">, Error #<%= error.id %></span></span>
24
+ <% if error.resolved? %>
25
+ <%= render 'solid_errors/errors/delete_button', error: error %>
26
+ <% else %>
27
+ <%= render 'solid_errors/errors/resolve_button', error: error %>
29
28
  <% end %>
30
29
  </td>
31
30
  </tr>
@@ -1,3 +1,25 @@
1
+ <div class="mb-6 border-b border-gray-300 flex justify-between items-baseline">
2
+ <h1 class="font-bold flex items-center text-2xl gap-2">
3
+ Errors
4
+ </h1>
5
+ <nav class="-mb-px flex space-x-8" aria-label="Tabs">
6
+ <%= link_to errors_path(scope: :unresolved), class: class_names(
7
+ "inline-flex items-center border-b-2 px-1 py-4 text-sm font-medium",
8
+ "border-blue-500 text-blue-500" => !error_scope.resolved?,
9
+ "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" => error_scope.resolved?) do %>
10
+ <span class="mr-2"><%= SolidErrors::Error::STATUS_TO_EMOJI[:unresolved] %></span>
11
+ <span>Unresolved</span>
12
+ <% end %>
13
+ <%= link_to errors_path(scope: :resolved), class: class_names(
14
+ "inline-flex items-center border-b-2 px-1 py-4 text-sm font-medium",
15
+ "border-blue-500 text-blue-500" => error_scope.resolved?,
16
+ "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" => !error_scope.resolved?) do %>
17
+ <span class="mr-2"><%= SolidErrors::Error::STATUS_TO_EMOJI[:resolved] %></span>
18
+ <span>Resolved</span>
19
+ <% end %>
20
+ </nav>
21
+ </div>
22
+
1
23
  <table class="min-w-full divide-y divide-gray-300">
2
24
  <thead>
3
25
  <tr>
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  SolidErrors::Engine.routes.draw do
2
2
  get "/" => "errors#index", :as => :root
3
3
 
4
- resources :errors, only: [:index, :show, :update], path: ""
4
+ resources :errors, only: [:index, :show, :update, :destroy], path: ""
5
5
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidErrors
4
- VERSION = "0.4.3"
4
+ VERSION = "0.5.0"
5
5
  end
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Margheim
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-21 00:00:00.000000000 Z
11
+ date: 2024-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '7.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '7.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: actionpack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '7.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '7.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: actionview
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '7.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '7.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activerecord
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '7.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '7.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activesupport
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '7.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '7.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: railties
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '7.0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '7.0'
97
97
  - !ruby/object:Gem::Dependency
@@ -130,7 +130,9 @@ files:
130
130
  - app/views/solid_errors/error_mailer/error_occurred.html.erb
131
131
  - app/views/solid_errors/error_mailer/error_occurred.text.erb
132
132
  - app/views/solid_errors/errors/_actions.html.erb
133
+ - app/views/solid_errors/errors/_delete_button.html.erb
133
134
  - app/views/solid_errors/errors/_error.html.erb
135
+ - app/views/solid_errors/errors/_resolve_button.html.erb
134
136
  - app/views/solid_errors/errors/_row.html.erb
135
137
  - app/views/solid_errors/errors/index.html.erb
136
138
  - app/views/solid_errors/errors/show.html.erb
@@ -167,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
169
  - !ruby/object:Gem::Version
168
170
  version: '0'
169
171
  requirements: []
170
- rubygems_version: 3.5.1
172
+ rubygems_version: 3.5.17
171
173
  signing_key:
172
174
  specification_version: 4
173
175
  summary: Database-backed Rails error subscriber