cluster_ec_volumes_templ.go 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  1. // Code generated by templ - DO NOT EDIT.
  2. // templ: version: v0.3.906
  3. package app
  4. //lint:file-ignore SA4006 This context is only used if a nested component is present.
  5. import "github.com/a-h/templ"
  6. import templruntime "github.com/a-h/templ/runtime"
  7. import (
  8. "fmt"
  9. "github.com/seaweedfs/seaweedfs/weed/admin/dash"
  10. "github.com/seaweedfs/seaweedfs/weed/storage/erasure_coding"
  11. "strings"
  12. )
  13. func ClusterEcVolumes(data dash.ClusterEcVolumesData) templ.Component {
  14. return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
  15. templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
  16. if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
  17. return templ_7745c5c3_CtxErr
  18. }
  19. templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
  20. if !templ_7745c5c3_IsBuffer {
  21. defer func() {
  22. templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
  23. if templ_7745c5c3_Err == nil {
  24. templ_7745c5c3_Err = templ_7745c5c3_BufErr
  25. }
  26. }()
  27. }
  28. ctx = templ.InitializeContext(ctx)
  29. templ_7745c5c3_Var1 := templ.GetChildren(ctx)
  30. if templ_7745c5c3_Var1 == nil {
  31. templ_7745c5c3_Var1 = templ.NopComponent
  32. }
  33. ctx = templ.ClearChildren(ctx)
  34. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><title>EC Volumes - SeaweedFS</title><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css\" rel=\"stylesheet\"><link href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\" rel=\"stylesheet\"></head><body><div class=\"container-fluid\"><div class=\"row\"><div class=\"col-12\"><h2 class=\"mb-4\"><i class=\"fas fa-database me-2\"></i>EC Volumes <small class=\"text-muted\">(")
  35. if templ_7745c5c3_Err != nil {
  36. return templ_7745c5c3_Err
  37. }
  38. var templ_7745c5c3_Var2 string
  39. templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalVolumes))
  40. if templ_7745c5c3_Err != nil {
  41. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 26, Col: 84}
  42. }
  43. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
  44. if templ_7745c5c3_Err != nil {
  45. return templ_7745c5c3_Err
  46. }
  47. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " volumes)</small></h2></div></div><!-- Statistics Cards --><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\">Total Volumes</h6><h4 class=\"mb-0\">")
  48. if templ_7745c5c3_Err != nil {
  49. return templ_7745c5c3_Err
  50. }
  51. var templ_7745c5c3_Var3 string
  52. templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalVolumes))
  53. if templ_7745c5c3_Err != nil {
  54. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 39, Col: 86}
  55. }
  56. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
  57. if templ_7745c5c3_Err != nil {
  58. return templ_7745c5c3_Err
  59. }
  60. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h4><small>EC encoded volumes</small></div><div class=\"align-self-center\"><i class=\"fas fa-cubes 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\">Total Shards</h6><h4 class=\"mb-0\">")
  61. if templ_7745c5c3_Err != nil {
  62. return templ_7745c5c3_Err
  63. }
  64. var templ_7745c5c3_Var4 string
  65. templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalShards))
  66. if templ_7745c5c3_Err != nil {
  67. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 55, Col: 85}
  68. }
  69. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
  70. if templ_7745c5c3_Err != nil {
  71. return templ_7745c5c3_Err
  72. }
  73. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</h4><small>Distributed shards</small></div><div class=\"align-self-center\"><i class=\"fas fa-puzzle-piece 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\">Complete Volumes</h6><h4 class=\"mb-0\">")
  74. if templ_7745c5c3_Err != nil {
  75. return templ_7745c5c3_Err
  76. }
  77. var templ_7745c5c3_Var5 string
  78. templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.CompleteVolumes))
  79. if templ_7745c5c3_Err != nil {
  80. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 71, Col: 89}
  81. }
  82. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
  83. if templ_7745c5c3_Err != nil {
  84. return templ_7745c5c3_Err
  85. }
  86. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</h4><small>All shards present</small></div><div class=\"align-self-center\"><i class=\"fas fa-check-circle 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\">Incomplete Volumes</h6><h4 class=\"mb-0\">")
  87. if templ_7745c5c3_Err != nil {
  88. return templ_7745c5c3_Err
  89. }
  90. var templ_7745c5c3_Var6 string
  91. templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.IncompleteVolumes))
  92. if templ_7745c5c3_Err != nil {
  93. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 87, Col: 91}
  94. }
  95. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
  96. if templ_7745c5c3_Err != nil {
  97. return templ_7745c5c3_Err
  98. }
  99. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</h4><small>Missing shards</small></div><div class=\"align-self-center\"><i class=\"fas fa-exclamation-triangle fa-2x\"></i></div></div></div></div></div></div><!-- EC Storage Information Note --><div class=\"alert alert-info mb-4\" role=\"alert\"><i class=\"fas fa-info-circle me-2\"></i> <strong>EC Storage Note:</strong> EC volumes use erasure coding (")
  100. if templ_7745c5c3_Err != nil {
  101. return templ_7745c5c3_Err
  102. }
  103. var templ_7745c5c3_Var7 string
  104. templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d+%d", erasure_coding.DataShardsCount, erasure_coding.ParityShardsCount))
  105. if templ_7745c5c3_Err != nil {
  106. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 103, Col: 131}
  107. }
  108. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
  109. if templ_7745c5c3_Err != nil {
  110. return templ_7745c5c3_Err
  111. }
  112. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, ") which stores data across ")
  113. if templ_7745c5c3_Err != nil {
  114. return templ_7745c5c3_Err
  115. }
  116. var templ_7745c5c3_Var8 string
  117. templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", erasure_coding.TotalShardsCount))
  118. if templ_7745c5c3_Err != nil {
  119. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 103, Col: 212}
  120. }
  121. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
  122. if templ_7745c5c3_Err != nil {
  123. return templ_7745c5c3_Err
  124. }
  125. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " shards with redundancy. Physical storage is approximately ")
  126. if templ_7745c5c3_Err != nil {
  127. return templ_7745c5c3_Err
  128. }
  129. var templ_7745c5c3_Var9 string
  130. templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1fx", float64(erasure_coding.TotalShardsCount)/float64(erasure_coding.DataShardsCount)))
  131. if templ_7745c5c3_Err != nil {
  132. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 104, Col: 150}
  133. }
  134. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
  135. if templ_7745c5c3_Err != nil {
  136. return templ_7745c5c3_Err
  137. }
  138. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " the original logical data size due to ")
  139. if templ_7745c5c3_Err != nil {
  140. return templ_7745c5c3_Err
  141. }
  142. var templ_7745c5c3_Var10 string
  143. templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", erasure_coding.ParityShardsCount))
  144. if templ_7745c5c3_Err != nil {
  145. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 104, Col: 244}
  146. }
  147. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
  148. if templ_7745c5c3_Err != nil {
  149. return templ_7745c5c3_Err
  150. }
  151. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " parity shards.</div><!-- Volumes Table --><div class=\"d-flex justify-content-between align-items-center mb-3\"><div class=\"d-flex align-items-center\"><span class=\"me-3\">Showing ")
  152. if templ_7745c5c3_Err != nil {
  153. return templ_7745c5c3_Err
  154. }
  155. var templ_7745c5c3_Var11 string
  156. templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", (data.Page-1)*data.PageSize+1))
  157. if templ_7745c5c3_Err != nil {
  158. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 111, Col: 79}
  159. }
  160. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
  161. if templ_7745c5c3_Err != nil {
  162. return templ_7745c5c3_Err
  163. }
  164. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " to ")
  165. if templ_7745c5c3_Err != nil {
  166. return templ_7745c5c3_Err
  167. }
  168. var templ_7745c5c3_Var12 string
  169. templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", func() int {
  170. end := data.Page * data.PageSize
  171. if end > data.TotalVolumes {
  172. return data.TotalVolumes
  173. }
  174. return end
  175. }()))
  176. if templ_7745c5c3_Err != nil {
  177. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 117, Col: 24}
  178. }
  179. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
  180. if templ_7745c5c3_Err != nil {
  181. return templ_7745c5c3_Err
  182. }
  183. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, " of ")
  184. if templ_7745c5c3_Err != nil {
  185. return templ_7745c5c3_Err
  186. }
  187. var templ_7745c5c3_Var13 string
  188. templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalVolumes))
  189. if templ_7745c5c3_Err != nil {
  190. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 117, Col: 66}
  191. }
  192. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
  193. if templ_7745c5c3_Err != nil {
  194. return templ_7745c5c3_Err
  195. }
  196. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " volumes</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=\"5\"")
  197. if templ_7745c5c3_Err != nil {
  198. return templ_7745c5c3_Err
  199. }
  200. if data.PageSize == 5 {
  201. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " selected")
  202. if templ_7745c5c3_Err != nil {
  203. return templ_7745c5c3_Err
  204. }
  205. }
  206. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, ">5</option> <option value=\"10\"")
  207. if templ_7745c5c3_Err != nil {
  208. return templ_7745c5c3_Err
  209. }
  210. if data.PageSize == 10 {
  211. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, " selected")
  212. if templ_7745c5c3_Err != nil {
  213. return templ_7745c5c3_Err
  214. }
  215. }
  216. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, ">10</option> <option value=\"25\"")
  217. if templ_7745c5c3_Err != nil {
  218. return templ_7745c5c3_Err
  219. }
  220. if data.PageSize == 25 {
  221. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " selected")
  222. if templ_7745c5c3_Err != nil {
  223. return templ_7745c5c3_Err
  224. }
  225. }
  226. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, ">25</option> <option value=\"50\"")
  227. if templ_7745c5c3_Err != nil {
  228. return templ_7745c5c3_Err
  229. }
  230. if data.PageSize == 50 {
  231. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " selected")
  232. if templ_7745c5c3_Err != nil {
  233. return templ_7745c5c3_Err
  234. }
  235. }
  236. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, ">50</option> <option value=\"100\"")
  237. if templ_7745c5c3_Err != nil {
  238. return templ_7745c5c3_Err
  239. }
  240. if data.PageSize == 100 {
  241. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, " selected")
  242. if templ_7745c5c3_Err != nil {
  243. return templ_7745c5c3_Err
  244. }
  245. }
  246. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, ">100</option></select> <span class=\"ms-2\">per page</span></div></div>")
  247. if templ_7745c5c3_Err != nil {
  248. return templ_7745c5c3_Err
  249. }
  250. if data.Collection != "" {
  251. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<div>")
  252. if templ_7745c5c3_Err != nil {
  253. return templ_7745c5c3_Err
  254. }
  255. if data.Collection == "default" {
  256. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<span class=\"badge bg-secondary text-white\">Collection: default</span> ")
  257. if templ_7745c5c3_Err != nil {
  258. return templ_7745c5c3_Err
  259. }
  260. } else {
  261. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<span class=\"badge bg-info text-white\">Collection: ")
  262. if templ_7745c5c3_Err != nil {
  263. return templ_7745c5c3_Err
  264. }
  265. var templ_7745c5c3_Var14 string
  266. templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(data.Collection)
  267. if templ_7745c5c3_Err != nil {
  268. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 138, Col: 91}
  269. }
  270. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
  271. if templ_7745c5c3_Err != nil {
  272. return templ_7745c5c3_Err
  273. }
  274. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</span> ")
  275. if templ_7745c5c3_Err != nil {
  276. return templ_7745c5c3_Err
  277. }
  278. }
  279. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<a href=\"/cluster/ec-shards\" class=\"btn btn-sm btn-outline-secondary ms-2\">Clear Filter</a></div>")
  280. if templ_7745c5c3_Err != nil {
  281. return templ_7745c5c3_Err
  282. }
  283. }
  284. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</div><div class=\"table-responsive\"><table class=\"table table-striped table-hover\" id=\"ecVolumesTable\"><thead><tr><th><a href=\"#\" onclick=\"sortBy('volume_id')\" class=\"text-dark text-decoration-none\">Volume ID ")
  285. if templ_7745c5c3_Err != nil {
  286. return templ_7745c5c3_Err
  287. }
  288. if data.SortBy == "volume_id" {
  289. if data.SortOrder == "asc" {
  290. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<i class=\"fas fa-sort-up ms-1\"></i>")
  291. if templ_7745c5c3_Err != nil {
  292. return templ_7745c5c3_Err
  293. }
  294. } else {
  295. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<i class=\"fas fa-sort-down ms-1\"></i>")
  296. if templ_7745c5c3_Err != nil {
  297. return templ_7745c5c3_Err
  298. }
  299. }
  300. } else {
  301. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<i class=\"fas fa-sort ms-1 text-muted\"></i>")
  302. if templ_7745c5c3_Err != nil {
  303. return templ_7745c5c3_Err
  304. }
  305. }
  306. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</a></th>")
  307. if templ_7745c5c3_Err != nil {
  308. return templ_7745c5c3_Err
  309. }
  310. if data.ShowCollectionColumn {
  311. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "<th><a href=\"#\" onclick=\"sortBy('collection')\" class=\"text-dark text-decoration-none\">Collection ")
  312. if templ_7745c5c3_Err != nil {
  313. return templ_7745c5c3_Err
  314. }
  315. if data.SortBy == "collection" {
  316. if data.SortOrder == "asc" {
  317. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<i class=\"fas fa-sort-up ms-1\"></i>")
  318. if templ_7745c5c3_Err != nil {
  319. return templ_7745c5c3_Err
  320. }
  321. } else {
  322. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<i class=\"fas fa-sort-down ms-1\"></i>")
  323. if templ_7745c5c3_Err != nil {
  324. return templ_7745c5c3_Err
  325. }
  326. }
  327. } else {
  328. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<i class=\"fas fa-sort ms-1 text-muted\"></i>")
  329. if templ_7745c5c3_Err != nil {
  330. return templ_7745c5c3_Err
  331. }
  332. }
  333. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</a></th>")
  334. if templ_7745c5c3_Err != nil {
  335. return templ_7745c5c3_Err
  336. }
  337. }
  338. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<th><a href=\"#\" onclick=\"sortBy('total_shards')\" class=\"text-dark text-decoration-none\">Shard Count ")
  339. if templ_7745c5c3_Err != nil {
  340. return templ_7745c5c3_Err
  341. }
  342. if data.SortBy == "total_shards" {
  343. if data.SortOrder == "asc" {
  344. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<i class=\"fas fa-sort-up ms-1\"></i>")
  345. if templ_7745c5c3_Err != nil {
  346. return templ_7745c5c3_Err
  347. }
  348. } else {
  349. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<i class=\"fas fa-sort-down ms-1\"></i>")
  350. if templ_7745c5c3_Err != nil {
  351. return templ_7745c5c3_Err
  352. }
  353. }
  354. } else {
  355. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<i class=\"fas fa-sort ms-1 text-muted\"></i>")
  356. if templ_7745c5c3_Err != nil {
  357. return templ_7745c5c3_Err
  358. }
  359. }
  360. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</a></th><th class=\"text-dark\">Shard Size</th><th class=\"text-dark\">Shard Locations</th><th><a href=\"#\" onclick=\"sortBy('completeness')\" class=\"text-dark text-decoration-none\">Status ")
  361. if templ_7745c5c3_Err != nil {
  362. return templ_7745c5c3_Err
  363. }
  364. if data.SortBy == "completeness" {
  365. if data.SortOrder == "asc" {
  366. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<i class=\"fas fa-sort-up ms-1\"></i>")
  367. if templ_7745c5c3_Err != nil {
  368. return templ_7745c5c3_Err
  369. }
  370. } else {
  371. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<i class=\"fas fa-sort-down ms-1\"></i>")
  372. if templ_7745c5c3_Err != nil {
  373. return templ_7745c5c3_Err
  374. }
  375. }
  376. } else {
  377. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<i class=\"fas fa-sort ms-1 text-muted\"></i>")
  378. if templ_7745c5c3_Err != nil {
  379. return templ_7745c5c3_Err
  380. }
  381. }
  382. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</a></th>")
  383. if templ_7745c5c3_Err != nil {
  384. return templ_7745c5c3_Err
  385. }
  386. if data.ShowDataCenterColumn {
  387. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<th class=\"text-dark\">Data Centers</th>")
  388. if templ_7745c5c3_Err != nil {
  389. return templ_7745c5c3_Err
  390. }
  391. }
  392. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<th class=\"text-dark\">Actions</th></tr></thead> <tbody>")
  393. if templ_7745c5c3_Err != nil {
  394. return templ_7745c5c3_Err
  395. }
  396. for _, volume := range data.EcVolumes {
  397. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "<tr><td><strong>")
  398. if templ_7745c5c3_Err != nil {
  399. return templ_7745c5c3_Err
  400. }
  401. var templ_7745c5c3_Var15 string
  402. templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", volume.VolumeID))
  403. if templ_7745c5c3_Err != nil {
  404. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 219, Col: 75}
  405. }
  406. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
  407. if templ_7745c5c3_Err != nil {
  408. return templ_7745c5c3_Err
  409. }
  410. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</strong></td>")
  411. if templ_7745c5c3_Err != nil {
  412. return templ_7745c5c3_Err
  413. }
  414. if data.ShowCollectionColumn {
  415. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "<td>")
  416. if templ_7745c5c3_Err != nil {
  417. return templ_7745c5c3_Err
  418. }
  419. if volume.Collection != "" {
  420. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<a href=\"/cluster/ec-shards?collection={volume.Collection}\" class=\"text-decoration-none\"><span class=\"badge bg-info text-white\">")
  421. if templ_7745c5c3_Err != nil {
  422. return templ_7745c5c3_Err
  423. }
  424. var templ_7745c5c3_Var16 string
  425. templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(volume.Collection)
  426. if templ_7745c5c3_Err != nil {
  427. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 225, Col: 101}
  428. }
  429. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
  430. if templ_7745c5c3_Err != nil {
  431. return templ_7745c5c3_Err
  432. }
  433. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "</span></a>")
  434. if templ_7745c5c3_Err != nil {
  435. return templ_7745c5c3_Err
  436. }
  437. } else {
  438. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "<a href=\"/cluster/ec-shards?collection=default\" class=\"text-decoration-none\"><span class=\"badge bg-secondary text-white\">default</span></a>")
  439. if templ_7745c5c3_Err != nil {
  440. return templ_7745c5c3_Err
  441. }
  442. }
  443. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</td>")
  444. if templ_7745c5c3_Err != nil {
  445. return templ_7745c5c3_Err
  446. }
  447. }
  448. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "<td><span class=\"badge bg-primary\">")
  449. if templ_7745c5c3_Err != nil {
  450. return templ_7745c5c3_Err
  451. }
  452. var templ_7745c5c3_Var17 string
  453. templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/14", volume.TotalShards))
  454. if templ_7745c5c3_Err != nil {
  455. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 235, Col: 104}
  456. }
  457. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
  458. if templ_7745c5c3_Err != nil {
  459. return templ_7745c5c3_Err
  460. }
  461. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</span></td><td>")
  462. if templ_7745c5c3_Err != nil {
  463. return templ_7745c5c3_Err
  464. }
  465. templ_7745c5c3_Err = displayShardSizes(volume.ShardSizes).Render(ctx, templ_7745c5c3_Buffer)
  466. if templ_7745c5c3_Err != nil {
  467. return templ_7745c5c3_Err
  468. }
  469. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</td><td>")
  470. if templ_7745c5c3_Err != nil {
  471. return templ_7745c5c3_Err
  472. }
  473. templ_7745c5c3_Err = displayVolumeDistribution(volume).Render(ctx, templ_7745c5c3_Buffer)
  474. if templ_7745c5c3_Err != nil {
  475. return templ_7745c5c3_Err
  476. }
  477. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</td><td>")
  478. if templ_7745c5c3_Err != nil {
  479. return templ_7745c5c3_Err
  480. }
  481. templ_7745c5c3_Err = displayEcVolumeStatus(volume).Render(ctx, templ_7745c5c3_Buffer)
  482. if templ_7745c5c3_Err != nil {
  483. return templ_7745c5c3_Err
  484. }
  485. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "</td>")
  486. if templ_7745c5c3_Err != nil {
  487. return templ_7745c5c3_Err
  488. }
  489. if data.ShowDataCenterColumn {
  490. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<td>")
  491. if templ_7745c5c3_Err != nil {
  492. return templ_7745c5c3_Err
  493. }
  494. for i, dc := range volume.DataCenters {
  495. if i > 0 {
  496. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "<span>, </span>")
  497. if templ_7745c5c3_Err != nil {
  498. return templ_7745c5c3_Err
  499. }
  500. }
  501. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, " <span class=\"badge bg-primary text-white\">")
  502. if templ_7745c5c3_Err != nil {
  503. return templ_7745c5c3_Err
  504. }
  505. var templ_7745c5c3_Var18 string
  506. templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(dc)
  507. if templ_7745c5c3_Err != nil {
  508. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 252, Col: 85}
  509. }
  510. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
  511. if templ_7745c5c3_Err != nil {
  512. return templ_7745c5c3_Err
  513. }
  514. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "</span>")
  515. if templ_7745c5c3_Err != nil {
  516. return templ_7745c5c3_Err
  517. }
  518. }
  519. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "</td>")
  520. if templ_7745c5c3_Err != nil {
  521. return templ_7745c5c3_Err
  522. }
  523. }
  524. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "<td><div class=\"btn-group\" role=\"group\"><button type=\"button\" class=\"btn btn-sm btn-outline-primary\" onclick=\"showVolumeDetails(event)\" data-volume-id=\"")
  525. if templ_7745c5c3_Err != nil {
  526. return templ_7745c5c3_Err
  527. }
  528. var templ_7745c5c3_Var19 string
  529. templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", volume.VolumeID))
  530. if templ_7745c5c3_Err != nil {
  531. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 260, Col: 95}
  532. }
  533. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
  534. if templ_7745c5c3_Err != nil {
  535. return templ_7745c5c3_Err
  536. }
  537. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "\" title=\"View EC volume details\"><i class=\"fas fa-info-circle\"></i></button> ")
  538. if templ_7745c5c3_Err != nil {
  539. return templ_7745c5c3_Err
  540. }
  541. if !volume.IsComplete {
  542. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "<button type=\"button\" class=\"btn btn-sm btn-outline-warning\" onclick=\"repairVolume(event)\" data-volume-id=\"")
  543. if templ_7745c5c3_Err != nil {
  544. return templ_7745c5c3_Err
  545. }
  546. var templ_7745c5c3_Var20 string
  547. templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", volume.VolumeID))
  548. if templ_7745c5c3_Err != nil {
  549. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 267, Col: 99}
  550. }
  551. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
  552. if templ_7745c5c3_Err != nil {
  553. return templ_7745c5c3_Err
  554. }
  555. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\" title=\"Repair missing shards\"><i class=\"fas fa-wrench\"></i></button>")
  556. if templ_7745c5c3_Err != nil {
  557. return templ_7745c5c3_Err
  558. }
  559. }
  560. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "</div></td></tr>")
  561. if templ_7745c5c3_Err != nil {
  562. return templ_7745c5c3_Err
  563. }
  564. }
  565. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</tbody></table></div><!-- Pagination -->")
  566. if templ_7745c5c3_Err != nil {
  567. return templ_7745c5c3_Err
  568. }
  569. if data.TotalPages > 1 {
  570. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "<nav aria-label=\"EC Volumes pagination\"><ul class=\"pagination justify-content-center\">")
  571. if templ_7745c5c3_Err != nil {
  572. return templ_7745c5c3_Err
  573. }
  574. if data.Page > 1 {
  575. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "<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=\"")
  576. if templ_7745c5c3_Err != nil {
  577. return templ_7745c5c3_Err
  578. }
  579. var templ_7745c5c3_Var21 string
  580. templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Page-1))
  581. if templ_7745c5c3_Err != nil {
  582. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 289, Col: 126}
  583. }
  584. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
  585. if templ_7745c5c3_Err != nil {
  586. return templ_7745c5c3_Err
  587. }
  588. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "\">Previous</a></li>")
  589. if templ_7745c5c3_Err != nil {
  590. return templ_7745c5c3_Err
  591. }
  592. }
  593. for i := 1; i <= data.TotalPages; i++ {
  594. if i == data.Page {
  595. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "<li class=\"page-item active\"><span class=\"page-link\">")
  596. if templ_7745c5c3_Err != nil {
  597. return templ_7745c5c3_Err
  598. }
  599. var templ_7745c5c3_Var22 string
  600. templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i))
  601. if templ_7745c5c3_Err != nil {
  602. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 296, Col: 77}
  603. }
  604. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
  605. if templ_7745c5c3_Err != nil {
  606. return templ_7745c5c3_Err
  607. }
  608. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "</span></li>")
  609. if templ_7745c5c3_Err != nil {
  610. return templ_7745c5c3_Err
  611. }
  612. } else if i <= 3 || i > data.TotalPages-3 || (i >= data.Page-2 && i <= data.Page+2) {
  613. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "<li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"")
  614. if templ_7745c5c3_Err != nil {
  615. return templ_7745c5c3_Err
  616. }
  617. var templ_7745c5c3_Var23 string
  618. templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i))
  619. if templ_7745c5c3_Err != nil {
  620. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 300, Col: 120}
  621. }
  622. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
  623. if templ_7745c5c3_Err != nil {
  624. return templ_7745c5c3_Err
  625. }
  626. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\">")
  627. if templ_7745c5c3_Err != nil {
  628. return templ_7745c5c3_Err
  629. }
  630. var templ_7745c5c3_Var24 string
  631. templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", i))
  632. if templ_7745c5c3_Err != nil {
  633. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 300, Col: 144}
  634. }
  635. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
  636. if templ_7745c5c3_Err != nil {
  637. return templ_7745c5c3_Err
  638. }
  639. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "</a></li>")
  640. if templ_7745c5c3_Err != nil {
  641. return templ_7745c5c3_Err
  642. }
  643. } else if i == 4 && data.Page > 6 {
  644. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "<li class=\"page-item disabled\"><span class=\"page-link\">...</span></li>")
  645. if templ_7745c5c3_Err != nil {
  646. return templ_7745c5c3_Err
  647. }
  648. } else if i == data.TotalPages-3 && data.Page < data.TotalPages-5 {
  649. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "<li class=\"page-item disabled\"><span class=\"page-link\">...</span></li>")
  650. if templ_7745c5c3_Err != nil {
  651. return templ_7745c5c3_Err
  652. }
  653. }
  654. }
  655. if data.Page < data.TotalPages {
  656. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "<li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"")
  657. if templ_7745c5c3_Err != nil {
  658. return templ_7745c5c3_Err
  659. }
  660. var templ_7745c5c3_Var25 string
  661. templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.Page+1))
  662. if templ_7745c5c3_Err != nil {
  663. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 315, Col: 126}
  664. }
  665. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
  666. if templ_7745c5c3_Err != nil {
  667. return templ_7745c5c3_Err
  668. }
  669. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "\">Next</a></li><li class=\"page-item\"><a class=\"page-link\" href=\"#\" onclick=\"goToPage(event)\" data-page=\"")
  670. if templ_7745c5c3_Err != nil {
  671. return templ_7745c5c3_Err
  672. }
  673. var templ_7745c5c3_Var26 string
  674. templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalPages))
  675. if templ_7745c5c3_Err != nil {
  676. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 318, Col: 130}
  677. }
  678. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
  679. if templ_7745c5c3_Err != nil {
  680. return templ_7745c5c3_Err
  681. }
  682. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "\">Last</a></li>")
  683. if templ_7745c5c3_Err != nil {
  684. return templ_7745c5c3_Err
  685. }
  686. }
  687. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "</ul></nav>")
  688. if templ_7745c5c3_Err != nil {
  689. return templ_7745c5c3_Err
  690. }
  691. }
  692. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "</div><script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js\"></script><script>\n // Sorting functionality\n function sortBy(field) {\n const currentSort = new URLSearchParams(window.location.search).get('sort_by');\n const currentOrder = new URLSearchParams(window.location.search).get('sort_order') || 'asc';\n \n let newOrder = 'asc';\n if (currentSort === field && currentOrder === 'asc') {\n newOrder = 'desc';\n }\n \n const url = new URL(window.location);\n url.searchParams.set('sort_by', field);\n url.searchParams.set('sort_order', newOrder);\n url.searchParams.set('page', '1'); // Reset to first page\n window.location.href = url.toString();\n }\n\n // Pagination functionality\n function goToPage(event) {\n event.preventDefault();\n const page = event.target.closest('a').getAttribute('data-page');\n const url = new URL(window.location);\n url.searchParams.set('page', page);\n window.location.href = url.toString();\n }\n\n // Page size functionality\n function changePageSize(newPageSize) {\n const url = new URL(window.location);\n url.searchParams.set('page_size', newPageSize);\n url.searchParams.set('page', '1'); // Reset to first page when changing page size\n window.location.href = url.toString();\n }\n\n // Volume details\n function showVolumeDetails(event) {\n const volumeId = event.target.closest('button').getAttribute('data-volume-id');\n window.location.href = `/cluster/ec-volumes/${volumeId}`;\n }\n\n // Repair volume\n function repairVolume(event) {\n const volumeId = event.target.closest('button').getAttribute('data-volume-id');\n if (confirm(`Are you sure you want to repair missing shards for volume ${volumeId}?`)) {\n // TODO: Implement repair functionality\n alert('Repair functionality will be implemented soon.');\n }\n }\n </script></body></html>")
  693. if templ_7745c5c3_Err != nil {
  694. return templ_7745c5c3_Err
  695. }
  696. return nil
  697. })
  698. }
  699. // displayShardLocationsHTML renders shard locations as proper HTML
  700. func displayShardLocationsHTML(shardLocations map[int]string) templ.Component {
  701. return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
  702. templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
  703. if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
  704. return templ_7745c5c3_CtxErr
  705. }
  706. templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
  707. if !templ_7745c5c3_IsBuffer {
  708. defer func() {
  709. templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
  710. if templ_7745c5c3_Err == nil {
  711. templ_7745c5c3_Err = templ_7745c5c3_BufErr
  712. }
  713. }()
  714. }
  715. ctx = templ.InitializeContext(ctx)
  716. templ_7745c5c3_Var27 := templ.GetChildren(ctx)
  717. if templ_7745c5c3_Var27 == nil {
  718. templ_7745c5c3_Var27 = templ.NopComponent
  719. }
  720. ctx = templ.ClearChildren(ctx)
  721. if len(shardLocations) == 0 {
  722. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "<span class=\"text-muted\">No shards</span>")
  723. if templ_7745c5c3_Err != nil {
  724. return templ_7745c5c3_Err
  725. }
  726. } else {
  727. for i, serverInfo := range groupShardsByServer(shardLocations) {
  728. if i > 0 {
  729. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "<br>")
  730. if templ_7745c5c3_Err != nil {
  731. return templ_7745c5c3_Err
  732. }
  733. }
  734. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, " <strong><a href=\"")
  735. if templ_7745c5c3_Err != nil {
  736. return templ_7745c5c3_Err
  737. }
  738. var templ_7745c5c3_Var28 templ.SafeURL
  739. templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/cluster/volume-servers/" + serverInfo.Server))
  740. if templ_7745c5c3_Err != nil {
  741. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 391, Col: 71}
  742. }
  743. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
  744. if templ_7745c5c3_Err != nil {
  745. return templ_7745c5c3_Err
  746. }
  747. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "\" class=\"text-primary text-decoration-none\">")
  748. if templ_7745c5c3_Err != nil {
  749. return templ_7745c5c3_Err
  750. }
  751. var templ_7745c5c3_Var29 string
  752. templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(serverInfo.Server)
  753. if templ_7745c5c3_Err != nil {
  754. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 392, Col: 24}
  755. }
  756. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
  757. if templ_7745c5c3_Err != nil {
  758. return templ_7745c5c3_Err
  759. }
  760. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "</a>:</strong> ")
  761. if templ_7745c5c3_Err != nil {
  762. return templ_7745c5c3_Err
  763. }
  764. var templ_7745c5c3_Var30 string
  765. templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(serverInfo.ShardRanges)
  766. if templ_7745c5c3_Err != nil {
  767. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 394, Col: 37}
  768. }
  769. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
  770. if templ_7745c5c3_Err != nil {
  771. return templ_7745c5c3_Err
  772. }
  773. }
  774. }
  775. return nil
  776. })
  777. }
  778. // displayShardSizes renders shard sizes in a compact format
  779. func displayShardSizes(shardSizes map[int]int64) templ.Component {
  780. return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
  781. templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
  782. if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
  783. return templ_7745c5c3_CtxErr
  784. }
  785. templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
  786. if !templ_7745c5c3_IsBuffer {
  787. defer func() {
  788. templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
  789. if templ_7745c5c3_Err == nil {
  790. templ_7745c5c3_Err = templ_7745c5c3_BufErr
  791. }
  792. }()
  793. }
  794. ctx = templ.InitializeContext(ctx)
  795. templ_7745c5c3_Var31 := templ.GetChildren(ctx)
  796. if templ_7745c5c3_Var31 == nil {
  797. templ_7745c5c3_Var31 = templ.NopComponent
  798. }
  799. ctx = templ.ClearChildren(ctx)
  800. if len(shardSizes) == 0 {
  801. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "<span class=\"text-muted\">-</span>")
  802. if templ_7745c5c3_Err != nil {
  803. return templ_7745c5c3_Err
  804. }
  805. } else {
  806. templ_7745c5c3_Err = renderShardSizesContent(shardSizes).Render(ctx, templ_7745c5c3_Buffer)
  807. if templ_7745c5c3_Err != nil {
  808. return templ_7745c5c3_Err
  809. }
  810. }
  811. return nil
  812. })
  813. }
  814. // renderShardSizesContent renders the content of shard sizes
  815. func renderShardSizesContent(shardSizes map[int]int64) templ.Component {
  816. return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
  817. templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
  818. if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
  819. return templ_7745c5c3_CtxErr
  820. }
  821. templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
  822. if !templ_7745c5c3_IsBuffer {
  823. defer func() {
  824. templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
  825. if templ_7745c5c3_Err == nil {
  826. templ_7745c5c3_Err = templ_7745c5c3_BufErr
  827. }
  828. }()
  829. }
  830. ctx = templ.InitializeContext(ctx)
  831. templ_7745c5c3_Var32 := templ.GetChildren(ctx)
  832. if templ_7745c5c3_Var32 == nil {
  833. templ_7745c5c3_Var32 = templ.NopComponent
  834. }
  835. ctx = templ.ClearChildren(ctx)
  836. if areAllShardSizesSame(shardSizes) {
  837. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, " <span class=\"text-success\">")
  838. if templ_7745c5c3_Err != nil {
  839. return templ_7745c5c3_Err
  840. }
  841. var templ_7745c5c3_Var33 string
  842. templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(getCommonShardSize(shardSizes))
  843. if templ_7745c5c3_Err != nil {
  844. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 412, Col: 60}
  845. }
  846. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
  847. if templ_7745c5c3_Err != nil {
  848. return templ_7745c5c3_Err
  849. }
  850. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "</span>")
  851. if templ_7745c5c3_Err != nil {
  852. return templ_7745c5c3_Err
  853. }
  854. } else {
  855. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, " <div class=\"shard-sizes\" style=\"max-width: 300px;\">")
  856. if templ_7745c5c3_Err != nil {
  857. return templ_7745c5c3_Err
  858. }
  859. var templ_7745c5c3_Var34 string
  860. templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(formatIndividualShardSizes(shardSizes))
  861. if templ_7745c5c3_Err != nil {
  862. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 416, Col: 43}
  863. }
  864. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
  865. if templ_7745c5c3_Err != nil {
  866. return templ_7745c5c3_Err
  867. }
  868. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "</div>")
  869. if templ_7745c5c3_Err != nil {
  870. return templ_7745c5c3_Err
  871. }
  872. }
  873. return nil
  874. })
  875. }
  876. // ServerShardInfo represents server and its shard ranges with sizes
  877. type ServerShardInfo struct {
  878. Server string
  879. ShardRanges string
  880. }
  881. // groupShardsByServer groups shards by server and formats ranges
  882. func groupShardsByServer(shardLocations map[int]string) []ServerShardInfo {
  883. if len(shardLocations) == 0 {
  884. return []ServerShardInfo{}
  885. }
  886. // Group shards by server
  887. serverShards := make(map[string][]int)
  888. for shardId, server := range shardLocations {
  889. serverShards[server] = append(serverShards[server], shardId)
  890. }
  891. var serverInfos []ServerShardInfo
  892. for server, shards := range serverShards {
  893. // Sort shards for each server
  894. for i := 0; i < len(shards); i++ {
  895. for j := i + 1; j < len(shards); j++ {
  896. if shards[i] > shards[j] {
  897. shards[i], shards[j] = shards[j], shards[i]
  898. }
  899. }
  900. }
  901. // Format shard ranges compactly
  902. shardRanges := formatShardRanges(shards)
  903. serverInfos = append(serverInfos, ServerShardInfo{
  904. Server: server,
  905. ShardRanges: shardRanges,
  906. })
  907. }
  908. // Sort by server name
  909. for i := 0; i < len(serverInfos); i++ {
  910. for j := i + 1; j < len(serverInfos); j++ {
  911. if serverInfos[i].Server > serverInfos[j].Server {
  912. serverInfos[i], serverInfos[j] = serverInfos[j], serverInfos[i]
  913. }
  914. }
  915. }
  916. return serverInfos
  917. }
  918. // groupShardsByServerWithSizes groups shards by server and formats ranges with sizes
  919. func groupShardsByServerWithSizes(shardLocations map[int]string, shardSizes map[int]int64) []ServerShardInfo {
  920. if len(shardLocations) == 0 {
  921. return []ServerShardInfo{}
  922. }
  923. // Group shards by server
  924. serverShards := make(map[string][]int)
  925. for shardId, server := range shardLocations {
  926. serverShards[server] = append(serverShards[server], shardId)
  927. }
  928. var serverInfos []ServerShardInfo
  929. for server, shards := range serverShards {
  930. // Sort shards for each server
  931. for i := 0; i < len(shards); i++ {
  932. for j := i + 1; j < len(shards); j++ {
  933. if shards[i] > shards[j] {
  934. shards[i], shards[j] = shards[j], shards[i]
  935. }
  936. }
  937. }
  938. // Format shard ranges compactly with sizes
  939. shardRanges := formatShardRangesWithSizes(shards, shardSizes)
  940. serverInfos = append(serverInfos, ServerShardInfo{
  941. Server: server,
  942. ShardRanges: shardRanges,
  943. })
  944. }
  945. // Sort by server name
  946. for i := 0; i < len(serverInfos); i++ {
  947. for j := i + 1; j < len(serverInfos); j++ {
  948. if serverInfos[i].Server > serverInfos[j].Server {
  949. serverInfos[i], serverInfos[j] = serverInfos[j], serverInfos[i]
  950. }
  951. }
  952. }
  953. return serverInfos
  954. }
  955. // Helper function to format shard ranges compactly (e.g., "0-3,7,9-11")
  956. func formatShardRanges(shards []int) string {
  957. if len(shards) == 0 {
  958. return ""
  959. }
  960. var ranges []string
  961. start := shards[0]
  962. end := shards[0]
  963. for i := 1; i < len(shards); i++ {
  964. if shards[i] == end+1 {
  965. end = shards[i]
  966. } else {
  967. if start == end {
  968. ranges = append(ranges, fmt.Sprintf("%d", start))
  969. } else {
  970. ranges = append(ranges, fmt.Sprintf("%d-%d", start, end))
  971. }
  972. start = shards[i]
  973. end = shards[i]
  974. }
  975. }
  976. // Add the last range
  977. if start == end {
  978. ranges = append(ranges, fmt.Sprintf("%d", start))
  979. } else {
  980. ranges = append(ranges, fmt.Sprintf("%d-%d", start, end))
  981. }
  982. return strings.Join(ranges, ",")
  983. }
  984. // Helper function to format shard ranges with sizes (e.g., "0(1.2MB),1-3(2.5MB),7(800KB)")
  985. func formatShardRangesWithSizes(shards []int, shardSizes map[int]int64) string {
  986. if len(shards) == 0 {
  987. return ""
  988. }
  989. var ranges []string
  990. start := shards[0]
  991. end := shards[0]
  992. var totalSize int64
  993. for i := 1; i < len(shards); i++ {
  994. if shards[i] == end+1 {
  995. end = shards[i]
  996. totalSize += shardSizes[shards[i]]
  997. } else {
  998. // Add current range with size
  999. if start == end {
  1000. size := shardSizes[start]
  1001. if size > 0 {
  1002. ranges = append(ranges, fmt.Sprintf("%d(%s)", start, bytesToHumanReadable(size)))
  1003. } else {
  1004. ranges = append(ranges, fmt.Sprintf("%d", start))
  1005. }
  1006. } else {
  1007. // Calculate total size for the range
  1008. rangeSize := shardSizes[start]
  1009. for j := start + 1; j <= end; j++ {
  1010. rangeSize += shardSizes[j]
  1011. }
  1012. if rangeSize > 0 {
  1013. ranges = append(ranges, fmt.Sprintf("%d-%d(%s)", start, end, bytesToHumanReadable(rangeSize)))
  1014. } else {
  1015. ranges = append(ranges, fmt.Sprintf("%d-%d", start, end))
  1016. }
  1017. }
  1018. start = shards[i]
  1019. end = shards[i]
  1020. totalSize = shardSizes[shards[i]]
  1021. }
  1022. }
  1023. // Add the last range
  1024. if start == end {
  1025. size := shardSizes[start]
  1026. if size > 0 {
  1027. ranges = append(ranges, fmt.Sprintf("%d(%s)", start, bytesToHumanReadable(size)))
  1028. } else {
  1029. ranges = append(ranges, fmt.Sprintf("%d", start))
  1030. }
  1031. } else {
  1032. // Calculate total size for the range
  1033. rangeSize := shardSizes[start]
  1034. for j := start + 1; j <= end; j++ {
  1035. rangeSize += shardSizes[j]
  1036. }
  1037. if rangeSize > 0 {
  1038. ranges = append(ranges, fmt.Sprintf("%d-%d(%s)", start, end, bytesToHumanReadable(rangeSize)))
  1039. } else {
  1040. ranges = append(ranges, fmt.Sprintf("%d-%d", start, end))
  1041. }
  1042. }
  1043. return strings.Join(ranges, ",")
  1044. }
  1045. // Helper function to convert bytes to human readable format
  1046. func bytesToHumanReadable(bytes int64) string {
  1047. const unit = 1024
  1048. if bytes < unit {
  1049. return fmt.Sprintf("%dB", bytes)
  1050. }
  1051. div, exp := int64(unit), 0
  1052. for n := bytes / unit; n >= unit; n /= unit {
  1053. div *= unit
  1054. exp++
  1055. }
  1056. return fmt.Sprintf("%.1f%cB", float64(bytes)/float64(div), "KMGTPE"[exp])
  1057. }
  1058. // Helper function to format missing shards
  1059. func formatMissingShards(missingShards []int) string {
  1060. if len(missingShards) == 0 {
  1061. return ""
  1062. }
  1063. var shardStrs []string
  1064. for _, shard := range missingShards {
  1065. shardStrs = append(shardStrs, fmt.Sprintf("%d", shard))
  1066. }
  1067. return strings.Join(shardStrs, ", ")
  1068. }
  1069. // Helper function to check if all shard sizes are the same
  1070. func areAllShardSizesSame(shardSizes map[int]int64) bool {
  1071. if len(shardSizes) <= 1 {
  1072. return true
  1073. }
  1074. var firstSize int64 = -1
  1075. for _, size := range shardSizes {
  1076. if firstSize == -1 {
  1077. firstSize = size
  1078. } else if size != firstSize {
  1079. return false
  1080. }
  1081. }
  1082. return true
  1083. }
  1084. // Helper function to get the common shard size (when all shards are the same size)
  1085. func getCommonShardSize(shardSizes map[int]int64) string {
  1086. for _, size := range shardSizes {
  1087. return bytesToHumanReadable(size)
  1088. }
  1089. return "-"
  1090. }
  1091. // Helper function to format individual shard sizes
  1092. func formatIndividualShardSizes(shardSizes map[int]int64) string {
  1093. if len(shardSizes) == 0 {
  1094. return ""
  1095. }
  1096. // Group shards by size for more compact display
  1097. sizeGroups := make(map[int64][]int)
  1098. for shardId, size := range shardSizes {
  1099. sizeGroups[size] = append(sizeGroups[size], shardId)
  1100. }
  1101. // If there are only 1-2 different sizes, show them grouped
  1102. if len(sizeGroups) <= 3 {
  1103. var groupStrs []string
  1104. for size, shardIds := range sizeGroups {
  1105. // Sort shard IDs
  1106. for i := 0; i < len(shardIds); i++ {
  1107. for j := i + 1; j < len(shardIds); j++ {
  1108. if shardIds[i] > shardIds[j] {
  1109. shardIds[i], shardIds[j] = shardIds[j], shardIds[i]
  1110. }
  1111. }
  1112. }
  1113. var idRanges []string
  1114. if len(shardIds) <= erasure_coding.ParityShardsCount {
  1115. // Show individual IDs if few shards
  1116. for _, id := range shardIds {
  1117. idRanges = append(idRanges, fmt.Sprintf("%d", id))
  1118. }
  1119. } else {
  1120. // Show count if many shards
  1121. idRanges = append(idRanges, fmt.Sprintf("%d shards", len(shardIds)))
  1122. }
  1123. groupStrs = append(groupStrs, fmt.Sprintf("%s: %s", strings.Join(idRanges, ","), bytesToHumanReadable(size)))
  1124. }
  1125. return strings.Join(groupStrs, " | ")
  1126. }
  1127. // If too many different sizes, show summary
  1128. return fmt.Sprintf("%d different sizes", len(sizeGroups))
  1129. }
  1130. // displayVolumeDistribution shows the distribution summary for a volume
  1131. func displayVolumeDistribution(volume dash.EcVolumeWithShards) templ.Component {
  1132. return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
  1133. templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
  1134. if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
  1135. return templ_7745c5c3_CtxErr
  1136. }
  1137. templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
  1138. if !templ_7745c5c3_IsBuffer {
  1139. defer func() {
  1140. templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
  1141. if templ_7745c5c3_Err == nil {
  1142. templ_7745c5c3_Err = templ_7745c5c3_BufErr
  1143. }
  1144. }()
  1145. }
  1146. ctx = templ.InitializeContext(ctx)
  1147. templ_7745c5c3_Var35 := templ.GetChildren(ctx)
  1148. if templ_7745c5c3_Var35 == nil {
  1149. templ_7745c5c3_Var35 = templ.NopComponent
  1150. }
  1151. ctx = templ.ClearChildren(ctx)
  1152. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "<div class=\"small\"><i class=\"fas fa-sitemap me-1\"></i> ")
  1153. if templ_7745c5c3_Err != nil {
  1154. return templ_7745c5c3_Err
  1155. }
  1156. var templ_7745c5c3_Var36 string
  1157. templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(calculateVolumeDistributionSummary(volume))
  1158. if templ_7745c5c3_Err != nil {
  1159. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 714, Col: 52}
  1160. }
  1161. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36))
  1162. if templ_7745c5c3_Err != nil {
  1163. return templ_7745c5c3_Err
  1164. }
  1165. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "</div>")
  1166. if templ_7745c5c3_Err != nil {
  1167. return templ_7745c5c3_Err
  1168. }
  1169. return nil
  1170. })
  1171. }
  1172. // displayEcVolumeStatus shows an improved status display for EC volumes
  1173. func displayEcVolumeStatus(volume dash.EcVolumeWithShards) templ.Component {
  1174. return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
  1175. templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
  1176. if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
  1177. return templ_7745c5c3_CtxErr
  1178. }
  1179. templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
  1180. if !templ_7745c5c3_IsBuffer {
  1181. defer func() {
  1182. templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
  1183. if templ_7745c5c3_Err == nil {
  1184. templ_7745c5c3_Err = templ_7745c5c3_BufErr
  1185. }
  1186. }()
  1187. }
  1188. ctx = templ.InitializeContext(ctx)
  1189. templ_7745c5c3_Var37 := templ.GetChildren(ctx)
  1190. if templ_7745c5c3_Var37 == nil {
  1191. templ_7745c5c3_Var37 = templ.NopComponent
  1192. }
  1193. ctx = templ.ClearChildren(ctx)
  1194. if volume.IsComplete {
  1195. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "<span class=\"badge bg-success\"><i class=\"fas fa-check me-1\"></i>Complete</span>")
  1196. if templ_7745c5c3_Err != nil {
  1197. return templ_7745c5c3_Err
  1198. }
  1199. } else {
  1200. if len(volume.MissingShards) > erasure_coding.DataShardsCount {
  1201. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "<span class=\"badge bg-danger\"><i class=\"fas fa-skull me-1\"></i>Critical (")
  1202. if templ_7745c5c3_Err != nil {
  1203. return templ_7745c5c3_Err
  1204. }
  1205. var templ_7745c5c3_Var38 string
  1206. templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(volume.MissingShards)))
  1207. if templ_7745c5c3_Err != nil {
  1208. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 724, Col: 130}
  1209. }
  1210. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38))
  1211. if templ_7745c5c3_Err != nil {
  1212. return templ_7745c5c3_Err
  1213. }
  1214. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, " missing)</span>")
  1215. if templ_7745c5c3_Err != nil {
  1216. return templ_7745c5c3_Err
  1217. }
  1218. } else if len(volume.MissingShards) > (erasure_coding.DataShardsCount / 2) {
  1219. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "<span class=\"badge bg-warning\"><i class=\"fas fa-exclamation-triangle me-1\"></i>Degraded (")
  1220. if templ_7745c5c3_Err != nil {
  1221. return templ_7745c5c3_Err
  1222. }
  1223. var templ_7745c5c3_Var39 string
  1224. templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(volume.MissingShards)))
  1225. if templ_7745c5c3_Err != nil {
  1226. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 726, Col: 146}
  1227. }
  1228. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39))
  1229. if templ_7745c5c3_Err != nil {
  1230. return templ_7745c5c3_Err
  1231. }
  1232. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, " missing)</span>")
  1233. if templ_7745c5c3_Err != nil {
  1234. return templ_7745c5c3_Err
  1235. }
  1236. } else if len(volume.MissingShards) > (erasure_coding.ParityShardsCount / 2) {
  1237. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "<span class=\"badge bg-warning\"><i class=\"fas fa-info-circle me-1\"></i>Incomplete (")
  1238. if templ_7745c5c3_Err != nil {
  1239. return templ_7745c5c3_Err
  1240. }
  1241. var templ_7745c5c3_Var40 string
  1242. templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(volume.MissingShards)))
  1243. if templ_7745c5c3_Err != nil {
  1244. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 728, Col: 139}
  1245. }
  1246. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
  1247. if templ_7745c5c3_Err != nil {
  1248. return templ_7745c5c3_Err
  1249. }
  1250. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, " missing)</span>")
  1251. if templ_7745c5c3_Err != nil {
  1252. return templ_7745c5c3_Err
  1253. }
  1254. } else {
  1255. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "<span class=\"badge bg-info\"><i class=\"fas fa-info-circle me-1\"></i>Minor Issues (")
  1256. if templ_7745c5c3_Err != nil {
  1257. return templ_7745c5c3_Err
  1258. }
  1259. var templ_7745c5c3_Var41 string
  1260. templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(volume.MissingShards)))
  1261. if templ_7745c5c3_Err != nil {
  1262. return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_ec_volumes.templ`, Line: 730, Col: 138}
  1263. }
  1264. _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41))
  1265. if templ_7745c5c3_Err != nil {
  1266. return templ_7745c5c3_Err
  1267. }
  1268. templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, " missing)</span>")
  1269. if templ_7745c5c3_Err != nil {
  1270. return templ_7745c5c3_Err
  1271. }
  1272. }
  1273. }
  1274. return nil
  1275. })
  1276. }
  1277. // calculateVolumeDistributionSummary calculates and formats the distribution summary for a volume
  1278. func calculateVolumeDistributionSummary(volume dash.EcVolumeWithShards) string {
  1279. dataCenters := make(map[string]bool)
  1280. racks := make(map[string]bool)
  1281. servers := make(map[string]bool)
  1282. // Count unique servers from shard locations
  1283. for _, server := range volume.ShardLocations {
  1284. servers[server] = true
  1285. }
  1286. // Use the DataCenters field if available
  1287. for _, dc := range volume.DataCenters {
  1288. dataCenters[dc] = true
  1289. }
  1290. // Use the Servers field if available
  1291. for _, server := range volume.Servers {
  1292. servers[server] = true
  1293. }
  1294. // Use the Racks field if available
  1295. for _, rack := range volume.Racks {
  1296. racks[rack] = true
  1297. }
  1298. // If we don't have rack information, estimate it from servers as fallback
  1299. rackCount := len(racks)
  1300. if rackCount == 0 {
  1301. // Fallback estimation - assume each server might be in a different rack
  1302. rackCount = len(servers)
  1303. if len(dataCenters) > 0 {
  1304. // More conservative estimate if we have DC info
  1305. rackCount = (len(servers) + len(dataCenters) - 1) / len(dataCenters)
  1306. if rackCount == 0 {
  1307. rackCount = 1
  1308. }
  1309. }
  1310. }
  1311. return fmt.Sprintf("%d DCs, %d racks, %d servers", len(dataCenters), rackCount, len(servers))
  1312. }
  1313. var _ = templruntime.GeneratedTemplate