15 changed files with 1993 additions and 384 deletions
-
268weed/admin/dash/collection_management.go
-
6weed/admin/dash/ec_shard_management.go
-
42weed/admin/dash/types.go
-
2weed/admin/handlers/admin_handlers.go
-
39weed/admin/handlers/cluster_handlers.go
-
75weed/admin/view/app/cluster_collections.templ
-
256weed/admin/view/app/cluster_collections_templ.go
-
18weed/admin/view/app/cluster_ec_shards.templ
-
263weed/admin/view/app/cluster_ec_shards_templ.go
-
22weed/admin/view/app/cluster_ec_volumes.templ
-
213weed/admin/view/app/cluster_ec_volumes_templ.go
-
371weed/admin/view/app/collection_details.templ
-
567weed/admin/view/app/collection_details_templ.go
-
86weed/admin/view/app/ec_volume_details.templ
-
149weed/admin/view/app/ec_volume_details_templ.go
256
weed/admin/view/app/cluster_collections_templ.go
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,371 @@ |
|||
package app |
|||
|
|||
import ( |
|||
"fmt" |
|||
"github.com/seaweedfs/seaweedfs/weed/admin/dash" |
|||
"github.com/seaweedfs/seaweedfs/weed/util" |
|||
) |
|||
|
|||
templ CollectionDetails(data dash.CollectionDetailsData) { |
|||
<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-layer-group me-2"></i>Collection Details: {data.CollectionName} |
|||
</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/collections" class="text-decoration-none">Collections</a></li> |
|||
<li class="breadcrumb-item active" aria-current="page">{data.CollectionName}</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> |
|||
|
|||
<!-- Collection Summary --> |
|||
<div class="row mb-4"> |
|||
<div class="col-md-3"> |
|||
<div class="card text-bg-primary"> |
|||
<div class="card-body"> |
|||
<div class="d-flex justify-content-between"> |
|||
<div> |
|||
<h6 class="card-title">Regular Volumes</h6> |
|||
<h4 class="mb-0">{fmt.Sprintf("%d", data.TotalVolumes)}</h4> |
|||
<small>Traditional volumes</small> |
|||
</div> |
|||
<div class="align-self-center"> |
|||
<i class="fas fa-database fa-2x"></i> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
<div class="card text-bg-info"> |
|||
<div class="card-body"> |
|||
<div class="d-flex justify-content-between"> |
|||
<div> |
|||
<h6 class="card-title">EC Volumes</h6> |
|||
<h4 class="mb-0">{fmt.Sprintf("%d", data.TotalEcVolumes)}</h4> |
|||
<small>Erasure coded volumes</small> |
|||
</div> |
|||
<div class="align-self-center"> |
|||
<i class="fas fa-th-large fa-2x"></i> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
<div class="card text-bg-success"> |
|||
<div class="card-body"> |
|||
<div class="d-flex justify-content-between"> |
|||
<div> |
|||
<h6 class="card-title">Total Files</h6> |
|||
<h4 class="mb-0">{fmt.Sprintf("%d", data.TotalFiles)}</h4> |
|||
<small>Files stored</small> |
|||
</div> |
|||
<div class="align-self-center"> |
|||
<i class="fas fa-file fa-2x"></i> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
<div class="card text-bg-warning"> |
|||
<div class="card-body"> |
|||
<div class="d-flex justify-content-between"> |
|||
<div> |
|||
<h6 class="card-title">Total Size (Logical)</h6> |
|||
<h4 class="mb-0">{util.BytesToHumanReadable(uint64(data.TotalSize))}</h4> |
|||
<small>Data stored (regular volumes only)</small> |
|||
</div> |
|||
<div class="align-self-center"> |
|||
<i class="fas fa-hdd fa-2x"></i> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Size Information Note --> |
|||
<div class="alert alert-info" role="alert"> |
|||
<i class="fas fa-info-circle me-2"></i> |
|||
<strong>Size Information:</strong> |
|||
Logical size represents the actual data stored (regular volumes only). |
|||
EC volumes show shard counts instead of size - physical storage for EC volumes is approximately 1.4x the original data due to erasure coding redundancy. |
|||
</div> |
|||
|
|||
<!-- Pagination Info --> |
|||
<div class="d-flex justify-content-between align-items-center mb-3"> |
|||
<div class="d-flex align-items-center"> |
|||
<span class="me-3"> |
|||
Showing {fmt.Sprintf("%d", (data.Page-1)*data.PageSize + 1)} to {fmt.Sprintf("%d", func() int { |
|||
end := data.Page * data.PageSize |
|||
totalItems := data.TotalVolumes + data.TotalEcVolumes |
|||
if end > totalItems { |
|||
return totalItems |
|||
} |
|||
return end |
|||
}())} of {fmt.Sprintf("%d", data.TotalVolumes + data.TotalEcVolumes)} items |
|||
</span> |
|||
|
|||
<div class="d-flex align-items-center"> |
|||
<label for="pageSize" class="form-label me-2 mb-0">Show:</label> |
|||
<select id="pageSize" class="form-select form-select-sm" style="width: auto;" onchange="changePageSize(this.value)"> |
|||
<option value="10" if data.PageSize == 10 { selected }>10</option> |
|||
<option value="25" if data.PageSize == 25 { selected }>25</option> |
|||
<option value="50" if data.PageSize == 50 { selected }>50</option> |
|||
<option value="100" if data.PageSize == 100 { selected }>100</option> |
|||
</select> |
|||
<span class="ms-2">per page</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Volumes Table --> |
|||
<div class="table-responsive"> |
|||
<table class="table table-striped table-hover" id="volumesTable"> |
|||
<thead> |
|||
<tr> |
|||
<th> |
|||
<a href="#" onclick="sortBy('volume_id')" class="text-dark text-decoration-none"> |
|||
Volume ID |
|||
if data.SortBy == "volume_id" { |
|||
if data.SortOrder == "asc" { |
|||
<i class="fas fa-sort-up ms-1"></i> |
|||
} else { |
|||
<i class="fas fa-sort-down ms-1"></i> |
|||
} |
|||
} else { |
|||
<i class="fas fa-sort ms-1 text-muted"></i> |
|||
} |
|||
</a> |
|||
</th> |
|||
<th> |
|||
<a href="#" onclick="sortBy('type')" class="text-dark text-decoration-none"> |
|||
Type |
|||
if data.SortBy == "type" { |
|||
if data.SortOrder == "asc" { |
|||
<i class="fas fa-sort-up ms-1"></i> |
|||
} else { |
|||
<i class="fas fa-sort-down ms-1"></i> |
|||
} |
|||
} else { |
|||
<i class="fas fa-sort ms-1 text-muted"></i> |
|||
} |
|||
</a> |
|||
</th> |
|||
<th class="text-dark">Logical Size / Shard Count</th> |
|||
<th class="text-dark">Files</th> |
|||
<th class="text-dark">Status</th> |
|||
<th class="text-dark">Actions</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
// Display regular volumes |
|||
for _, volume := range data.RegularVolumes { |
|||
<tr> |
|||
<td> |
|||
<strong>{fmt.Sprintf("%d", volume.Id)}</strong> |
|||
</td> |
|||
<td> |
|||
<span class="badge bg-primary"> |
|||
<i class="fas fa-database me-1"></i>Regular |
|||
</span> |
|||
</td> |
|||
<td> |
|||
{util.BytesToHumanReadable(volume.Size)} |
|||
</td> |
|||
<td> |
|||
{fmt.Sprintf("%d", volume.FileCount)} |
|||
</td> |
|||
<td> |
|||
if volume.ReadOnly { |
|||
<span class="badge bg-warning">Read Only</span> |
|||
} else { |
|||
<span class="badge bg-success">Read/Write</span> |
|||
} |
|||
</td> |
|||
<td> |
|||
<div class="btn-group" role="group"> |
|||
<button type="button" class="btn btn-sm btn-outline-primary" |
|||
onclick="showVolumeDetails(event)" |
|||
data-volume-id={ fmt.Sprintf("%d", volume.Id) } |
|||
data-server={ volume.Server } |
|||
title="View volume details"> |
|||
<i class="fas fa-info-circle"></i> |
|||
</button> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
} |
|||
|
|||
// Display EC volumes |
|||
for _, ecVolume := range data.EcVolumes { |
|||
<tr> |
|||
<td> |
|||
<strong>{fmt.Sprintf("%d", ecVolume.VolumeID)}</strong> |
|||
</td> |
|||
<td> |
|||
<span class="badge bg-info"> |
|||
<i class="fas fa-th-large me-1"></i>EC |
|||
</span> |
|||
</td> |
|||
<td> |
|||
<span class="badge bg-primary">{fmt.Sprintf("%d/14", ecVolume.TotalShards)}</span> |
|||
</td> |
|||
<td> |
|||
<span class="text-muted">-</span> |
|||
</td> |
|||
<td> |
|||
if ecVolume.IsComplete { |
|||
<span class="badge bg-success"> |
|||
<i class="fas fa-check me-1"></i>Complete |
|||
</span> |
|||
} else { |
|||
<span class="badge bg-warning"> |
|||
<i class="fas fa-exclamation-triangle me-1"></i> |
|||
Missing {fmt.Sprintf("%d", len(ecVolume.MissingShards))} shards |
|||
</span> |
|||
} |
|||
</td> |
|||
<td> |
|||
<div class="btn-group" role="group"> |
|||
<button type="button" class="btn btn-sm btn-outline-info" |
|||
onclick="showEcVolumeDetails(event)" |
|||
data-volume-id={ fmt.Sprintf("%d", ecVolume.VolumeID) } |
|||
title="View EC volume details"> |
|||
<i class="fas fa-info-circle"></i> |
|||
</button> |
|||
if !ecVolume.IsComplete { |
|||
<button type="button" class="btn btn-sm btn-outline-warning" |
|||
onclick="repairEcVolume(event)" |
|||
data-volume-id={ fmt.Sprintf("%d", ecVolume.VolumeID) } |
|||
title="Repair missing shards"> |
|||
<i class="fas fa-wrench"></i> |
|||
</button> |
|||
} |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
|
|||
<!-- Pagination --> |
|||
if data.TotalPages > 1 { |
|||
<nav aria-label="Collection volumes pagination"> |
|||
<ul class="pagination justify-content-center"> |
|||
if data.Page > 1 { |
|||
<li class="page-item"> |
|||
<a class="page-link" href="#" onclick="goToPage(event)" data-page="1">First</a> |
|||
</li> |
|||
<li class="page-item"> |
|||
<a class="page-link" href="#" onclick="goToPage(event)" data-page={ fmt.Sprintf("%d", data.Page-1) }>Previous</a> |
|||
</li> |
|||
} |
|||
|
|||
for i := 1; i <= data.TotalPages; i++ { |
|||
if i == data.Page { |
|||
<li class="page-item active"> |
|||
<span class="page-link">{fmt.Sprintf("%d", i)}</span> |
|||
</li> |
|||
} else if i <= 3 || i > data.TotalPages-3 || (i >= data.Page-2 && i <= data.Page+2) { |
|||
<li class="page-item"> |
|||
<a class="page-link" href="#" onclick="goToPage(event)" data-page={ fmt.Sprintf("%d", i) }>{fmt.Sprintf("%d", i)}</a> |
|||
</li> |
|||
} else if i == 4 && data.Page > 6 { |
|||
<li class="page-item disabled"> |
|||
<span class="page-link">...</span> |
|||
</li> |
|||
} else if i == data.TotalPages-3 && data.Page < data.TotalPages-5 { |
|||
<li class="page-item disabled"> |
|||
<span class="page-link">...</span> |
|||
</li> |
|||
} |
|||
} |
|||
|
|||
if data.Page < data.TotalPages { |
|||
<li class="page-item"> |
|||
<a class="page-link" href="#" onclick="goToPage(event)" data-page={ fmt.Sprintf("%d", data.Page+1) }>Next</a> |
|||
</li> |
|||
<li class="page-item"> |
|||
<a class="page-link" href="#" onclick="goToPage(event)" data-page={ fmt.Sprintf("%d", data.TotalPages) }>Last</a> |
|||
</li> |
|||
} |
|||
</ul> |
|||
</nav> |
|||
} |
|||
|
|||
<script> |
|||
// Sorting functionality |
|||
function sortBy(field) { |
|||
const currentSort = new URLSearchParams(window.location.search).get('sort_by'); |
|||
const currentOrder = new URLSearchParams(window.location.search).get('sort_order') || 'asc'; |
|||
|
|||
let newOrder = 'asc'; |
|||
if (currentSort === field && currentOrder === 'asc') { |
|||
newOrder = 'desc'; |
|||
} |
|||
|
|||
const url = new URL(window.location); |
|||
url.searchParams.set('sort_by', field); |
|||
url.searchParams.set('sort_order', newOrder); |
|||
url.searchParams.set('page', '1'); // Reset to first page |
|||
window.location.href = url.toString(); |
|||
} |
|||
|
|||
// Pagination functionality |
|||
function goToPage(event) { |
|||
event.preventDefault(); |
|||
const page = event.target.closest('a').getAttribute('data-page'); |
|||
const url = new URL(window.location); |
|||
url.searchParams.set('page', page); |
|||
window.location.href = url.toString(); |
|||
} |
|||
|
|||
// Page size functionality |
|||
function changePageSize(newPageSize) { |
|||
const url = new URL(window.location); |
|||
url.searchParams.set('page_size', newPageSize); |
|||
url.searchParams.set('page', '1'); // Reset to first page when changing page size |
|||
window.location.href = url.toString(); |
|||
} |
|||
|
|||
// Volume details |
|||
function showVolumeDetails(event) { |
|||
const volumeId = event.target.closest('button').getAttribute('data-volume-id'); |
|||
const server = event.target.closest('button').getAttribute('data-server'); |
|||
window.location.href = `/cluster/volumes/${volumeId}/${server}`; |
|||
} |
|||
|
|||
// EC Volume details |
|||
function showEcVolumeDetails(event) { |
|||
const volumeId = event.target.closest('button').getAttribute('data-volume-id'); |
|||
window.location.href = `/cluster/ec-volumes/${volumeId}`; |
|||
} |
|||
|
|||
// Repair EC Volume |
|||
function repairEcVolume(event) { |
|||
const volumeId = event.target.closest('button').getAttribute('data-volume-id'); |
|||
if (confirm(`Are you sure you want to repair missing shards for EC volume ${volumeId}?`)) { |
|||
// TODO: Implement repair functionality |
|||
alert('Repair functionality will be implemented soon.'); |
|||
} |
|||
} |
|||
</script> |
|||
} |
|||
@ -0,0 +1,567 @@ |
|||
// Code generated by templ - DO NOT EDIT.
|
|||
|
|||
// templ: version: v0.3.906
|
|||
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" |
|||
"github.com/seaweedfs/seaweedfs/weed/util" |
|||
) |
|||
|
|||
func CollectionDetails(data dash.CollectionDetailsData) 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-layer-group me-2\"></i>Collection Details: ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var2 string |
|||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.CollectionName) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 13, Col: 83} |
|||
} |
|||
_, 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, "</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/collections\" class=\"text-decoration-none\">Collections</a></li><li class=\"breadcrumb-item active\" aria-current=\"page\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var3 string |
|||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.CollectionName) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 19, Col: 80} |
|||
} |
|||
_, 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, "</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><!-- Collection Summary --><div class=\"row mb-4\"><div class=\"col-md-3\"><div class=\"card text-bg-primary\"><div class=\"card-body\"><div class=\"d-flex justify-content-between\"><div><h6 class=\"card-title\">Regular Volumes</h6><h4 class=\"mb-0\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var4 string |
|||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalVolumes)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 43, Col: 61} |
|||
} |
|||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</h4><small>Traditional volumes</small></div><div class=\"align-self-center\"><i class=\"fas fa-database fa-2x\"></i></div></div></div></div></div><div class=\"col-md-3\"><div class=\"card text-bg-info\"><div class=\"card-body\"><div class=\"d-flex justify-content-between\"><div><h6 class=\"card-title\">EC Volumes</h6><h4 class=\"mb-0\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var5 string |
|||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalEcVolumes)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 59, Col: 63} |
|||
} |
|||
_, 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, "</h4><small>Erasure coded volumes</small></div><div class=\"align-self-center\"><i class=\"fas fa-th-large fa-2x\"></i></div></div></div></div></div><div class=\"col-md-3\"><div class=\"card text-bg-success\"><div class=\"card-body\"><div class=\"d-flex justify-content-between\"><div><h6 class=\"card-title\">Total Files</h6><h4 class=\"mb-0\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var6 string |
|||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalFiles)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 75, Col: 59} |
|||
} |
|||
_, 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, "</h4><small>Files stored</small></div><div class=\"align-self-center\"><i class=\"fas fa-file fa-2x\"></i></div></div></div></div></div><div class=\"col-md-3\"><div class=\"card text-bg-warning\"><div class=\"card-body\"><div class=\"d-flex justify-content-between\"><div><h6 class=\"card-title\">Total Size (Logical)</h6><h4 class=\"mb-0\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var7 string |
|||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(util.BytesToHumanReadable(uint64(data.TotalSize))) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 91, Col: 74} |
|||
} |
|||
_, 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, "</h4><small>Data stored (regular volumes only)</small></div><div class=\"align-self-center\"><i class=\"fas fa-hdd fa-2x\"></i></div></div></div></div></div></div><!-- Size Information Note --><div class=\"alert alert-info\" role=\"alert\"><i class=\"fas fa-info-circle me-2\"></i> <strong>Size Information:</strong> Logical size represents the actual data stored (regular volumes only). EC volumes show shard counts instead of size - physical storage for EC volumes is approximately 1.4x the original data due to erasure coding redundancy.</div><!-- Pagination Info --><div class=\"d-flex justify-content-between align-items-center mb-3\"><div class=\"d-flex align-items-center\"><span class=\"me-3\">Showing ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var8 string |
|||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", (data.Page-1)*data.PageSize+1)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 115, Col: 63} |
|||
} |
|||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " to ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var9 string |
|||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", func() int { |
|||
end := data.Page * data.PageSize |
|||
totalItems := data.TotalVolumes + data.TotalEcVolumes |
|||
if end > totalItems { |
|||
return totalItems |
|||
} |
|||
return end |
|||
}())) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 122, Col: 8} |
|||
} |
|||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " of ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var10 string |
|||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalVolumes+data.TotalEcVolumes)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 122, Col: 72} |
|||
} |
|||
_, 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, 10, " items</span><div class=\"d-flex align-items-center\"><label for=\"pageSize\" class=\"form-label me-2 mb-0\">Show:</label> <select id=\"pageSize\" class=\"form-select form-select-sm\" style=\"width: auto;\" onchange=\"changePageSize(this.value)\"><option value=\"10\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.PageSize == 10 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " selected") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, ">10</option> <option value=\"25\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.PageSize == 25 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " selected") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, ">25</option> <option value=\"50\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.PageSize == 50 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " selected") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, ">50</option> <option value=\"100\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.PageSize == 100 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, " selected") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, ">100</option></select> <span class=\"ms-2\">per page</span></div></div></div><!-- Volumes Table --><div class=\"table-responsive\"><table class=\"table table-striped table-hover\" id=\"volumesTable\"><thead><tr><th><a href=\"#\" onclick=\"sortBy('volume_id')\" class=\"text-dark text-decoration-none\">Volume ID ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.SortBy == "volume_id" { |
|||
if data.SortOrder == "asc" { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<i class=\"fas fa-sort-up ms-1\"></i>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<i class=\"fas fa-sort-down ms-1\"></i>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
} else { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<i class=\"fas fa-sort ms-1 text-muted\"></i>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</a></th><th><a href=\"#\" onclick=\"sortBy('type')\" class=\"text-dark text-decoration-none\">Type ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.SortBy == "type" { |
|||
if data.SortOrder == "asc" { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<i class=\"fas fa-sort-up ms-1\"></i>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<i class=\"fas fa-sort-down ms-1\"></i>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
} else { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<i class=\"fas fa-sort ms-1 text-muted\"></i>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</a></th><th class=\"text-dark\">Logical Size / Shard Count</th><th class=\"text-dark\">Files</th><th class=\"text-dark\">Status</th><th class=\"text-dark\">Actions</th></tr></thead> <tbody>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
for _, volume := range data.RegularVolumes { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<tr><td><strong>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var11 string |
|||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", volume.Id)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 182, Col: 44} |
|||
} |
|||
_, 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, 28, "</strong></td><td><span class=\"badge bg-primary\"><i class=\"fas fa-database me-1\"></i>Regular</span></td><td>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var12 string |
|||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(util.BytesToHumanReadable(volume.Size)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 190, Col: 46} |
|||
} |
|||
_, 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, 29, "</td><td>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var13 string |
|||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", volume.FileCount)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 193, Col: 43} |
|||
} |
|||
_, 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, 30, "</td><td>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if volume.ReadOnly { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<span class=\"badge bg-warning\">Read Only</span>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<span class=\"badge bg-success\">Read/Write</span>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</td><td><div class=\"btn-group\" role=\"group\"><button type=\"button\" class=\"btn btn-sm btn-outline-primary\" onclick=\"showVolumeDetails(event)\" data-volume-id=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var14 string |
|||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", volume.Id)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 206, Col: 55} |
|||
} |
|||
_, 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, 34, "\" data-server=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var15 string |
|||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(volume.Server) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 207, Col: 37} |
|||
} |
|||
_, 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, 35, "\" title=\"View volume details\"><i class=\"fas fa-info-circle\"></i></button></div></td></tr>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
for _, ecVolume := range data.EcVolumes { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<tr><td><strong>") |
|||
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", ecVolume.VolumeID)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 220, Col: 52} |
|||
} |
|||
_, 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, 37, "</strong></td><td><span class=\"badge bg-info\"><i class=\"fas fa-th-large me-1\"></i>EC</span></td><td><span class=\"badge bg-primary\">") |
|||
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/14", ecVolume.TotalShards)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 228, Col: 81} |
|||
} |
|||
_, 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, 38, "</span></td><td><span class=\"text-muted\">-</span></td><td>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if ecVolume.IsComplete { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<span class=\"badge bg-success\"><i class=\"fas fa-check me-1\"></i>Complete</span>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<span class=\"badge bg-warning\"><i class=\"fas fa-exclamation-triangle me-1\"></i> Missing ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var18 string |
|||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(ecVolume.MissingShards))) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 241, Col: 64} |
|||
} |
|||
_, 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, 41, " shards</span>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</td><td><div class=\"btn-group\" role=\"group\"><button type=\"button\" class=\"btn btn-sm btn-outline-info\" onclick=\"showEcVolumeDetails(event)\" data-volume-id=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var19 string |
|||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", ecVolume.VolumeID)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 249, Col: 63} |
|||
} |
|||
_, 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, 43, "\" title=\"View EC volume details\"><i class=\"fas fa-info-circle\"></i></button> ") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if !ecVolume.IsComplete { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<button type=\"button\" class=\"btn btn-sm btn-outline-warning\" onclick=\"repairEcVolume(event)\" data-volume-id=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var20 string |
|||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", ecVolume.VolumeID)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 256, Col: 64} |
|||
} |
|||
_, 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, 45, "\" title=\"Repair missing shards\"><i class=\"fas fa-wrench\"></i></button>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</div></td></tr>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</tbody></table></div><!-- Pagination -->") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.TotalPages > 1 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<nav aria-label=\"Collection volumes pagination\"><ul class=\"pagination justify-content-center\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
if data.Page > 1 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"1\">First</a></li><li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"") |
|||
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.Page-1)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 278, Col: 104} |
|||
} |
|||
_, 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, 50, "\">Previous</a></li>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
for i := 1; i <= data.TotalPages; i++ { |
|||
if i == data.Page { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "<li class=\"page-item active\"><span class=\"page-link\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var22 string |
|||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 285, Col: 52} |
|||
} |
|||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</span></li>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else if i <= 3 || i > data.TotalPages-3 || (i >= data.Page-2 && i <= data.Page+2) { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var23 string |
|||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 289, Col: 95} |
|||
} |
|||
_, 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, 54, "\">") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var24 string |
|||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 289, Col: 119} |
|||
} |
|||
_, 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, 55, "</a></li>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else if i == 4 && data.Page > 6 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "<li class=\"page-item disabled\"><span class=\"page-link\">...</span></li>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} else if i == data.TotalPages-3 && data.Page < data.TotalPages-5 { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "<li class=\"page-item disabled\"><span class=\"page-link\">...</span></li>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
} |
|||
if data.Page < data.TotalPages { |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "<li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var25 string |
|||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Page+1)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 304, Col: 104} |
|||
} |
|||
_, 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, 59, "\">Next</a></li><li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
var templ_7745c5c3_Var26 string |
|||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalPages)) |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/collection_details.templ`, Line: 307, Col: 108} |
|||
} |
|||
_, 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, 60, "\">Last</a></li>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "</ul></nav>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
} |
|||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<script>\n\t\t// Sorting functionality\n\t\tfunction sortBy(field) {\n\t\t\tconst currentSort = new URLSearchParams(window.location.search).get('sort_by');\n\t\t\tconst currentOrder = new URLSearchParams(window.location.search).get('sort_order') || 'asc';\n\t\t\t\n\t\t\tlet newOrder = 'asc';\n\t\t\tif (currentSort === field && currentOrder === 'asc') {\n\t\t\t\tnewOrder = 'desc';\n\t\t\t}\n\t\t\t\n\t\t\tconst url = new URL(window.location);\n\t\t\turl.searchParams.set('sort_by', field);\n\t\t\turl.searchParams.set('sort_order', newOrder);\n\t\t\turl.searchParams.set('page', '1'); // Reset to first page\n\t\t\twindow.location.href = url.toString();\n\t\t}\n\n\t\t// Pagination functionality\n\t\tfunction goToPage(event) {\n\t\t\tevent.preventDefault();\n\t\t\tconst page = event.target.closest('a').getAttribute('data-page');\n\t\t\tconst url = new URL(window.location);\n\t\t\turl.searchParams.set('page', page);\n\t\t\twindow.location.href = url.toString();\n\t\t}\n\n\t\t// Page size functionality\n\t\tfunction changePageSize(newPageSize) {\n\t\t\tconst url = new URL(window.location);\n\t\t\turl.searchParams.set('page_size', newPageSize);\n\t\t\turl.searchParams.set('page', '1'); // Reset to first page when changing page size\n\t\t\twindow.location.href = url.toString();\n\t\t}\n\n\t\t// Volume details\n\t\tfunction showVolumeDetails(event) {\n\t\t\tconst volumeId = event.target.closest('button').getAttribute('data-volume-id');\n\t\t\tconst server = event.target.closest('button').getAttribute('data-server');\n\t\t\twindow.location.href = `/cluster/volumes/${volumeId}/${server}`;\n\t\t}\n\n\t\t// EC Volume details\n\t\tfunction showEcVolumeDetails(event) {\n\t\t\tconst volumeId = event.target.closest('button').getAttribute('data-volume-id');\n\t\t\twindow.location.href = `/cluster/ec-volumes/${volumeId}`;\n\t\t}\n\n\t\t// Repair EC Volume\n\t\tfunction repairEcVolume(event) {\n\t\t\tconst volumeId = event.target.closest('button').getAttribute('data-volume-id');\n\t\t\tif (confirm(`Are you sure you want to repair missing shards for EC volume ${volumeId}?`)) {\n\t\t\t\t// TODO: Implement repair functionality\n\t\t\t\talert('Repair functionality will be implemented soon.');\n\t\t\t}\n\t\t}\n\t</script>") |
|||
if templ_7745c5c3_Err != nil { |
|||
return templ_7745c5c3_Err |
|||
} |
|||
return nil |
|||
}) |
|||
} |
|||
|
|||
var _ = templruntime.GeneratedTemplate |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue