7 changed files with 1391 additions and 135 deletions
-
162weed/admin/dash/admin_server.go
-
2weed/admin/handlers/admin_handlers.go
-
39weed/admin/handlers/cluster_handlers.go
-
43weed/admin/view/app/cluster_volumes.templ
-
165weed/admin/view/app/cluster_volumes_templ.go
-
425weed/admin/view/app/volume_details.templ
-
690weed/admin/view/app/volume_details_templ.go
@ -0,0 +1,425 @@ |
|||||
|
package app |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"time" |
||||
|
"github.com/seaweedfs/seaweedfs/weed/admin/dash" |
||||
|
) |
||||
|
|
||||
|
templ VolumeDetails(data dash.VolumeDetailsData) { |
||||
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"> |
||||
|
<div> |
||||
|
<h1 class="h2"> |
||||
|
<i class="fas fa-database me-2"></i>Volume Details |
||||
|
</h1> |
||||
|
<nav aria-label="breadcrumb"> |
||||
|
<ol class="breadcrumb"> |
||||
|
<li class="breadcrumb-item"><a href="/admin" class="text-decoration-none">Dashboard</a></li> |
||||
|
<li class="breadcrumb-item"><a href="/cluster/volumes" class="text-decoration-none">Volumes</a></li> |
||||
|
<li class="breadcrumb-item active" aria-current="page">Volume {fmt.Sprintf("%d", data.Volume.Id)}</li> |
||||
|
</ol> |
||||
|
</nav> |
||||
|
</div> |
||||
|
<div class="btn-toolbar mb-2 mb-md-0"> |
||||
|
<div class="btn-group me-2"> |
||||
|
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="history.back()"> |
||||
|
<i class="fas fa-arrow-left me-1"></i>Back |
||||
|
</button> |
||||
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="window.location.reload()"> |
||||
|
<i class="fas fa-refresh me-1"></i>Refresh |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<!-- Volume Information Card --> |
||||
|
<div class="col-lg-8"> |
||||
|
<div class="card shadow mb-4"> |
||||
|
<div class="card-header py-3"> |
||||
|
<h6 class="m-0 font-weight-bold text-primary"> |
||||
|
<i class="fas fa-info-circle me-2"></i>Volume Information |
||||
|
</h6> |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Volume ID:</strong></label> |
||||
|
<div><code class="fs-5">{fmt.Sprintf("%d", data.Volume.Id)}</code></div> |
||||
|
</div> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Server:</strong></label> |
||||
|
<div> |
||||
|
<a href={templ.SafeURL(fmt.Sprintf("http://%s", data.Volume.Server))} target="_blank" class="text-decoration-none"> |
||||
|
{data.Volume.Server} |
||||
|
<i class="fas fa-external-link-alt ms-1 text-muted"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Data Center:</strong></label> |
||||
|
<div><span class="badge bg-light text-dark">{data.Volume.DataCenter}</span></div> |
||||
|
</div> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Rack:</strong></label> |
||||
|
<div><span class="badge bg-light text-dark">{data.Volume.Rack}</span></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Collection:</strong></label> |
||||
|
<div> |
||||
|
if data.Volume.Collection == "" { |
||||
|
<a href={templ.SafeURL("/cluster/volumes?collection=default")} class="text-decoration-none"> |
||||
|
<span class="badge bg-secondary">default</span> |
||||
|
</a> |
||||
|
} else { |
||||
|
<a href={templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", data.Volume.Collection))} class="text-decoration-none"> |
||||
|
<span class="badge bg-secondary">{data.Volume.Collection}</span> |
||||
|
</a> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Replication:</strong></label> |
||||
|
<div><span class="badge bg-info">{fmt.Sprintf("%03d", data.Volume.ReplicaPlacement)}</span></div> |
||||
|
</div> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Disk Type:</strong></label> |
||||
|
<div> |
||||
|
<span class="badge bg-primary"> |
||||
|
if data.Volume.DiskType == "" { |
||||
|
hdd |
||||
|
} else { |
||||
|
{data.Volume.DiskType} |
||||
|
} |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="mb-3"> |
||||
|
<label class="form-label"><strong>Version:</strong></label> |
||||
|
<div><span class="badge bg-dark">{fmt.Sprintf("v%d", data.Volume.Version)}</span></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Statistics Card --> |
||||
|
<div class="col-lg-4"> |
||||
|
<!-- Volume Statistics & Health Card --> |
||||
|
<div class="card shadow mb-4"> |
||||
|
<div class="card-header py-3"> |
||||
|
<h6 class="m-0 font-weight-bold text-primary"> |
||||
|
<i class="fas fa-chart-pie me-2"></i>Volume Statistics & Health |
||||
|
</h6> |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<!-- Storage Metrics --> |
||||
|
<div class="row mb-3"> |
||||
|
<div class="col-6"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h4 mb-0 font-weight-bold text-success"> |
||||
|
{formatBytes(int64(data.Volume.Size - data.Volume.DeletedByteCount))} |
||||
|
</div> |
||||
|
<small class="text-muted">Active Bytes</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-6"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h4 mb-0 font-weight-bold text-danger"> |
||||
|
{formatBytes(int64(data.Volume.DeletedByteCount))} |
||||
|
</div> |
||||
|
<small class="text-muted">Deleted Bytes</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- File Metrics --> |
||||
|
<div class="row mb-3"> |
||||
|
<div class="col-6"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h4 mb-0 font-weight-bold text-success"> |
||||
|
{fmt.Sprintf("%d", data.Volume.FileCount)} |
||||
|
</div> |
||||
|
<small class="text-muted">Active Files</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-6"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h4 mb-0 font-weight-bold text-danger"> |
||||
|
{fmt.Sprintf("%d", data.Volume.DeleteCount)} |
||||
|
</div> |
||||
|
<small class="text-muted">Deleted Files</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- Storage Efficiency --> |
||||
|
if data.Volume.FileCount > 0 && data.Volume.Size > 0 { |
||||
|
<div class="mb-3"> |
||||
|
<div class="d-flex justify-content-between align-items-center mb-1"> |
||||
|
<small class="text-muted">Storage Efficiency</small> |
||||
|
<small class="text-muted"> |
||||
|
{fmt.Sprintf("%.1f%%", float64(data.Volume.Size-data.Volume.DeletedByteCount)/float64(data.Volume.Size)*100)} |
||||
|
</small> |
||||
|
</div> |
||||
|
<div class="progress" style="height: 8px;"> |
||||
|
<div class="progress-bar bg-info" role="progressbar" |
||||
|
style={fmt.Sprintf("width: %.1f%%", float64(data.Volume.Size-data.Volume.DeletedByteCount)/float64(data.Volume.Size)*100)} |
||||
|
aria-valuenow={fmt.Sprintf("%.1f", float64(data.Volume.Size-data.Volume.DeletedByteCount)/float64(data.Volume.Size)*100)} |
||||
|
aria-valuemin="0" aria-valuemax="100"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
<hr class="my-3"> |
||||
|
|
||||
|
<!-- Status & Configuration --> |
||||
|
<div class="row mb-3"> |
||||
|
<div class="col-12"> |
||||
|
<div class="text-center mb-2"> |
||||
|
if data.Volume.ReadOnly { |
||||
|
<span class="badge bg-warning fs-6 px-3 py-2"> |
||||
|
<i class="fas fa-lock me-1"></i>Read Only |
||||
|
</span> |
||||
|
if data.Volume.Size >= data.VolumeSizeLimit { |
||||
|
<div class="mt-1"> |
||||
|
<small class="text-muted">Size limit exceeded</small> |
||||
|
</div> |
||||
|
} |
||||
|
} else if data.VolumeSizeLimit > data.Volume.Size { |
||||
|
<span class="badge bg-success fs-6 px-3 py-2"> |
||||
|
<i class="fas fa-edit me-1"></i>Read/Write |
||||
|
</span> |
||||
|
} else { |
||||
|
<span class="badge bg-warning fs-6 px-3 py-2"> |
||||
|
<i class="fas fa-exclamation-triangle me-1"></i>Size Limit Reached |
||||
|
</span> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Maintenance Info --> |
||||
|
<div class="row mb-3"> |
||||
|
<div class="col-6"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h6 mb-0 font-weight-bold text-info"> |
||||
|
#{fmt.Sprintf("%d", data.Volume.CompactRevision)} |
||||
|
</div> |
||||
|
<small class="text-muted">Compact Revision</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-6"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h6 mb-0 font-weight-bold text-secondary"> |
||||
|
if data.Volume.ModifiedAtSecond > 0 { |
||||
|
{formatTimestamp(data.Volume.ModifiedAtSecond)} |
||||
|
} else { |
||||
|
<span class="text-muted">Never modified</span> |
||||
|
} |
||||
|
</div> |
||||
|
<small class="text-muted">Last Modified</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- TTL Configuration --> |
||||
|
if data.Volume.Ttl > 0 { |
||||
|
<div class="mb-3 text-center"> |
||||
|
<span class="badge bg-info fs-6 px-3 py-2"> |
||||
|
<i class="fas fa-clock me-1"></i>{formatTTL(data.Volume.Ttl)} |
||||
|
</span> |
||||
|
<div class="mt-1"> |
||||
|
<small class="text-muted">Time To Live</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
<!-- Remote Storage Configuration --> |
||||
|
if data.Volume.RemoteStorageName != "" { |
||||
|
<hr class="my-3"> |
||||
|
<div class="mb-2"> |
||||
|
<div class="text-center"> |
||||
|
<div class="h6 mb-1 font-weight-bold text-info"> |
||||
|
<i class="fas fa-cloud me-1"></i>{data.Volume.RemoteStorageName} |
||||
|
</div> |
||||
|
<small class="text-muted">Remote Storage</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
if data.Volume.RemoteStorageKey != "" { |
||||
|
<div class="text-center"> |
||||
|
<div class="text-xs font-monospace bg-light p-2 rounded text-truncate" title={data.Volume.RemoteStorageKey}> |
||||
|
{data.Volume.RemoteStorageKey} |
||||
|
</div> |
||||
|
<small class="text-muted">Storage Key</small> |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Replicas Card --> |
||||
|
if len(data.Replicas) > 0 { |
||||
|
<div class="row"> |
||||
|
<div class="col-12"> |
||||
|
<div class="card shadow mb-4"> |
||||
|
<div class="card-header py-3"> |
||||
|
<h6 class="m-0 font-weight-bold text-primary"> |
||||
|
<i class="fas fa-copy me-2"></i>Replicas ({fmt.Sprintf("%d", data.ReplicationCount)}) |
||||
|
</h6> |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="table-responsive"> |
||||
|
<table class="table table-hover"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>Server</th> |
||||
|
<th>Data Center</th> |
||||
|
<th>Rack</th> |
||||
|
<th>Size</th> |
||||
|
<th>File Count</th> |
||||
|
<th>Status</th> |
||||
|
<th>Actions</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<!-- Primary Volume (current one) --> |
||||
|
<tr class="table-primary"> |
||||
|
<td> |
||||
|
<strong> |
||||
|
<a href={templ.SafeURL(fmt.Sprintf("http://%s", data.Volume.Server))} target="_blank" class="text-decoration-none"> |
||||
|
{data.Volume.Server} |
||||
|
<i class="fas fa-external-link-alt ms-1 text-muted"></i> |
||||
|
</a> |
||||
|
</strong> |
||||
|
<span class="badge bg-success ms-2">Primary</span> |
||||
|
</td> |
||||
|
<td><span class="badge bg-light text-dark">{data.Volume.DataCenter}</span></td> |
||||
|
<td><span class="badge bg-light text-dark">{data.Volume.Rack}</span></td> |
||||
|
<td>{formatBytes(int64(data.Volume.Size))}</td> |
||||
|
<td>{fmt.Sprintf("%d", data.Volume.FileCount)}</td> |
||||
|
<td><span class="badge bg-success">Active</span></td> |
||||
|
<td> |
||||
|
<span class="text-muted">Current Volume</span> |
||||
|
</td> |
||||
|
</tr> |
||||
|
<!-- Replica Volumes --> |
||||
|
for _, replica := range data.Replicas { |
||||
|
<tr> |
||||
|
<td> |
||||
|
<a href={templ.SafeURL(fmt.Sprintf("http://%s", replica.Server))} target="_blank" class="text-decoration-none"> |
||||
|
{replica.Server} |
||||
|
<i class="fas fa-external-link-alt ms-1 text-muted"></i> |
||||
|
</a> |
||||
|
</td> |
||||
|
<td><span class="badge bg-light text-dark">{replica.DataCenter}</span></td> |
||||
|
<td><span class="badge bg-light text-dark">{replica.Rack}</span></td> |
||||
|
<td>{formatBytes(int64(replica.Size))}</td> |
||||
|
<td>{fmt.Sprintf("%d", replica.FileCount)}</td> |
||||
|
<td><span class="badge bg-info">Replica</span></td> |
||||
|
<td> |
||||
|
<a href={templ.SafeURL(fmt.Sprintf("/cluster/volumes/%d/%s", replica.Id, replica.Server))} class="btn btn-sm btn-outline-primary"> |
||||
|
<i class="fas fa-eye me-1"></i>View |
||||
|
</a> |
||||
|
</td> |
||||
|
</tr> |
||||
|
} |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
<!-- Actions Card --> |
||||
|
<div class="row"> |
||||
|
<div class="col-12"> |
||||
|
<div class="card shadow mb-4"> |
||||
|
<div class="card-header py-3"> |
||||
|
<h6 class="m-0 font-weight-bold text-primary"> |
||||
|
<i class="fas fa-tools me-2"></i>Actions |
||||
|
</h6> |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div class="btn-group" role="group"> |
||||
|
<button type="button" class="btn btn-outline-secondary" title="Compact Volume"> |
||||
|
<i class="fas fa-compress-alt me-1"></i>Compact |
||||
|
</button> |
||||
|
<button type="button" class="btn btn-outline-warning" title="Fix Volume"> |
||||
|
<i class="fas fa-wrench me-1"></i>Fix |
||||
|
</button> |
||||
|
<button type="button" class="btn btn-outline-danger" title="Vacuum Volume"> |
||||
|
<i class="fas fa-trash me-1"></i>Vacuum |
||||
|
</button> |
||||
|
</div> |
||||
|
<div class="mt-3"> |
||||
|
<small class="text-muted"> |
||||
|
<i class="fas fa-info-circle me-1"></i> |
||||
|
Use these actions to perform maintenance operations on the volume. |
||||
|
</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Last Updated --> |
||||
|
<div class="row"> |
||||
|
<div class="col-12"> |
||||
|
<small class="text-muted"> |
||||
|
<i class="fas fa-clock me-1"></i> |
||||
|
Last updated: {data.LastUpdated.Format("2006-01-02 15:04:05")} |
||||
|
</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
func formatTimestamp(unixTimestamp int64) string { |
||||
|
if unixTimestamp <= 0 { |
||||
|
return "Never" |
||||
|
} |
||||
|
t := time.Unix(unixTimestamp, 0) |
||||
|
return t.Format("2006-01-02 15:04:05") |
||||
|
} |
||||
|
|
||||
|
func formatTTL(ttlSeconds uint32) string { |
||||
|
if ttlSeconds == 0 { |
||||
|
return "No TTL" |
||||
|
} |
||||
|
|
||||
|
duration := time.Duration(ttlSeconds) * time.Second |
||||
|
|
||||
|
// Convert to human readable format |
||||
|
days := int(duration.Hours()) / 24 |
||||
|
hours := int(duration.Hours()) % 24 |
||||
|
minutes := int(duration.Minutes()) % 60 |
||||
|
|
||||
|
if days > 0 { |
||||
|
if hours > 0 { |
||||
|
return fmt.Sprintf("%dd %dh", days, hours) |
||||
|
} |
||||
|
return fmt.Sprintf("%d days", days) |
||||
|
} else if hours > 0 { |
||||
|
if minutes > 0 { |
||||
|
return fmt.Sprintf("%dh %dm", hours, minutes) |
||||
|
} |
||||
|
return fmt.Sprintf("%d hours", hours) |
||||
|
} else if minutes > 0 { |
||||
|
return fmt.Sprintf("%d minutes", minutes) |
||||
|
} else { |
||||
|
return fmt.Sprintf("%d seconds", int(duration.Seconds())) |
||||
|
} |
||||
|
} |
@ -0,0 +1,690 @@ |
|||||
|
// Code generated by templ - DO NOT EDIT.
|
||||
|
|
||||
|
// templ: version: v0.3.833
|
||||
|
package app |
||||
|
|
||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
|
||||
|
import "github.com/a-h/templ" |
||||
|
import templruntime "github.com/a-h/templ/runtime" |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"github.com/seaweedfs/seaweedfs/weed/admin/dash" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
func VolumeDetails(data dash.VolumeDetailsData) templ.Component { |
||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { |
||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context |
||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { |
||||
|
return templ_7745c5c3_CtxErr |
||||
|
} |
||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) |
||||
|
if !templ_7745c5c3_IsBuffer { |
||||
|
defer func() { |
||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) |
||||
|
if templ_7745c5c3_Err == nil { |
||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr |
||||
|
} |
||||
|
}() |
||||
|
} |
||||
|
ctx = templ.InitializeContext(ctx) |
||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx) |
||||
|
if templ_7745c5c3_Var1 == nil { |
||||
|
templ_7745c5c3_Var1 = templ.NopComponent |
||||
|
} |
||||
|
ctx = templ.ClearChildren(ctx) |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom\"><div><h1 class=\"h2\"><i class=\"fas fa-database me-2\"></i>Volume Details</h1><nav aria-label=\"breadcrumb\"><ol class=\"breadcrumb\"><li class=\"breadcrumb-item\"><a href=\"/admin\" class=\"text-decoration-none\">Dashboard</a></li><li class=\"breadcrumb-item\"><a href=\"/cluster/volumes\" class=\"text-decoration-none\">Volumes</a></li><li class=\"breadcrumb-item active\" aria-current=\"page\">Volume ") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var2 string |
||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Volume.Id)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 19, Col: 116} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</li></ol></nav></div><div class=\"btn-toolbar mb-2 mb-md-0\"><div class=\"btn-group me-2\"><button type=\"button\" class=\"btn btn-sm btn-outline-secondary\" onclick=\"history.back()\"><i class=\"fas fa-arrow-left me-1\"></i>Back</button> <button type=\"button\" class=\"btn btn-sm btn-outline-primary\" onclick=\"window.location.reload()\"><i class=\"fas fa-refresh me-1\"></i>Refresh</button></div></div></div><div class=\"row\"><!-- Volume Information Card --><div class=\"col-lg-8\"><div class=\"card shadow mb-4\"><div class=\"card-header py-3\"><h6 class=\"m-0 font-weight-bold text-primary\"><i class=\"fas fa-info-circle me-2\"></i>Volume Information</h6></div><div class=\"card-body\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label class=\"form-label\"><strong>Volume ID:</strong></label><div><code class=\"fs-5\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var3 string |
||||
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Volume.Id)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 49, Col: 90} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</code></div></div><div class=\"mb-3\"><label class=\"form-label\"><strong>Server:</strong></label><div><a href=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s", data.Volume.Server)) |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" target=\"_blank\" class=\"text-decoration-none\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var5 string |
||||
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.Server) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 55, Col: 59} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " <i class=\"fas fa-external-link-alt ms-1 text-muted\"></i></a></div></div><div class=\"mb-3\"><label class=\"form-label\"><strong>Data Center:</strong></label><div><span class=\"badge bg-light text-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var6 string |
||||
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.DataCenter) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 62, Col: 99} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</span></div></div><div class=\"mb-3\"><label class=\"form-label\"><strong>Rack:</strong></label><div><span class=\"badge bg-light text-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var7 string |
||||
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.Rack) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 66, Col: 93} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span></div></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label class=\"form-label\"><strong>Collection:</strong></label><div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.Collection == "" { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<a href=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL("/cluster/volumes?collection=default") |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" class=\"text-decoration-none\"><span class=\"badge bg-secondary\">default</span></a>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} else { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<a href=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", data.Volume.Collection)) |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" class=\"text-decoration-none\"><span class=\"badge bg-secondary\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var10 string |
||||
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.Collection) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 79, Col: 100} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</span></a>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div><div class=\"mb-3\"><label class=\"form-label\"><strong>Replication:</strong></label><div><span class=\"badge bg-info\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var11 string |
||||
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%03d", data.Volume.ReplicaPlacement)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 86, Col: 115} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</span></div></div><div class=\"mb-3\"><label class=\"form-label\"><strong>Disk Type:</strong></label><div><span class=\"badge bg-primary\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.DiskType == "" { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "hdd") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} else { |
||||
|
var templ_7745c5c3_Var12 string |
||||
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.DiskType) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 95, Col: 65} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span></div></div><div class=\"mb-3\"><label class=\"form-label\"><strong>Version:</strong></label><div><span class=\"badge bg-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var13 string |
||||
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("v%d", data.Volume.Version)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 102, Col: 105} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</span></div></div></div></div></div></div></div><!-- Statistics Card --><div class=\"col-lg-4\"><!-- Volume Statistics & Health Card --><div class=\"card shadow mb-4\"><div class=\"card-header py-3\"><h6 class=\"m-0 font-weight-bold text-primary\"><i class=\"fas fa-chart-pie me-2\"></i>Volume Statistics & Health</h6></div><div class=\"card-body\"><!-- Storage Metrics --><div class=\"row mb-3\"><div class=\"col-6\"><div class=\"text-center\"><div class=\"h4 mb-0 font-weight-bold text-success\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var14 string |
||||
|
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(int64(data.Volume.Size - data.Volume.DeletedByteCount))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 125, Col: 104} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div><small class=\"text-muted\">Active Bytes</small></div></div><div class=\"col-6\"><div class=\"text-center\"><div class=\"h4 mb-0 font-weight-bold text-danger\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var15 string |
||||
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(int64(data.Volume.DeletedByteCount))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 133, Col: 85} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div><small class=\"text-muted\">Deleted Bytes</small></div></div></div><!-- File Metrics --><div class=\"row mb-3\"><div class=\"col-6\"><div class=\"text-center\"><div class=\"h4 mb-0 font-weight-bold text-success\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var16 string |
||||
|
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Volume.FileCount)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 147, Col: 77} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div><small class=\"text-muted\">Active Files</small></div></div><div class=\"col-6\"><div class=\"text-center\"><div class=\"h4 mb-0 font-weight-bold text-danger\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var17 string |
||||
|
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Volume.DeleteCount)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 155, Col: 79} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div><small class=\"text-muted\">Deleted Files</small></div></div></div><!-- Storage Efficiency -->") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.FileCount > 0 && data.Volume.Size > 0 { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<div class=\"mb-3\"><div class=\"d-flex justify-content-between align-items-center mb-1\"><small class=\"text-muted\">Storage Efficiency</small> <small class=\"text-muted\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var18 string |
||||
|
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f%%", float64(data.Volume.Size-data.Volume.DeletedByteCount)/float64(data.Volume.Size)*100)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 170, Col: 144} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</small></div><div class=\"progress\" style=\"height: 8px;\"><div class=\"progress-bar bg-info\" role=\"progressbar\" style=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var19 string |
||||
|
templ_7745c5c3_Var19, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %.1f%%", float64(data.Volume.Size-data.Volume.DeletedByteCount)/float64(data.Volume.Size)*100)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 175, Col: 158} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" aria-valuenow=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var20 string |
||||
|
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", float64(data.Volume.Size-data.Volume.DeletedByteCount)/float64(data.Volume.Size)*100)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 176, Col: 157} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" aria-valuemin=\"0\" aria-valuemax=\"100\"></div></div></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<hr class=\"my-3\"><!-- Status & Configuration --><div class=\"row mb-3\"><div class=\"col-12\"><div class=\"text-center mb-2\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.ReadOnly { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<span class=\"badge bg-warning fs-6 px-3 py-2\"><i class=\"fas fa-lock me-1\"></i>Read Only</span> ") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.Size >= data.VolumeSizeLimit { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"mt-1\"><small class=\"text-muted\">Size limit exceeded</small></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
} else if data.VolumeSizeLimit > data.Volume.Size { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<span class=\"badge bg-success fs-6 px-3 py-2\"><i class=\"fas fa-edit me-1\"></i>Read/Write</span>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} else { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<span class=\"badge bg-warning fs-6 px-3 py-2\"><i class=\"fas fa-exclamation-triangle me-1\"></i>Size Limit Reached</span>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div></div></div><!-- Maintenance Info --><div class=\"row mb-3\"><div class=\"col-6\"><div class=\"text-center\"><div class=\"h6 mb-0 font-weight-bold text-info\">#") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var21 string |
||||
|
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Volume.CompactRevision)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 216, Col: 84} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</div><small class=\"text-muted\">Compact Revision</small></div></div><div class=\"col-6\"><div class=\"text-center\"><div class=\"h6 mb-0 font-weight-bold text-secondary\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.ModifiedAtSecond > 0 { |
||||
|
var templ_7745c5c3_Var22 string |
||||
|
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(formatTimestamp(data.Volume.ModifiedAtSecond)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 225, Col: 86} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} else { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<span class=\"text-muted\">Never modified</span>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</div><small class=\"text-muted\">Last Modified</small></div></div></div><!-- TTL Configuration -->") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.Ttl > 0 { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<div class=\"mb-3 text-center\"><span class=\"badge bg-info fs-6 px-3 py-2\"><i class=\"fas fa-clock me-1\"></i>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var23 string |
||||
|
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(formatTTL(data.Volume.Ttl)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 239, Col: 92} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</span><div class=\"mt-1\"><small class=\"text-muted\">Time To Live</small></div></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<!-- Remote Storage Configuration -->") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.RemoteStorageName != "" { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<hr class=\"my-3\"><div class=\"mb-2\"><div class=\"text-center\"><div class=\"h6 mb-1 font-weight-bold text-info\"><i class=\"fas fa-cloud me-1\"></i>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var24 string |
||||
|
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.RemoteStorageName) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 253, Col: 99} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</div><small class=\"text-muted\">Remote Storage</small></div></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if data.Volume.RemoteStorageKey != "" { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<div class=\"text-center\"><div class=\"text-xs font-monospace bg-light p-2 rounded text-truncate\" title=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var25 string |
||||
|
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.RemoteStorageKey) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 260, Col: 138} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var26 string |
||||
|
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.RemoteStorageKey) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 261, Col: 65} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</div><small class=\"text-muted\">Storage Key</small></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</div></div></div></div><!-- Replicas Card -->") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
if len(data.Replicas) > 0 { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<div class=\"row\"><div class=\"col-12\"><div class=\"card shadow mb-4\"><div class=\"card-header py-3\"><h6 class=\"m-0 font-weight-bold text-primary\"><i class=\"fas fa-copy me-2\"></i>Replicas (") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var27 string |
||||
|
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.ReplicationCount)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 279, Col: 111} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, ")</h6></div><div class=\"card-body\"><div class=\"table-responsive\"><table class=\"table table-hover\"><thead><tr><th>Server</th><th>Data Center</th><th>Rack</th><th>Size</th><th>File Count</th><th>Status</th><th>Actions</th></tr></thead> <tbody><!-- Primary Volume (current one) --><tr class=\"table-primary\"><td><strong><a href=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var28 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s", data.Volume.Server)) |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var28))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\" target=\"_blank\" class=\"text-decoration-none\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var29 string |
||||
|
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.Server) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 302, Col: 71} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, " <i class=\"fas fa-external-link-alt ms-1 text-muted\"></i></a></strong> <span class=\"badge bg-success ms-2\">Primary</span></td><td><span class=\"badge bg-light text-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var30 string |
||||
|
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.DataCenter) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 308, Col: 106} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</span></td><td><span class=\"badge bg-light text-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var31 string |
||||
|
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(data.Volume.Rack) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 309, Col: 100} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</span></td><td>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var32 string |
||||
|
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(int64(data.Volume.Size))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 310, Col: 81} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</td><td>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var33 string |
||||
|
templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Volume.FileCount)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 311, Col: 85} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</td><td><span class=\"badge bg-success\">Active</span></td><td><span class=\"text-muted\">Current Volume</span></td></tr><!-- Replica Volumes -->") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
for _, replica := range data.Replicas { |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "<tr><td><a href=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var34 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s", replica.Server)) |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var34))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" target=\"_blank\" class=\"text-decoration-none\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var35 string |
||||
|
templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(replica.Server) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 322, Col: 67} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, " <i class=\"fas fa-external-link-alt ms-1 text-muted\"></i></a></td><td><span class=\"badge bg-light text-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var36 string |
||||
|
templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(replica.DataCenter) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 326, Col: 106} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</span></td><td><span class=\"badge bg-light text-dark\">") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var37 string |
||||
|
templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(replica.Rack) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 327, Col: 100} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</span></td><td>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var38 string |
||||
|
templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(int64(replica.Size))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 328, Col: 81} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "</td><td>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var39 string |
||||
|
templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", replica.FileCount)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 329, Col: 85} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</td><td><span class=\"badge bg-info\">Replica</span></td><td><a href=\"") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var40 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes/%d/%s", replica.Id, replica.Server)) |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var40))) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "\" class=\"btn btn-sm btn-outline-primary\"><i class=\"fas fa-eye me-1\"></i>View</a></td></tr>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</tbody></table></div></div></div></div></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "<!-- Actions Card --><div class=\"row\"><div class=\"col-12\"><div class=\"card shadow mb-4\"><div class=\"card-header py-3\"><h6 class=\"m-0 font-weight-bold text-primary\"><i class=\"fas fa-tools me-2\"></i>Actions</h6></div><div class=\"card-body\"><div class=\"btn-group\" role=\"group\"><button type=\"button\" class=\"btn btn-outline-secondary\" title=\"Compact Volume\"><i class=\"fas fa-compress-alt me-1\"></i>Compact</button> <button type=\"button\" class=\"btn btn-outline-warning\" title=\"Fix Volume\"><i class=\"fas fa-wrench me-1\"></i>Fix</button> <button type=\"button\" class=\"btn btn-outline-danger\" title=\"Vacuum Volume\"><i class=\"fas fa-trash me-1\"></i>Vacuum</button></div><div class=\"mt-3\"><small class=\"text-muted\"><i class=\"fas fa-info-circle me-1\"></i> Use these actions to perform maintenance operations on the volume.</small></div></div></div></div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"fas fa-clock me-1\"></i> Last updated: ") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
var templ_7745c5c3_Var41 string |
||||
|
templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05")) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 384, Col: 77} |
||||
|
} |
||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "</small></div></div>") |
||||
|
if templ_7745c5c3_Err != nil { |
||||
|
return templ_7745c5c3_Err |
||||
|
} |
||||
|
return nil |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
func formatTimestamp(unixTimestamp int64) string { |
||||
|
if unixTimestamp <= 0 { |
||||
|
return "Never" |
||||
|
} |
||||
|
t := time.Unix(unixTimestamp, 0) |
||||
|
return t.Format("2006-01-02 15:04:05") |
||||
|
} |
||||
|
|
||||
|
func formatTTL(ttlSeconds uint32) string { |
||||
|
if ttlSeconds == 0 { |
||||
|
return "No TTL" |
||||
|
} |
||||
|
|
||||
|
duration := time.Duration(ttlSeconds) * time.Second |
||||
|
|
||||
|
// Convert to human readable format
|
||||
|
days := int(duration.Hours()) / 24 |
||||
|
hours := int(duration.Hours()) % 24 |
||||
|
minutes := int(duration.Minutes()) % 60 |
||||
|
|
||||
|
if days > 0 { |
||||
|
if hours > 0 { |
||||
|
return fmt.Sprintf("%dd %dh", days, hours) |
||||
|
} |
||||
|
return fmt.Sprintf("%d days", days) |
||||
|
} else if hours > 0 { |
||||
|
if minutes > 0 { |
||||
|
return fmt.Sprintf("%dh %dm", hours, minutes) |
||||
|
} |
||||
|
return fmt.Sprintf("%d hours", hours) |
||||
|
} else if minutes > 0 { |
||||
|
return fmt.Sprintf("%d minutes", minutes) |
||||
|
} else { |
||||
|
return fmt.Sprintf("%d seconds", int(duration.Seconds())) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var _ = templruntime.GeneratedTemplate |
Write
Preview
Loading…
Cancel
Save
Reference in new issue