Files
MosisService/portal/internal/web/templates/pages/app_crashes.html

149 lines
6.4 KiB
HTML

{{define "content"}}
<div class="mb-6">
<a href="/apps/{{.App.ID}}/analytics" class="inline-flex items-center text-sm text-gray-500 hover:text-gray-700">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
Back to Analytics
</a>
</div>
<!-- Header -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<div class="w-12 h-12 bg-red-100 rounded-xl flex items-center justify-center">
<svg class="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
</svg>
</div>
<div>
<h1 class="text-2xl font-bold text-gray-900">Crash Reports</h1>
<p class="text-gray-500">{{.App.Name}}</p>
</div>
</div>
<!-- Status Filter -->
<div class="flex items-center space-x-2">
<a href="/apps/{{.App.ID}}/crashes?status=open"
class="px-4 py-2 text-sm font-medium rounded-lg {{if eq .Status "open"}}bg-red-100 text-red-700{{else}}text-gray-500 hover:bg-gray-100{{end}}">
Open
</a>
<a href="/apps/{{.App.ID}}/crashes?status=resolved"
class="px-4 py-2 text-sm font-medium rounded-lg {{if eq .Status "resolved"}}bg-green-100 text-green-700{{else}}text-gray-500 hover:bg-gray-100{{end}}">
Resolved
</a>
<a href="/apps/{{.App.ID}}/crashes?status=ignored"
class="px-4 py-2 text-sm font-medium rounded-lg {{if eq .Status "ignored"}}bg-gray-200 text-gray-700{{else}}text-gray-500 hover:bg-gray-100{{end}}">
Ignored
</a>
</div>
</div>
</div>
<!-- Crashes List -->
{{if .Crashes}}
<div class="space-y-4">
{{range .Crashes}}
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 hover:border-gray-300 transition-colors">
<div class="flex items-start justify-between">
<div class="flex-1">
<div class="flex items-center space-x-2 mb-2">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
{{.CrashType}}
</span>
<span class="text-xs text-gray-500">{{.OccurrenceCount}} occurrences</span>
</div>
<h3 class="text-lg font-medium text-gray-900 mb-2">{{.Message}}</h3>
{{if .SampleStackTrace}}
<pre class="mt-3 p-3 bg-gray-50 rounded-lg text-xs text-gray-600 overflow-x-auto max-h-32">{{.SampleStackTrace}}</pre>
{{end}}
<div class="mt-3 flex items-center space-x-4 text-xs text-gray-500">
<span>First seen: {{.FirstSeen}}</span>
<span>Last seen: {{.LastSeen}}</span>
{{if .AffectedVersions}}
<span>Versions: {{range $i, $v := .AffectedVersions}}{{if $i}}, {{end}}{{$v}}{{end}}</span>
{{end}}
</div>
</div>
<div class="ml-6 flex flex-col items-end space-y-2">
<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium {{if eq .Status "open"}}bg-red-100 text-red-800{{else if eq .Status "resolved"}}bg-green-100 text-green-800{{else}}bg-gray-100 text-gray-800{{end}}">
{{.Status}}
</span>
<div class="flex space-x-2">
{{if eq .Status "open"}}
<button hx-post="/apps/{{$.App.ID}}/crashes/{{.ID}}/resolve"
hx-swap="outerHTML"
hx-target="closest div.bg-white"
class="text-xs text-green-600 hover:text-green-700 font-medium">
Mark Resolved
</button>
<button hx-post="/apps/{{$.App.ID}}/crashes/{{.ID}}/ignore"
hx-swap="outerHTML"
hx-target="closest div.bg-white"
class="text-xs text-gray-500 hover:text-gray-700 font-medium">
Ignore
</button>
{{else if eq .Status "resolved"}}
<button hx-post="/apps/{{$.App.ID}}/crashes/{{.ID}}/reopen"
hx-swap="outerHTML"
hx-target="closest div.bg-white"
class="text-xs text-red-600 hover:text-red-700 font-medium">
Reopen
</button>
{{else}}
<button hx-post="/apps/{{$.App.ID}}/crashes/{{.ID}}/reopen"
hx-swap="outerHTML"
hx-target="closest div.bg-white"
class="text-xs text-red-600 hover:text-red-700 font-medium">
Reopen
</button>
{{end}}
</div>
</div>
</div>
</div>
{{end}}
</div>
<!-- Pagination -->
{{if gt .Pagination.TotalPages 1}}
<div class="mt-6 flex items-center justify-between">
<div class="text-sm text-gray-500">
Showing {{add (mul (sub .Pagination.Page 1) .Pagination.Limit) 1}} to {{min (mul .Pagination.Page .Pagination.Limit) .Pagination.Total}} of {{.Pagination.Total}} crashes
</div>
<nav class="flex space-x-2">
{{if gt .Pagination.Page 1}}
<a href="/apps/{{.App.ID}}/crashes?status={{.Status}}&page={{sub .Pagination.Page 1}}"
class="px-3 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
Previous
</a>
{{end}}
{{if lt .Pagination.Page .Pagination.TotalPages}}
<a href="/apps/{{.App.ID}}/crashes?status={{.Status}}&page={{add .Pagination.Page 1}}"
class="px-3 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
Next
</a>
{{end}}
</nav>
</div>
{{end}}
{{else}}
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-12 text-center">
<svg class="mx-auto h-12 w-12 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<h3 class="mt-4 text-lg font-medium text-gray-900">No crashes</h3>
<p class="mt-2 text-sm text-gray-500">
{{if eq .Status "open"}}
No open crash reports. Your app is running smoothly!
{{else if eq .Status "resolved"}}
No resolved crashes to show.
{{else}}
No ignored crashes.
{{end}}
</p>
</div>
{{end}}
{{end}}