Check / check (pull_request) Successful in 5m7s
Table cells never wrap, so a long repository URL made the table wider than its card, which hides what does not fit and so cut off the Actions column and the Deploy buttons. The repository URL now wraps within its column, and the card scrolls sideways when the table still does not fit. A handler test checks both. Every class used was already in the committed static/css/tailwind.css. Model: opus-5-5 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
103 lines
4.5 KiB
HTML
103 lines
4.5 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "title"}}Dashboard - µPaaS{{end}}
|
|
|
|
{{define "content"}}
|
|
{{template "nav" .}}
|
|
|
|
<main class="max-w-6xl mx-auto px-4 py-8" x-data="dashboard()">
|
|
{{template "alert-success" .}}
|
|
{{template "alert-error" .}}
|
|
|
|
<div class="section-header">
|
|
<h1 class="text-2xl font-medium text-gray-900">Applications</h1>
|
|
<a href="/apps/new" class="btn-primary">
|
|
<svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
|
</svg>
|
|
New App
|
|
</a>
|
|
</div>
|
|
|
|
{{if .AppStats}}
|
|
<div class="card overflow-x-auto">
|
|
<table class="table">
|
|
<thead class="table-header">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Repository</th>
|
|
<th>Branch</th>
|
|
<th>Status</th>
|
|
<th>Last Deploy</th>
|
|
<th>Deploys</th>
|
|
<th class="text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="table-body">
|
|
{{range .AppStats}}
|
|
<tr class="table-row-hover">
|
|
<td>
|
|
<a href="/apps/{{.App.ID}}" class="text-primary-600 hover:text-primary-800 font-medium">
|
|
{{.App.Name}}
|
|
</a>
|
|
</td>
|
|
<td class="text-gray-500 font-mono text-xs whitespace-normal break-all">{{.App.RepoURL}}</td>
|
|
<td class="text-gray-500">{{.App.Branch}}</td>
|
|
<td>
|
|
{{if eq .App.Status "running"}}
|
|
<span class="badge-success">Running</span>
|
|
{{else if eq .App.Status "building"}}
|
|
<span class="badge-warning">Building</span>
|
|
{{else if eq .App.Status "error"}}
|
|
<span class="badge-error">Error</span>
|
|
{{else if eq .App.Status "stopped"}}
|
|
<span class="badge-neutral">Stopped</span>
|
|
{{else}}
|
|
<span class="badge-neutral">{{.App.Status}}</span>
|
|
{{end}}
|
|
</td>
|
|
<td class="text-gray-500 text-sm">
|
|
{{if .LastDeployTime}}
|
|
<span x-data="relativeTime('{{.LastDeployISO}}')" x-text="display" class="cursor-default" title="{{.LastDeployLabel}}"></span>
|
|
{{else}}
|
|
<span class="text-gray-400">-</span>
|
|
{{end}}
|
|
</td>
|
|
<td class="text-gray-500 text-sm">{{.DeployCount}}</td>
|
|
<td class="text-right">
|
|
<div class="flex justify-end gap-2">
|
|
<a href="/apps/{{.App.ID}}" class="btn-text text-sm py-1 px-2">View</a>
|
|
<a href="/apps/{{.App.ID}}/edit" class="btn-secondary text-sm py-1 px-2">Edit</a>
|
|
<form method="POST" action="/apps/{{.App.ID}}/deploy" class="inline">
|
|
{{ $.CSRFField }}
|
|
<button type="submit" class="btn-success text-sm py-1 px-2">Deploy</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{else}}
|
|
<div class="card">
|
|
<div class="empty-state">
|
|
<svg class="empty-state-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/>
|
|
</svg>
|
|
<h3 class="empty-state-title">No applications yet</h3>
|
|
<p class="empty-state-description">Get started by creating your first application.</p>
|
|
<div class="mt-6">
|
|
<a href="/apps/new" class="btn-primary">
|
|
<svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
|
</svg>
|
|
Create App
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</main>
|
|
{{end}}
|