eras 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +38 -0
- data/Rakefile +8 -0
- data/app/assets/builds/eras.css +1 -0
- data/app/assets/config/eras_manifest.js +1 -0
- data/app/assets/stylesheets/application.tailwind.css +13 -0
- data/app/assets/stylesheets/eras/application.css +15 -0
- data/app/controllers/eras/application_controller.rb +4 -0
- data/app/controllers/eras/errors_controller.rb +11 -0
- data/app/helpers/eras/application_helper.rb +4 -0
- data/app/models/eras/application_record.rb +5 -0
- data/app/views/eras/errors/_severity_cell.html.erb +8 -0
- data/app/views/eras/errors/index.html.erb +38 -0
- data/app/views/eras/errors/show.html.erb +14 -0
- data/app/views/layouts/eras/application.html.erb +19 -0
- data/app/views/shared/_navbar.html.erb +7 -0
- data/config/routes.rb +4 -0
- data/config/tailwind.config.js +22 -0
- data/lib/eras/adapters/file_system.rb +38 -0
- data/lib/eras/engine.rb +15 -0
- data/lib/eras/error_reporter.rb +22 -0
- data/lib/eras/version.rb +3 -0
- data/lib/eras.rb +7 -0
- data/lib/tasks/eras_tasks.rake +15 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2d2f4cfffca1ebd81a5d5c4d942a60831848d0e08d3e0a3797485a4e8180103c
|
4
|
+
data.tar.gz: 76f580ebdaea0dda0a8bda34c86f0bd513c041e5c92d2b7fddd942731a5ce400
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 81e46b4c372456839dcbef202e18c5ab5f2c2833702b1818f4380410d57362de0accf26a1013f4795fae61c64ae15cca32a6994a9a3df11d2a466d34fb5e0519
|
7
|
+
data.tar.gz: 5b8fd890c3b4ed2cf4a621ac9e8b7bc78d201cc9e0c83a77b9e22b77163ac768c23cf6e68d51b6e905c4f089a56be7b1f8c845b54b08ed730fcc559944d581d2
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Eras
|
2
|
+
Error reporting services such as Bugsnag, Honeybadger, and Sentry are great, but they oftentimes leave us scratching our heads while developing locally. You're most likely not sending the errors in development environment, but the notifier caught it anyways, and now it's gone *poof*, missing. Eras takes advantage of Rails 7.0's [`ActiveSupport::ErrorReporter`](https://api.rubyonrails.org/classes/ActiveSupport/ErrorReporter.html)
|
3
|
+
|
4
|
+
### Index
|
5
|
+
![Index](./readme_assets/index.png)
|
6
|
+
|
7
|
+
### Show
|
8
|
+
![Show](./readme_assets/show.png)
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "eras", group: :development
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
```bash
|
19
|
+
$ bundle
|
20
|
+
```
|
21
|
+
|
22
|
+
mount the engine wherever you like (I prefer /eras)
|
23
|
+
```ruby
|
24
|
+
# config/routes.rb
|
25
|
+
mount Eras::Engine => "/eras" if defined?(Eras::Engine) # We only require this in development
|
26
|
+
```
|
27
|
+
|
28
|
+
## Disclaimer
|
29
|
+
|
30
|
+
This gem is in active development, and delivered as-is.
|
31
|
+
|
32
|
+
## Contributing
|
33
|
+
You must run the tailwindcss server while developing, and commit any changes to `app/assets/builds`
|
34
|
+
```
|
35
|
+
rake tailwind_engine_watch
|
36
|
+
```
|
37
|
+
|
38
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
/*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:Inter var,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-radius:0;border-width:1px;font-size:1rem;line-height:1.5rem;padding:.5rem .75rem}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);border-color:#2563eb;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid #0000;outline-offset:2px}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-bottom:0;padding-top:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-origin:border-box;border-color:#6b7280;border-width:1px;color:#2563eb;display:inline-block;flex-shrink:0;height:1rem;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:1rem}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid #0000;outline-offset:2px}[type=checkbox]:checked,[type=radio]:checked{background-color:currentColor;background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:#0000}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=checkbox]:indeterminate,[type=radio]:checked:focus,[type=radio]:checked:hover{background-color:currentColor;border-color:#0000}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:100% 100%}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{background-color:currentColor;border-color:#0000}[type=file]{background:unset;border-color:inherit;border-radius:0;border-width:0;font-size:unset;line-height:inherit;padding:0}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.mb-5{margin-bottom:1.25rem}.mt-4{margin-top:1rem}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.h-20{height:5rem}.w-full{width:100%}.w-3{width:.75rem}.min-w-full{min-width:100%}.max-w-2xl{max-width:42rem}.table-fixed{table-layout:fixed}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(229 231 235/var(--tw-divide-opacity))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity))}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-slate-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.p-6{padding:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-bottom:1rem;padding-top:1rem}.py-2\.5{padding-bottom:.625rem;padding-top:.625rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-extrabold{font-weight:800}.uppercase{text-transform:uppercase}.leading-tight{line-height:1.25}.tracking-wider{letter-spacing:.05em}.tracking-wide{letter-spacing:.025em}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition{transition-duration:.15s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity))}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:bg-blue-700:focus{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity))}.focus\:shadow-lg:focus{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.active\:bg-blue-800:active{--tw-bg-opacity:1;background-color:rgb(30 64 175/var(--tw-bg-opacity))}.active\:shadow-lg:active{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}@media (prefers-color-scheme:dark){.dark\:divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(55 65 81/var(--tw-divide-opacity))}.dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.dark\:hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}}
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_tree ../builds/ .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<div class="max-w-2xl mx-auto">
|
2
|
+
|
3
|
+
<div class="flex flex-col">
|
4
|
+
<div class="overflow-x-auto shadow-md sm:rounded-lg">
|
5
|
+
<div class="inline-block min-w-full align-middle">
|
6
|
+
<div class="overflow-hidden ">
|
7
|
+
<table class="min-w-full divide-y divide-gray-200 table-fixed dark:divide-gray-700">
|
8
|
+
<thead class="bg-gray-100 dark:bg-gray-700">
|
9
|
+
<tr>
|
10
|
+
<th></th>
|
11
|
+
<th scope="col" class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400">
|
12
|
+
Class
|
13
|
+
</th>
|
14
|
+
<th scope="col" class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400">
|
15
|
+
Message
|
16
|
+
</th>
|
17
|
+
<th></th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody data-controller="error-show" class="bg-white divide-y divide-gray-200 dark:bg-gray-800 dark:divide-gray-700">
|
21
|
+
<% @errors.each do |error| %>
|
22
|
+
<tr class="hover:bg-gray-100 dark:hover:bg-gray-700">
|
23
|
+
<%= render partial: "severity_cell", locals: { severity: error["severity"] } %>
|
24
|
+
<td class="py-4 px-6 text-sm font-medium text-gray-900 whitespace-nowrap dark:text-white"><%= error.dig("error", "class") %></td>
|
25
|
+
<td class="py-4 px-6 text-sm font-medium text-gray-500 whitespace-nowrap dark:text-white"><%= error.dig("error", "message") %></td>
|
26
|
+
<td>
|
27
|
+
<div class="flex space-x-2 justify-center">
|
28
|
+
<a href="<%= error_path(error['id'])%>" class="inline-block px-6 py-2.5 bg-blue-600 text-white font-medium text-xs leading-tight uppercase rounded shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out">View</a>
|
29
|
+
</div>
|
30
|
+
</td>
|
31
|
+
</tr>
|
32
|
+
<% end %>
|
33
|
+
</tbody>
|
34
|
+
</table>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="p-6 shadow-lg rounded-lg bg-gray-100 text-gray-700">
|
2
|
+
<h2 class="font-semibold text-3xl mb-5"><%= @error.dig('error', 'class') %></h2>
|
3
|
+
<p><%= @error.dig('error', 'message') %></p>
|
4
|
+
<hr class="my-6 border-gray-300" />
|
5
|
+
<p class="whitespace-pre-line text-xs"><%= @error.dig('error', 'backtrace').gsub('\n', '<br/>').html_safe %></p>
|
6
|
+
<a
|
7
|
+
href="<%= errors_path %>"
|
8
|
+
class="inline-block px-6 py-2.5 mt-4 bg-blue-600 text-white font-medium text-xs leading-tight uppercase rounded shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out"
|
9
|
+
data-mdb-ripple="true"
|
10
|
+
data-mdb-ripple-color="light"
|
11
|
+
>
|
12
|
+
Back
|
13
|
+
</a>
|
14
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Eras</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<%= stylesheet_link_tag "eras", "data-turbo-track": "reload" %>
|
9
|
+
</head>
|
10
|
+
<%= render "shared/navbar" %>
|
11
|
+
|
12
|
+
<body class="bg-slate-500">
|
13
|
+
|
14
|
+
<div class="container mx-auto">
|
15
|
+
<%= yield %>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
</body>
|
19
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
const defaultTheme = require('tailwindcss/defaultTheme')
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
content: [
|
5
|
+
'./public/*.html',
|
6
|
+
'./app/helpers/**/*.rb',
|
7
|
+
'./app/javascript/**/*.js',
|
8
|
+
'./app/views/**/*.{erb,haml,html,slim}'
|
9
|
+
],
|
10
|
+
theme: {
|
11
|
+
extend: {
|
12
|
+
fontFamily: {
|
13
|
+
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
14
|
+
},
|
15
|
+
},
|
16
|
+
},
|
17
|
+
plugins: [
|
18
|
+
require('@tailwindcss/forms'),
|
19
|
+
require('@tailwindcss/aspect-ratio'),
|
20
|
+
require('@tailwindcss/typography'),
|
21
|
+
]
|
22
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Eras
|
2
|
+
module Adapters
|
3
|
+
class FileSystem
|
4
|
+
def initialize(path = nil)
|
5
|
+
@path = Rails.root.join("tmp", "eras", "errors.json")
|
6
|
+
end
|
7
|
+
|
8
|
+
def write_error(data)
|
9
|
+
# Database adapters may have an id, but filesystem adapters don't
|
10
|
+
data['id'] = SecureRandom.uuid
|
11
|
+
|
12
|
+
# TODO: Large numbers of errors will cause this to grow unbounded, could have memory issues.
|
13
|
+
# Should we use file rotation, sqlite (separate adapter), or something else?
|
14
|
+
existing_errors = begin
|
15
|
+
JSON.parse(File.read(@path))
|
16
|
+
rescue Errno::ENOENT, JSON::ParserError
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
|
20
|
+
File.open(@path, "w") do |f|
|
21
|
+
errors = existing_errors
|
22
|
+
errors.unshift(data)
|
23
|
+
f.write(errors.to_json)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_errors
|
28
|
+
File.open(@path, "r") do |f|
|
29
|
+
JSON.parse(f.read)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_error(id)
|
34
|
+
read_errors.find { |e| e['id'] == id }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/eras/engine.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'eras/error_reporter'
|
2
|
+
|
3
|
+
module Eras
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace Eras
|
6
|
+
|
7
|
+
initializer "eras.assets" do |app|
|
8
|
+
app.config.assets.precompile += %w[eras_manifest]
|
9
|
+
end
|
10
|
+
|
11
|
+
initializer "eras.error_subscriber" do |app|
|
12
|
+
app.executor.error_reporter.subscribe(Eras::ErrorReporter.new)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Eras
|
2
|
+
class ErrorReporter
|
3
|
+
def initialize(adapter: Eras::Adapters::FileSystem.new)
|
4
|
+
@adapter = adapter
|
5
|
+
end
|
6
|
+
|
7
|
+
def report(error, handled:, severity:, context:, source: nil)
|
8
|
+
data = {
|
9
|
+
error: {
|
10
|
+
class: error.class.name,
|
11
|
+
message: error.message,
|
12
|
+
backtrace: error.backtrace.join("\n")
|
13
|
+
},
|
14
|
+
handled: handled,
|
15
|
+
severity: severity,
|
16
|
+
context: context.transform_values(&:to_s), # ActionController.to_s causes stack overflow
|
17
|
+
source: source
|
18
|
+
}
|
19
|
+
@adapter.write_error(data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/eras/version.rb
ADDED
data/lib/eras.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# desc "Explaining what the task does"
|
2
|
+
# task :eras do
|
3
|
+
# # Task goes here
|
4
|
+
# end
|
5
|
+
task default: [:test, "standard:fix"]
|
6
|
+
|
7
|
+
task :tailwind_engine_watch do
|
8
|
+
require 'tailwindcss-rails'
|
9
|
+
# NOTE: tailwindcss-rails is an engine
|
10
|
+
system "#{Tailwindcss::Engine.root.join("exe/tailwindcss")} \
|
11
|
+
-i #{Eras::Engine.root.join("app/assets/stylesheets/application.tailwind.css")} \
|
12
|
+
-o #{Eras::Engine.root.join("app/assets/builds/eras.css")} \
|
13
|
+
-c #{Eras::Engine.root.join("config/tailwind.config.js")} \
|
14
|
+
--minify -w"
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eras
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bobby McDonald
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-11-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.0.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.0.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tailwindcss-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: standard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Local error visibility for Rails' ActiveSupport::ErrorReporter
|
56
|
+
email:
|
57
|
+
- bobbymcwho@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- app/assets/builds/eras.css
|
66
|
+
- app/assets/config/eras_manifest.js
|
67
|
+
- app/assets/stylesheets/application.tailwind.css
|
68
|
+
- app/assets/stylesheets/eras/application.css
|
69
|
+
- app/controllers/eras/application_controller.rb
|
70
|
+
- app/controllers/eras/errors_controller.rb
|
71
|
+
- app/helpers/eras/application_helper.rb
|
72
|
+
- app/models/eras/application_record.rb
|
73
|
+
- app/views/eras/errors/_severity_cell.html.erb
|
74
|
+
- app/views/eras/errors/index.html.erb
|
75
|
+
- app/views/eras/errors/show.html.erb
|
76
|
+
- app/views/layouts/eras/application.html.erb
|
77
|
+
- app/views/shared/_navbar.html.erb
|
78
|
+
- config/routes.rb
|
79
|
+
- config/tailwind.config.js
|
80
|
+
- lib/eras.rb
|
81
|
+
- lib/eras/adapters/file_system.rb
|
82
|
+
- lib/eras/engine.rb
|
83
|
+
- lib/eras/error_reporter.rb
|
84
|
+
- lib/eras/version.rb
|
85
|
+
- lib/tasks/eras_tasks.rake
|
86
|
+
homepage: https://github.com/bobbymcwho/eras
|
87
|
+
licenses:
|
88
|
+
- MIT
|
89
|
+
metadata:
|
90
|
+
allowed_push_host: https://rubygems.org
|
91
|
+
homepage_uri: https://github.com/bobbymcwho/eras
|
92
|
+
source_code_uri: https://github.com/bobbymcwho/eras
|
93
|
+
changelog_uri: https://github.com/bobbymcwho/eras
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.2.32
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Local error visibility for Rails' ActiveSupport::ErrorReporter
|
113
|
+
test_files: []
|