admin ui: filter by collection
This commit is contained in:
@@ -151,16 +151,22 @@ type ClusterVolumesData struct {
|
|||||||
DataCenterCount int `json:"datacenter_count"`
|
DataCenterCount int `json:"datacenter_count"`
|
||||||
RackCount int `json:"rack_count"`
|
RackCount int `json:"rack_count"`
|
||||||
DiskTypeCount int `json:"disk_type_count"`
|
DiskTypeCount int `json:"disk_type_count"`
|
||||||
|
CollectionCount int `json:"collection_count"`
|
||||||
|
|
||||||
// Conditional display flags
|
// Conditional display flags
|
||||||
ShowDataCenterColumn bool `json:"show_datacenter_column"`
|
ShowDataCenterColumn bool `json:"show_datacenter_column"`
|
||||||
ShowRackColumn bool `json:"show_rack_column"`
|
ShowRackColumn bool `json:"show_rack_column"`
|
||||||
ShowDiskTypeColumn bool `json:"show_disk_type_column"`
|
ShowDiskTypeColumn bool `json:"show_disk_type_column"`
|
||||||
|
ShowCollectionColumn bool `json:"show_collection_column"`
|
||||||
|
|
||||||
// Single values when only one exists
|
// Single values when only one exists
|
||||||
SingleDataCenter string `json:"single_datacenter"`
|
SingleDataCenter string `json:"single_datacenter"`
|
||||||
SingleRack string `json:"single_rack"`
|
SingleRack string `json:"single_rack"`
|
||||||
SingleDiskType string `json:"single_disk_type"`
|
SingleDiskType string `json:"single_disk_type"`
|
||||||
|
SingleCollection string `json:"single_collection"`
|
||||||
|
|
||||||
|
// Filtering
|
||||||
|
FilterCollection string `json:"filter_collection"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CollectionInfo struct {
|
type CollectionInfo struct {
|
||||||
@@ -795,8 +801,8 @@ func (s *AdminServer) GetClusterVolumeServers() (*ClusterVolumeServersData, erro
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClusterVolumes retrieves cluster volumes data with pagination and sorting
|
// GetClusterVolumes retrieves cluster volumes data with pagination, sorting, and optional collection filtering
|
||||||
func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, sortOrder string) (*ClusterVolumesData, error) {
|
func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, sortOrder string, collection string) (*ClusterVolumesData, error) {
|
||||||
// Set defaults
|
// Set defaults
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
page = 1
|
page = 1
|
||||||
@@ -812,7 +818,6 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
}
|
}
|
||||||
var volumes []VolumeInfo
|
var volumes []VolumeInfo
|
||||||
var totalSize int64
|
var totalSize int64
|
||||||
volumeID := 1
|
|
||||||
|
|
||||||
// Get detailed volume information via gRPC
|
// Get detailed volume information via gRPC
|
||||||
err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
|
err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
|
||||||
@@ -840,7 +845,7 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
volume := VolumeInfo{
|
volume := VolumeInfo{
|
||||||
ID: volumeID,
|
ID: int(volInfo.Id), // Use actual SeaweedFS volume ID
|
||||||
Server: node.Id,
|
Server: node.Id,
|
||||||
DataCenter: dc.Id,
|
DataCenter: dc.Id,
|
||||||
Rack: rack.Id,
|
Rack: rack.Id,
|
||||||
@@ -853,7 +858,6 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
}
|
}
|
||||||
volumes = append(volumes, volume)
|
volumes = append(volumes, volume)
|
||||||
totalSize += volume.Size
|
totalSize += volume.Size
|
||||||
volumeID++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -868,10 +872,25 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate unique data center, rack, and disk type counts from all volumes
|
// Filter by collection if specified
|
||||||
|
if collection != "" {
|
||||||
|
var filteredVolumes []VolumeInfo
|
||||||
|
var filteredTotalSize int64
|
||||||
|
for _, volume := range volumes {
|
||||||
|
if volume.Collection == collection {
|
||||||
|
filteredVolumes = append(filteredVolumes, volume)
|
||||||
|
filteredTotalSize += volume.Size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volumes = filteredVolumes
|
||||||
|
totalSize = filteredTotalSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate unique data center, rack, disk type, and collection counts from all volumes
|
||||||
dataCenterMap := make(map[string]bool)
|
dataCenterMap := make(map[string]bool)
|
||||||
rackMap := make(map[string]bool)
|
rackMap := make(map[string]bool)
|
||||||
diskTypeMap := make(map[string]bool)
|
diskTypeMap := make(map[string]bool)
|
||||||
|
collectionMap := make(map[string]bool)
|
||||||
for _, volume := range volumes {
|
for _, volume := range volumes {
|
||||||
if volume.DataCenter != "" {
|
if volume.DataCenter != "" {
|
||||||
dataCenterMap[volume.DataCenter] = true
|
dataCenterMap[volume.DataCenter] = true
|
||||||
@@ -884,10 +903,14 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
diskType = "hdd" // Default to hdd if not specified
|
diskType = "hdd" // Default to hdd if not specified
|
||||||
}
|
}
|
||||||
diskTypeMap[diskType] = true
|
diskTypeMap[diskType] = true
|
||||||
|
if volume.Collection != "" {
|
||||||
|
collectionMap[volume.Collection] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dataCenterCount := len(dataCenterMap)
|
dataCenterCount := len(dataCenterMap)
|
||||||
rackCount := len(rackMap)
|
rackCount := len(rackMap)
|
||||||
diskTypeCount := len(diskTypeMap)
|
diskTypeCount := len(diskTypeMap)
|
||||||
|
collectionCount := len(collectionMap)
|
||||||
|
|
||||||
// Sort volumes
|
// Sort volumes
|
||||||
s.sortVolumes(volumes, sortBy, sortOrder)
|
s.sortVolumes(volumes, sortBy, sortOrder)
|
||||||
@@ -915,8 +938,9 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
showDataCenterColumn := dataCenterCount > 1
|
showDataCenterColumn := dataCenterCount > 1
|
||||||
showRackColumn := rackCount > 1
|
showRackColumn := rackCount > 1
|
||||||
showDiskTypeColumn := diskTypeCount > 1
|
showDiskTypeColumn := diskTypeCount > 1
|
||||||
|
showCollectionColumn := collectionCount > 1 && collection == "" // Hide column when filtering by collection
|
||||||
|
|
||||||
var singleDataCenter, singleRack, singleDiskType string
|
var singleDataCenter, singleRack, singleDiskType, singleCollection string
|
||||||
if dataCenterCount == 1 {
|
if dataCenterCount == 1 {
|
||||||
for dc := range dataCenterMap {
|
for dc := range dataCenterMap {
|
||||||
singleDataCenter = dc
|
singleDataCenter = dc
|
||||||
@@ -935,6 +959,12 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if collectionCount == 1 {
|
||||||
|
for collection := range collectionMap {
|
||||||
|
singleCollection = collection
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &ClusterVolumesData{
|
return &ClusterVolumesData{
|
||||||
Volumes: volumes,
|
Volumes: volumes,
|
||||||
@@ -949,12 +979,16 @@ func (s *AdminServer) GetClusterVolumes(page int, pageSize int, sortBy string, s
|
|||||||
DataCenterCount: dataCenterCount,
|
DataCenterCount: dataCenterCount,
|
||||||
RackCount: rackCount,
|
RackCount: rackCount,
|
||||||
DiskTypeCount: diskTypeCount,
|
DiskTypeCount: diskTypeCount,
|
||||||
|
CollectionCount: collectionCount,
|
||||||
ShowDataCenterColumn: showDataCenterColumn,
|
ShowDataCenterColumn: showDataCenterColumn,
|
||||||
ShowRackColumn: showRackColumn,
|
ShowRackColumn: showRackColumn,
|
||||||
ShowDiskTypeColumn: showDiskTypeColumn,
|
ShowDiskTypeColumn: showDiskTypeColumn,
|
||||||
|
ShowCollectionColumn: showCollectionColumn,
|
||||||
SingleDataCenter: singleDataCenter,
|
SingleDataCenter: singleDataCenter,
|
||||||
SingleRack: singleRack,
|
SingleRack: singleRack,
|
||||||
SingleDiskType: singleDiskType,
|
SingleDiskType: singleDiskType,
|
||||||
|
SingleCollection: singleCollection,
|
||||||
|
FilterCollection: collection,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,9 +68,10 @@ func (h *ClusterHandlers) ShowClusterVolumes(c *gin.Context) {
|
|||||||
|
|
||||||
sortBy := c.DefaultQuery("sortBy", "id")
|
sortBy := c.DefaultQuery("sortBy", "id")
|
||||||
sortOrder := c.DefaultQuery("sortOrder", "asc")
|
sortOrder := c.DefaultQuery("sortOrder", "asc")
|
||||||
|
collection := c.Query("collection") // Optional collection filter
|
||||||
|
|
||||||
// Get cluster volumes data
|
// Get cluster volumes data
|
||||||
volumesData, err := h.adminServer.GetClusterVolumes(page, pageSize, sortBy, sortOrder)
|
volumesData, err := h.adminServer.GetClusterVolumes(page, pageSize, sortBy, sortOrder, collection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get cluster volumes: " + err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get cluster volumes: " + err.Error()})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -131,13 +131,17 @@ templ ClusterCollections(data dash.ClusterCollectionsData) {
|
|||||||
for _, collection := range data.Collections {
|
for _, collection := range data.Collections {
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<strong>{collection.Name}</strong>
|
<a href={templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name))} class="text-decoration-none">
|
||||||
|
<strong>{collection.Name}</strong>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex align-items-center">
|
<a href={templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name))} class="text-decoration-none">
|
||||||
<i class="fas fa-database me-2 text-muted"></i>
|
<div class="d-flex align-items-center">
|
||||||
{fmt.Sprintf("%d", collection.VolumeCount)}
|
<i class="fas fa-database me-2 text-muted"></i>
|
||||||
</div>
|
{fmt.Sprintf("%d", collection.VolumeCount)}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
|
|||||||
@@ -96,157 +96,175 @@ func ClusterCollections(data dash.ClusterCollectionsData) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for _, collection := range data.Collections {
|
for _, collection := range data.Collections {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<tr><td><strong>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<tr><td><a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var6 string
|
var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name))
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 134, Col: 68}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</strong></td><td><div class=\"d-flex align-items-center\"><i class=\"fas fa-database me-2 text-muted\"></i> ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" class=\"text-decoration-none\"><strong>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", collection.VolumeCount))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 139, Col: 90}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 135, Col: 72}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></td><td><div class=\"d-flex align-items-center\"><i class=\"fas fa-file me-2 text-muted\"></i> ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</strong></a></td><td><a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name))
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", collection.FileCount))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 145, Col: 88}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div></td><td><div class=\"d-flex align-items-center\"><i class=\"fas fa-hdd me-2 text-muted\"></i> ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" class=\"text-decoration-none\"><div class=\"d-flex align-items-center\"><i class=\"fas fa-database me-2 text-muted\"></i> ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(collection.TotalSize))
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", collection.VolumeCount))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 151, Col: 82}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 142, Col: 94}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></td><td>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></a></td><td><div class=\"d-flex align-items-center\"><i class=\"fas fa-file me-2 text-muted\"></i> ")
|
||||||
|
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", collection.FileCount))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 149, Col: 88}
|
||||||
|
}
|
||||||
|
_, 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, "</div></td><td><div class=\"d-flex align-items-center\"><i class=\"fas fa-hdd me-2 text-muted\"></i> ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var11 string
|
||||||
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(collection.TotalSize))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 155, Col: 82}
|
||||||
|
}
|
||||||
|
_, 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, 13, "</div></td><td>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for i, diskType := range collection.DiskTypes {
|
for i, diskType := range collection.DiskTypes {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<span class=\"me-1\"></span>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<span class=\"me-1\"></span>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var10 = []any{fmt.Sprintf("badge bg-%s me-1", getDiskTypeColor(diskType))}
|
var templ_7745c5c3_Var12 = []any{fmt.Sprintf("badge bg-%s me-1", getDiskTypeColor(diskType))}
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<span class=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<span class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var11 string
|
var templ_7745c5c3_Var13 string
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var10).String())
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 1, Col: 0}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var12 string
|
var templ_7745c5c3_Var14 string
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(diskType)
|
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(diskType)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 159, Col: 131}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 163, Col: 131}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span> ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</span> ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(collection.DiskTypes) == 0 {
|
if len(collection.DiskTypes) == 0 {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<span class=\"text-muted\">Unknown</span>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<span class=\"text-muted\">Unknown</span>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</td><td><div class=\"btn-group btn-group-sm\"><button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"View Details\"><i class=\"fas fa-eye\"></i></button> <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" title=\"Edit\"><i class=\"fas fa-edit\"></i></button> <button type=\"button\" class=\"btn btn-outline-danger btn-sm\" title=\"Delete\" data-collection-name=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</td><td><div class=\"btn-group btn-group-sm\"><button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"View Details\"><i class=\"fas fa-eye\"></i></button> <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" title=\"Edit\"><i class=\"fas fa-edit\"></i></button> <button type=\"button\" class=\"btn btn-outline-danger btn-sm\" title=\"Delete\" data-collection-name=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var13 string
|
var templ_7745c5c3_Var15 string
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 177, Col: 93}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 181, Col: 93}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" onclick=\"confirmDeleteCollection(this)\"><i class=\"fas fa-trash\"></i></button></div></td></tr>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" onclick=\"confirmDeleteCollection(this)\"><i class=\"fas fa-trash\"></i></button></div></td></tr>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</tbody></table></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</tbody></table></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"text-center py-5\"><i class=\"fas fa-layer-group fa-3x text-muted mb-3\"></i><h5 class=\"text-muted\">No Collections Found</h5><p class=\"text-muted\">No collections are currently configured in the cluster.</p><button type=\"button\" class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#createCollectionModal\"><i class=\"fas fa-plus me-2\"></i>Create First Collection</button></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<div class=\"text-center py-5\"><i class=\"fas fa-layer-group fa-3x text-muted mb-3\"></i><h5 class=\"text-muted\">No Collections Found</h5><p class=\"text-muted\">No collections are currently configured in the cluster.</p><button type=\"button\" class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#createCollectionModal\"><i class=\"fas fa-plus me-2\"></i>Create First Collection</button></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</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: ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var14 string
|
var templ_7745c5c3_Var16 string
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
|
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 206, Col: 81}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 210, Col: 81}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</small></div></div></div><!-- Create Collection Modal --><div class=\"modal fade\" id=\"createCollectionModal\" tabindex=\"-1\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-plus me-2\"></i>Create New Collection</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><form id=\"createCollectionForm\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"collectionName\" class=\"form-label\">Collection Name</label> <input type=\"text\" class=\"form-control\" id=\"collectionName\" name=\"name\" required><div class=\"form-text\">Enter a unique name for the collection</div></div><div class=\"mb-3\"><label for=\"replication\" class=\"form-label\">Replication</label> <select class=\"form-select\" id=\"replication\" name=\"replication\" required><option value=\"000\">000 - No replication</option> <option value=\"001\" selected>001 - Replicate once on same rack</option> <option value=\"010\">010 - Replicate once on different rack</option> <option value=\"100\">100 - Replicate once on different data center</option> <option value=\"200\">200 - Replicate twice on different data centers</option></select></div><div class=\"mb-3\"><label for=\"ttl\" class=\"form-label\">TTL (Time To Live)</label> <input type=\"text\" class=\"form-control\" id=\"ttl\" name=\"ttl\" placeholder=\"e.g., 1d, 7d, 30d\"><div class=\"form-text\">Optional: Specify how long files should be kept</div></div><div class=\"mb-3\"><label for=\"diskType\" class=\"form-label\">Disk Type</label> <select class=\"form-select\" id=\"diskType\" name=\"diskType\"><option value=\"hdd\" selected>HDD</option> <option value=\"ssd\">SSD</option></select></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Create Collection</button></div></form></div></div></div><!-- Delete Confirmation Modal --><div class=\"modal fade\" id=\"deleteCollectionModal\" tabindex=\"-1\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title text-danger\"><i class=\"fas fa-exclamation-triangle me-2\"></i>Delete Collection</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><p>Are you sure you want to delete the collection <strong id=\"deleteCollectionName\"></strong>?</p><div class=\"alert alert-warning\"><i class=\"fas fa-warning me-2\"></i> This action cannot be undone. All volumes in this collection will be affected.</div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-danger\" id=\"confirmDeleteCollection\">Delete Collection</button></div></div></div></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</small></div></div></div><!-- Create Collection Modal --><div class=\"modal fade\" id=\"createCollectionModal\" tabindex=\"-1\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-plus me-2\"></i>Create New Collection</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><form id=\"createCollectionForm\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"collectionName\" class=\"form-label\">Collection Name</label> <input type=\"text\" class=\"form-control\" id=\"collectionName\" name=\"name\" required><div class=\"form-text\">Enter a unique name for the collection</div></div><div class=\"mb-3\"><label for=\"replication\" class=\"form-label\">Replication</label> <select class=\"form-select\" id=\"replication\" name=\"replication\" required><option value=\"000\">000 - No replication</option> <option value=\"001\" selected>001 - Replicate once on same rack</option> <option value=\"010\">010 - Replicate once on different rack</option> <option value=\"100\">100 - Replicate once on different data center</option> <option value=\"200\">200 - Replicate twice on different data centers</option></select></div><div class=\"mb-3\"><label for=\"ttl\" class=\"form-label\">TTL (Time To Live)</label> <input type=\"text\" class=\"form-control\" id=\"ttl\" name=\"ttl\" placeholder=\"e.g., 1d, 7d, 30d\"><div class=\"form-text\">Optional: Specify how long files should be kept</div></div><div class=\"mb-3\"><label for=\"diskType\" class=\"form-label\">Disk Type</label> <select class=\"form-select\" id=\"diskType\" name=\"diskType\"><option value=\"hdd\" selected>HDD</option> <option value=\"ssd\">SSD</option></select></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Create Collection</button></div></form></div></div></div><!-- Delete Confirmation Modal --><div class=\"modal fade\" id=\"deleteCollectionModal\" tabindex=\"-1\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title text-danger\"><i class=\"fas fa-exclamation-triangle me-2\"></i>Delete Collection</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><p>Are you sure you want to delete the collection <strong id=\"deleteCollectionName\"></strong>?</p><div class=\"alert alert-warning\"><i class=\"fas fa-warning me-2\"></i> This action cannot be undone. All volumes in this collection will be affected.</div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-danger\" id=\"confirmDeleteCollection\">Delete Collection</button></div></div></div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,21 @@ import (
|
|||||||
|
|
||||||
templ ClusterVolumes(data dash.ClusterVolumesData) {
|
templ ClusterVolumes(data dash.ClusterVolumesData) {
|
||||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||||
<h1 class="h2">
|
<div>
|
||||||
<i class="fas fa-database me-2"></i>Cluster Volumes
|
<h1 class="h2">
|
||||||
</h1>
|
<i class="fas fa-database me-2"></i>Cluster Volumes
|
||||||
|
</h1>
|
||||||
|
if data.FilterCollection != "" {
|
||||||
|
<div class="d-flex align-items-center mt-2">
|
||||||
|
<span class="badge bg-info me-2">
|
||||||
|
<i class="fas fa-filter me-1"></i>Collection: {data.FilterCollection}
|
||||||
|
</span>
|
||||||
|
<a href="/cluster/volumes" class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="fas fa-times me-1"></i>Clear Filter
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<div class="btn-toolbar mb-2 mb-md-0">
|
<div class="btn-toolbar mb-2 mb-md-0">
|
||||||
<div class="btn-group me-2">
|
<div class="btn-group me-2">
|
||||||
<select class="form-select form-select-sm me-2" id="pageSizeSelect" onchange="changePageSize()" style="width: auto;">
|
<select class="form-select form-select-sm me-2" id="pageSizeSelect" onchange="changePageSize()" style="width: auto;">
|
||||||
@@ -54,10 +66,18 @@ templ ClusterVolumes(data dash.ClusterVolumesData) {
|
|||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
<div class="col mr-2">
|
<div class="col mr-2">
|
||||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
||||||
Collections
|
if data.CollectionCount == 1 {
|
||||||
|
Collection
|
||||||
|
} else {
|
||||||
|
Collections
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800">
|
<div class="h5 mb-0 font-weight-bold text-gray-800">
|
||||||
{fmt.Sprintf("%d", countUniqueCollections(data.Volumes))}
|
if data.CollectionCount == 1 {
|
||||||
|
{data.SingleCollection}
|
||||||
|
} else {
|
||||||
|
{fmt.Sprintf("%d", data.CollectionCount)}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
@@ -214,12 +234,14 @@ templ ClusterVolumes(data dash.ClusterVolumesData) {
|
|||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
}
|
}
|
||||||
<th>
|
if data.ShowCollectionColumn {
|
||||||
<a href="#" onclick="sortTable('collection')" class="text-decoration-none text-dark">
|
<th>
|
||||||
Collection
|
<a href="#" onclick="sortTable('collection')" class="text-decoration-none text-dark">
|
||||||
@getSortIcon("collection", data.SortBy, data.SortOrder)
|
Collection
|
||||||
</a>
|
@getSortIcon("collection", data.SortBy, data.SortOrder)
|
||||||
</th>
|
</a>
|
||||||
|
</th>
|
||||||
|
}
|
||||||
<th>
|
<th>
|
||||||
<a href="#" onclick="sortTable('size')" class="text-decoration-none text-dark">
|
<a href="#" onclick="sortTable('size')" class="text-decoration-none text-dark">
|
||||||
Size
|
Size
|
||||||
@@ -271,9 +293,11 @@ templ ClusterVolumes(data dash.ClusterVolumesData) {
|
|||||||
<span class="badge bg-light text-dark">{volume.Rack}</span>
|
<span class="badge bg-light text-dark">{volume.Rack}</span>
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
<td>
|
if data.ShowCollectionColumn {
|
||||||
<span class="badge bg-secondary">{volume.Collection}</span>
|
<td>
|
||||||
</td>
|
<span class="badge bg-secondary">{volume.Collection}</span>
|
||||||
|
</td>
|
||||||
|
}
|
||||||
<td>{formatBytes(volume.Size)}</td>
|
<td>{formatBytes(volume.Size)}</td>
|
||||||
<td>{fmt.Sprintf("%d", volume.FileCount)}</td>
|
<td>{fmt.Sprintf("%d", volume.FileCount)}</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -485,15 +509,7 @@ func countUniqueDiskTypes(volumes []dash.VolumeInfo) int {
|
|||||||
return len(diskTypeMap)
|
return len(diskTypeMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func countUniqueCollections(volumes []dash.VolumeInfo) int {
|
|
||||||
collectionMap := make(map[string]bool)
|
|
||||||
for _, volume := range volumes {
|
|
||||||
if volume.Collection != "" {
|
|
||||||
collectionMap[volume.Collection] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(collectionMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
templ getSortIcon(column, currentSort, currentOrder string) {
|
templ getSortIcon(column, currentSort, currentOrder string) {
|
||||||
if column != currentSort {
|
if column != currentSort {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user