rails_error_dashboard 0.1.17 → 0.1.18
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/app/helpers/rails_error_dashboard/application_helper.rb +63 -0
- data/app/views/layouts/rails_error_dashboard.html.erb +183 -0
- data/app/views/rails_error_dashboard/errors/_error_row.html.erb +2 -2
- data/app/views/rails_error_dashboard/errors/_timeline.html.erb +1 -1
- data/app/views/rails_error_dashboard/errors/analytics.html.erb +2 -2
- data/app/views/rails_error_dashboard/errors/index.html.erb +1 -1
- data/app/views/rails_error_dashboard/errors/overview.html.erb +2 -2
- data/app/views/rails_error_dashboard/errors/show.html.erb +12 -12
- data/lib/rails_error_dashboard/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2cdd815518aac095839eaf937dde33835b52b260cc6494d7e0a904de0c59b614
|
|
4
|
+
data.tar.gz: 7cd803c5e3ac4e724d3514088d46d8c76316336ce89e233a116a8ba95dad00bc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5cea12724e61c164845596926c4d6fdebacd4fada853b512c78e8c345b87f18f5347eb53c70b17f911d84963a5c2913415688b23afaebf50a47ece25ec695b5
|
|
7
|
+
data.tar.gz: a4110c8cf08406f79683e3a923967cd5a5fc3f383893e3a616ebd6a360f079e982e3f2be0bfea0db1c0d406e99d5cd3fada6bcba15294a0355739ccb1854a2c2
|
|
@@ -130,5 +130,68 @@ module RailsErrorDashboard
|
|
|
130
130
|
content_tag(:code, display_sha, class: "font-monospace")
|
|
131
131
|
end
|
|
132
132
|
end
|
|
133
|
+
|
|
134
|
+
# Renders a timestamp that will be automatically converted to user's local timezone
|
|
135
|
+
# Server sends UTC timestamp, JavaScript converts to local timezone on page load
|
|
136
|
+
# @param time [Time, DateTime, nil] The timestamp to display
|
|
137
|
+
# @param format [Symbol] Format preset (:full, :short, :date_only, :time_only, :datetime)
|
|
138
|
+
# @param fallback [String] Text to show if time is nil
|
|
139
|
+
# @return [String] HTML safe span with data attributes for JS conversion
|
|
140
|
+
def local_time(time, format: :full, fallback: "N/A")
|
|
141
|
+
return fallback if time.nil?
|
|
142
|
+
|
|
143
|
+
# Convert to UTC if not already
|
|
144
|
+
utc_time = time.respond_to?(:utc) ? time.utc : time
|
|
145
|
+
|
|
146
|
+
# ISO 8601 format for JavaScript parsing
|
|
147
|
+
iso_time = utc_time.iso8601
|
|
148
|
+
|
|
149
|
+
# Format presets for data-format attribute
|
|
150
|
+
format_string = case format
|
|
151
|
+
when :full
|
|
152
|
+
"%B %d, %Y %I:%M:%S %p" # December 31, 2024 11:59:59 PM
|
|
153
|
+
when :short
|
|
154
|
+
"%m/%d %I:%M%p" # 12/31 11:59PM
|
|
155
|
+
when :date_only
|
|
156
|
+
"%B %d, %Y" # December 31, 2024
|
|
157
|
+
when :time_only
|
|
158
|
+
"%I:%M:%S %p" # 11:59:59 PM
|
|
159
|
+
when :datetime
|
|
160
|
+
"%b %d, %Y %H:%M" # Dec 31, 2024 23:59
|
|
161
|
+
else
|
|
162
|
+
format.to_s
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
content_tag(
|
|
166
|
+
:span,
|
|
167
|
+
utc_time.strftime(format_string + " UTC"), # Fallback for non-JS browsers
|
|
168
|
+
class: "local-time",
|
|
169
|
+
data: {
|
|
170
|
+
utc: iso_time,
|
|
171
|
+
format: format_string
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Renders a relative time ("3 hours ago") that updates automatically
|
|
177
|
+
# @param time [Time, DateTime, nil] The timestamp to display
|
|
178
|
+
# @param fallback [String] Text to show if time is nil
|
|
179
|
+
# @return [String] HTML safe span with data attributes for JS conversion
|
|
180
|
+
def local_time_ago(time, fallback: "N/A")
|
|
181
|
+
return fallback if time.nil?
|
|
182
|
+
|
|
183
|
+
# Convert to UTC if not already
|
|
184
|
+
utc_time = time.respond_to?(:utc) ? time.utc : time
|
|
185
|
+
iso_time = utc_time.iso8601
|
|
186
|
+
|
|
187
|
+
content_tag(
|
|
188
|
+
:span,
|
|
189
|
+
time_ago_in_words(time) + " ago", # Fallback for non-JS browsers
|
|
190
|
+
class: "local-time-ago",
|
|
191
|
+
data: {
|
|
192
|
+
utc: iso_time
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
end
|
|
133
196
|
end
|
|
134
197
|
end
|
|
@@ -1188,6 +1188,189 @@
|
|
|
1188
1188
|
showToast('<%= j flash[:error] %>', 'danger');
|
|
1189
1189
|
<% end %>
|
|
1190
1190
|
<% end %>
|
|
1191
|
+
|
|
1192
|
+
// Local Timezone Conversion
|
|
1193
|
+
// Converts UTC timestamps to user's local timezone on page load
|
|
1194
|
+
function convertToLocalTime() {
|
|
1195
|
+
// Convert all .local-time elements (formatted timestamps)
|
|
1196
|
+
document.querySelectorAll('.local-time').forEach(function(element) {
|
|
1197
|
+
const utcString = element.dataset.utc;
|
|
1198
|
+
const formatString = element.dataset.format;
|
|
1199
|
+
|
|
1200
|
+
if (!utcString) return;
|
|
1201
|
+
|
|
1202
|
+
try {
|
|
1203
|
+
const date = new Date(utcString);
|
|
1204
|
+
if (isNaN(date.getTime())) return; // Invalid date
|
|
1205
|
+
|
|
1206
|
+
// Parse the format string and convert to local time
|
|
1207
|
+
const formatted = formatDateTime(date, formatString);
|
|
1208
|
+
|
|
1209
|
+
// Get timezone abbreviation
|
|
1210
|
+
const timezone = getTimezoneAbbreviation(date);
|
|
1211
|
+
|
|
1212
|
+
// Update element text
|
|
1213
|
+
element.textContent = formatted + ' ' + timezone;
|
|
1214
|
+
element.title = 'Your local time (click to see UTC)';
|
|
1215
|
+
|
|
1216
|
+
// Add click handler to toggle between local and UTC
|
|
1217
|
+
element.style.cursor = 'pointer';
|
|
1218
|
+
element.dataset.originalUtc = utcString;
|
|
1219
|
+
element.dataset.localFormatted = formatted + ' ' + timezone;
|
|
1220
|
+
element.dataset.showingLocal = 'true';
|
|
1221
|
+
|
|
1222
|
+
element.addEventListener('click', function() {
|
|
1223
|
+
if (this.dataset.showingLocal === 'true') {
|
|
1224
|
+
// Show UTC
|
|
1225
|
+
const utcDate = new Date(this.dataset.originalUtc);
|
|
1226
|
+
const utcFormatted = formatDateTime(utcDate, formatString);
|
|
1227
|
+
this.textContent = utcFormatted + ' UTC';
|
|
1228
|
+
this.title = 'UTC time (click to see local time)';
|
|
1229
|
+
this.dataset.showingLocal = 'false';
|
|
1230
|
+
} else {
|
|
1231
|
+
// Show local
|
|
1232
|
+
this.textContent = this.dataset.localFormatted;
|
|
1233
|
+
this.title = 'Your local time (click to see UTC)';
|
|
1234
|
+
this.dataset.showingLocal = 'true';
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
} catch (e) {
|
|
1238
|
+
console.error('Error converting timestamp:', e);
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
// Convert all .local-time-ago elements (relative time)
|
|
1243
|
+
document.querySelectorAll('.local-time-ago').forEach(function(element) {
|
|
1244
|
+
const utcString = element.dataset.utc;
|
|
1245
|
+
if (!utcString) return;
|
|
1246
|
+
|
|
1247
|
+
try {
|
|
1248
|
+
const date = new Date(utcString);
|
|
1249
|
+
if (isNaN(date.getTime())) return; // Invalid date
|
|
1250
|
+
|
|
1251
|
+
// Calculate relative time
|
|
1252
|
+
const now = new Date();
|
|
1253
|
+
const diffMs = now - date;
|
|
1254
|
+
const formatted = formatRelativeTime(diffMs);
|
|
1255
|
+
|
|
1256
|
+
// Update element text
|
|
1257
|
+
element.textContent = formatted;
|
|
1258
|
+
element.title = 'Click to see exact time';
|
|
1259
|
+
|
|
1260
|
+
// Add click handler to toggle between relative and absolute
|
|
1261
|
+
element.style.cursor = 'pointer';
|
|
1262
|
+
element.dataset.originalUtc = utcString;
|
|
1263
|
+
element.dataset.showingRelative = 'true';
|
|
1264
|
+
|
|
1265
|
+
element.addEventListener('click', function() {
|
|
1266
|
+
if (this.dataset.showingRelative === 'true') {
|
|
1267
|
+
// Show absolute time
|
|
1268
|
+
const absoluteDate = new Date(this.dataset.originalUtc);
|
|
1269
|
+
const absoluteFormatted = formatDateTime(absoluteDate, '%B %d, %Y %I:%M:%S %p');
|
|
1270
|
+
const timezone = getTimezoneAbbreviation(absoluteDate);
|
|
1271
|
+
this.textContent = absoluteFormatted + ' ' + timezone;
|
|
1272
|
+
this.title = 'Click to see relative time';
|
|
1273
|
+
this.dataset.showingRelative = 'false';
|
|
1274
|
+
} else {
|
|
1275
|
+
// Show relative time
|
|
1276
|
+
const now = new Date();
|
|
1277
|
+
const date = new Date(this.dataset.originalUtc);
|
|
1278
|
+
const diffMs = now - date;
|
|
1279
|
+
this.textContent = formatRelativeTime(diffMs);
|
|
1280
|
+
this.title = 'Click to see exact time';
|
|
1281
|
+
this.dataset.showingRelative = 'true';
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
} catch (e) {
|
|
1285
|
+
console.error('Error converting relative time:', e);
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
// Format date according to strftime-like format string
|
|
1291
|
+
function formatDateTime(date, formatString) {
|
|
1292
|
+
const months = ['January', 'February', 'March', 'April', 'May', 'June',
|
|
1293
|
+
'July', 'August', 'September', 'October', 'November', 'December'];
|
|
1294
|
+
const monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
1295
|
+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
1296
|
+
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
1297
|
+
const daysShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
1298
|
+
|
|
1299
|
+
const year = date.getFullYear();
|
|
1300
|
+
const month = date.getMonth();
|
|
1301
|
+
const day = date.getDate();
|
|
1302
|
+
const hours = date.getHours();
|
|
1303
|
+
const minutes = date.getMinutes();
|
|
1304
|
+
const seconds = date.getSeconds();
|
|
1305
|
+
const dayOfWeek = date.getDay();
|
|
1306
|
+
|
|
1307
|
+
// 12-hour format
|
|
1308
|
+
const hours12 = hours % 12 || 12;
|
|
1309
|
+
const ampm = hours >= 12 ? 'PM' : 'AM';
|
|
1310
|
+
|
|
1311
|
+
// Padding helper
|
|
1312
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
1313
|
+
|
|
1314
|
+
// Replace format specifiers
|
|
1315
|
+
let result = formatString
|
|
1316
|
+
.replace('%Y', year)
|
|
1317
|
+
.replace('%y', year.toString().substr(2))
|
|
1318
|
+
.replace('%B', months[month])
|
|
1319
|
+
.replace('%b', monthsShort[month])
|
|
1320
|
+
.replace('%m', pad(month + 1))
|
|
1321
|
+
.replace('%d', pad(day))
|
|
1322
|
+
.replace('%e', day)
|
|
1323
|
+
.replace('%A', days[dayOfWeek])
|
|
1324
|
+
.replace('%a', daysShort[dayOfWeek])
|
|
1325
|
+
.replace('%H', pad(hours))
|
|
1326
|
+
.replace('%I', pad(hours12))
|
|
1327
|
+
.replace('%M', pad(minutes))
|
|
1328
|
+
.replace('%S', pad(seconds))
|
|
1329
|
+
.replace('%p', ampm)
|
|
1330
|
+
.replace('%P', ampm.toLowerCase());
|
|
1331
|
+
|
|
1332
|
+
return result;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
// Get timezone abbreviation (e.g., "PST", "EST", "UTC+2")
|
|
1336
|
+
function getTimezoneAbbreviation(date) {
|
|
1337
|
+
const timeZoneString = date.toLocaleTimeString('en-US', { timeZoneName: 'short' });
|
|
1338
|
+
const parts = timeZoneString.split(' ');
|
|
1339
|
+
return parts[parts.length - 1]; // Last part is timezone abbreviation
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
// Format relative time ("3 hours ago", "2 days ago")
|
|
1343
|
+
function formatRelativeTime(diffMs) {
|
|
1344
|
+
const seconds = Math.floor(diffMs / 1000);
|
|
1345
|
+
const minutes = Math.floor(seconds / 60);
|
|
1346
|
+
const hours = Math.floor(minutes / 60);
|
|
1347
|
+
const days = Math.floor(hours / 24);
|
|
1348
|
+
const months = Math.floor(days / 30);
|
|
1349
|
+
const years = Math.floor(days / 365);
|
|
1350
|
+
|
|
1351
|
+
if (seconds < 60) {
|
|
1352
|
+
return seconds <= 1 ? '1 second ago' : seconds + ' seconds ago';
|
|
1353
|
+
} else if (minutes < 60) {
|
|
1354
|
+
return minutes === 1 ? '1 minute ago' : minutes + ' minutes ago';
|
|
1355
|
+
} else if (hours < 24) {
|
|
1356
|
+
return hours === 1 ? '1 hour ago' : hours + ' hours ago';
|
|
1357
|
+
} else if (days < 30) {
|
|
1358
|
+
return days === 1 ? '1 day ago' : days + ' days ago';
|
|
1359
|
+
} else if (months < 12) {
|
|
1360
|
+
return months === 1 ? '1 month ago' : months + ' months ago';
|
|
1361
|
+
} else {
|
|
1362
|
+
return years === 1 ? '1 year ago' : years + ' years ago';
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// Run conversion on page load
|
|
1367
|
+
convertToLocalTime();
|
|
1368
|
+
|
|
1369
|
+
// Also run after Turbo navigation (if using Turbo/Hotwire)
|
|
1370
|
+
if (typeof Turbo !== 'undefined') {
|
|
1371
|
+
document.addEventListener('turbo:load', convertToLocalTime);
|
|
1372
|
+
document.addEventListener('turbo:frame-load', convertToLocalTime);
|
|
1373
|
+
}
|
|
1191
1374
|
});
|
|
1192
1375
|
</script>
|
|
1193
1376
|
</body>
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
</td>
|
|
37
37
|
<td onclick="window.location='<%= error_path(error) %>';">
|
|
38
38
|
<small>
|
|
39
|
-
<strong>First:</strong> <%= error.first_seen_at
|
|
40
|
-
<strong>Last:</strong> <%= error.last_seen_at
|
|
39
|
+
<strong>First:</strong> <%= local_time(error.first_seen_at, format: :short) %><br>
|
|
40
|
+
<strong>Last:</strong> <%= local_time(error.last_seen_at, format: :short) %>
|
|
41
41
|
</small>
|
|
42
42
|
</td>
|
|
43
43
|
<% if local_assigns[:show_platform] %>
|
|
@@ -386,8 +386,8 @@
|
|
|
386
386
|
<td><code class="small"><%= error[:error_type] %></code></td>
|
|
387
387
|
<td><span class="badge bg-danger"><%= error[:total_occurrences] %></span></td>
|
|
388
388
|
<td><%= error[:duration_days] %> days</td>
|
|
389
|
-
<td><small class="text-muted"><%= error[:first_seen]
|
|
390
|
-
<td><small class="text-muted"><%= error[:last_seen]
|
|
389
|
+
<td><small class="text-muted"><%= local_time(error[:first_seen], format: :date_only) %></small></td>
|
|
390
|
+
<td><small class="text-muted"><%= local_time(error[:last_seen], format: :datetime) %></small></td>
|
|
391
391
|
<td>
|
|
392
392
|
<% if error[:still_active] %>
|
|
393
393
|
<span class="badge bg-warning">Active</span>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<h2 class="mb-0"><i class="bi bi-bug-fill text-primary"></i> Error Overview</h2>
|
|
11
11
|
<div class="text-muted">
|
|
12
12
|
<small>
|
|
13
|
-
Last updated: <%= Time.current
|
|
13
|
+
Last updated: <%= local_time(Time.current, format: :full) %>
|
|
14
14
|
<span class="badge bg-success ms-2" id="live-indicator">
|
|
15
15
|
<i class="bi bi-broadcast"></i> Live
|
|
16
16
|
</span>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</h1>
|
|
9
9
|
<div class="text-muted">
|
|
10
10
|
<small>
|
|
11
|
-
Last updated: <%= Time.current
|
|
11
|
+
Last updated: <%= local_time(Time.current, format: :full) %>
|
|
12
12
|
</small>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
<p class="mb-1 small"><%= error.message&.truncate(100) %></p>
|
|
200
200
|
<small class="text-muted">
|
|
201
201
|
<i class="bi bi-clock me-1"></i>
|
|
202
|
-
<%=
|
|
202
|
+
<%= local_time_ago(error.occurred_at) %>
|
|
203
203
|
•
|
|
204
204
|
<i class="bi bi-arrow-repeat me-1"></i>
|
|
205
205
|
<%= error.occurrence_count %> occurrence<%= error.occurrence_count != 1 ? 's' : '' %>
|
|
@@ -436,8 +436,8 @@
|
|
|
436
436
|
<% end %>
|
|
437
437
|
</div>
|
|
438
438
|
<small class="text-muted">
|
|
439
|
-
<%= comment.
|
|
440
|
-
<span class="ms-1 text-muted">(<%=
|
|
439
|
+
<%= local_time(comment.created_at, format: :datetime) %>
|
|
440
|
+
<span class="ms-1 text-muted">(<%= local_time_ago(comment.created_at) %>)</span>
|
|
441
441
|
</small>
|
|
442
442
|
</div>
|
|
443
443
|
<div class="text-break">
|
|
@@ -682,20 +682,20 @@
|
|
|
682
682
|
<small class="text-muted d-block mb-1">First Seen</small>
|
|
683
683
|
<% if @related_errors.any? %>
|
|
684
684
|
<%= link_to "#timeline", class: "text-decoration-none", data: { bs_toggle: "tooltip" }, title: "Jump to timeline" do %>
|
|
685
|
-
<strong><%= @error.first_seen_at
|
|
686
|
-
<small><%= @error.first_seen_at
|
|
685
|
+
<strong><%= local_time(@error.first_seen_at, format: :date_only) %></strong><br>
|
|
686
|
+
<small><%= local_time(@error.first_seen_at, format: :time_only) %></small>
|
|
687
687
|
<i class="bi bi-arrow-down-circle ms-1"></i>
|
|
688
688
|
<% end %>
|
|
689
689
|
<% else %>
|
|
690
|
-
<strong><%= @error.first_seen_at
|
|
691
|
-
<small><%= @error.first_seen_at
|
|
690
|
+
<strong><%= local_time(@error.first_seen_at, format: :date_only) %></strong><br>
|
|
691
|
+
<small><%= local_time(@error.first_seen_at, format: :time_only) %></small>
|
|
692
692
|
<% end %>
|
|
693
693
|
</div>
|
|
694
694
|
|
|
695
695
|
<div class="mb-3">
|
|
696
696
|
<small class="text-muted d-block mb-1">Last Seen</small>
|
|
697
|
-
<strong><%= @error.last_seen_at
|
|
698
|
-
<small><%= @error.last_seen_at
|
|
697
|
+
<strong><%= local_time(@error.last_seen_at, format: :date_only) %></strong><br>
|
|
698
|
+
<small><%= local_time(@error.last_seen_at, format: :time_only) %></small>
|
|
699
699
|
</div>
|
|
700
700
|
|
|
701
701
|
<div class="mb-3">
|
|
@@ -751,7 +751,7 @@
|
|
|
751
751
|
<% if @error.resolved_at.present? %>
|
|
752
752
|
<br>
|
|
753
753
|
<small class="text-muted mt-1 d-block">
|
|
754
|
-
<%= @error.resolved_at
|
|
754
|
+
<%= local_time(@error.resolved_at, format: :full) %>
|
|
755
755
|
</small>
|
|
756
756
|
<% end %>
|
|
757
757
|
<% else %>
|
|
@@ -773,7 +773,7 @@
|
|
|
773
773
|
<% if @error.assigned_at.present? %>
|
|
774
774
|
<br>
|
|
775
775
|
<small class="text-muted">
|
|
776
|
-
<%=
|
|
776
|
+
<%= local_time_ago(@error.assigned_at) %>
|
|
777
777
|
</small>
|
|
778
778
|
<% end %>
|
|
779
779
|
</div>
|
|
@@ -809,7 +809,7 @@
|
|
|
809
809
|
<div class="alert alert-warning py-2 mb-2">
|
|
810
810
|
<i class="bi bi-alarm"></i>
|
|
811
811
|
<strong>Snoozed</strong><br>
|
|
812
|
-
<small>Until <%= @error.snoozed_until
|
|
812
|
+
<small>Until <%= local_time(@error.snoozed_until, format: :datetime) %></small>
|
|
813
813
|
</div>
|
|
814
814
|
<%= button_to unsnooze_error_path(@error), method: :patch, class: "btn btn-sm btn-outline-warning" do %>
|
|
815
815
|
<i class="bi bi-alarm-fill"></i> Unsnooze
|
|
@@ -971,7 +971,7 @@
|
|
|
971
971
|
<small class="text-muted">
|
|
972
972
|
Sample: <%= baseline.respond_to?(:sample_size) ? baseline.sample_size : 'N/A' %> periods
|
|
973
973
|
<span class="text-muted">|</span>
|
|
974
|
-
Updated: <%= baseline.respond_to?(:updated_at) ? baseline.updated_at
|
|
974
|
+
Updated: <%= baseline.respond_to?(:updated_at) ? local_time(baseline.updated_at, format: :short) : 'N/A' %>
|
|
975
975
|
</small>
|
|
976
976
|
</div>
|
|
977
977
|
</div>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_error_dashboard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.18
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anjan Jagirdar
|
|
@@ -379,7 +379,7 @@ metadata:
|
|
|
379
379
|
source_code_uri: https://github.com/AnjanJ/rails_error_dashboard
|
|
380
380
|
changelog_uri: https://github.com/AnjanJ/rails_error_dashboard/blob/main/CHANGELOG.md
|
|
381
381
|
post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
|
|
382
|
-
\ Rails Error Dashboard v0.1.
|
|
382
|
+
\ Rails Error Dashboard v0.1.18\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
|
|
383
383
|
First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
|
|
384
384
|
db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
|
|
385
385
|
=> '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n
|