diff options
| author | chrislu <chris.lu@gmail.com> | 2025-07-11 13:03:04 -0700 |
|---|---|---|
| committer | chrislu <chris.lu@gmail.com> | 2025-07-11 13:03:04 -0700 |
| commit | 3d4a9bdac06a833da998f3c4dff0211e8b5c1b44 (patch) | |
| tree | bd9696c309ae9a3213f08dcfdfe52fcb97cfc024 | |
| parent | 51543bbb872161b7fa1c6ae30998981d4c55bc89 (diff) | |
| download | seaweedfs-3d4a9bdac06a833da998f3c4dff0211e8b5c1b44.tar.xz seaweedfs-3d4a9bdac06a833da998f3c4dff0211e8b5c1b44.zip | |
upgrade templ version from v0.3.833 to v0.3.906
// templ: version: v0.3.833
// templ: version: v0.3.906
fix https://github.com/seaweedfs/seaweedfs/issues/6966#issuecomment-3063449163
27 files changed, 509 insertions, 603 deletions
diff --git a/weed/admin/view/app/admin_templ.go b/weed/admin/view/app/admin_templ.go index 7320edd47..f9c0f1b57 100644 --- a/weed/admin/view/app/admin_templ.go +++ b/weed/admin/view/app/admin_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -185,8 +185,12 @@ func Admin(data dash.AdminData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", vs.PublicURL)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11))) + var templ_7745c5c3_Var11 templ.SafeURL + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", vs.PublicURL))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 210, Col: 124} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -301,8 +305,12 @@ func Admin(data dash.AdminData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var19 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s", filer.Address)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var19))) + var templ_7745c5c3_Var19 templ.SafeURL + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s", filer.Address))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 278, Col: 111} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/cluster_brokers_templ.go b/weed/admin/view/app/cluster_brokers_templ.go index 1d5030d15..bc3bf8f20 100644 --- a/weed/admin/view/app/cluster_brokers_templ.go +++ b/weed/admin/view/app/cluster_brokers_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/app/cluster_collections_templ.go b/weed/admin/view/app/cluster_collections_templ.go index 94282f11f..8c675695a 100644 --- a/weed/admin/view/app/cluster_collections_templ.go +++ b/weed/admin/view/app/cluster_collections_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -100,8 +100,12 @@ func ClusterCollections(data dash.ClusterCollectionsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6))) + var templ_7745c5c3_Var6 templ.SafeURL + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 131, Col: 130} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -122,8 +126,12 @@ func ClusterCollections(data dash.ClusterCollectionsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8))) + var templ_7745c5c3_Var8 templ.SafeURL + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", collection.Name))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_collections.templ`, Line: 136, Col: 130} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/cluster_filers.templ b/weed/admin/view/app/cluster_filers.templ index 2221106b3..6ed14ac6e 100644 --- a/weed/admin/view/app/cluster_filers.templ +++ b/weed/admin/view/app/cluster_filers.templ @@ -90,11 +90,8 @@ templ ClusterFilers(data dash.ClusterFilersData) { } </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="File Browser" onclick={ templ.ComponentScript{Call: fmt.Sprintf("window.open('http://%s', '_blank')", filer.Address)} }> + <div class="btn-group btn-group-sm" role="group"> + <button type="button" class="btn btn-outline-secondary btn-sm" title="File Browser" data-action="open-filer" data-address={ filer.Address }> <i class="fas fa-folder-open"></i> </button> </div> diff --git a/weed/admin/view/app/cluster_filers_templ.go b/weed/admin/view/app/cluster_filers_templ.go index fc4b9138d..ecc2d873e 100644 --- a/weed/admin/view/app/cluster_filers_templ.go +++ b/weed/admin/view/app/cluster_filers_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -61,8 +61,12 @@ func ClusterFilers(data dash.ClusterFilersData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s", filer.Address)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3))) + var templ_7745c5c3_Var3 templ.SafeURL + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s", filer.Address))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_filers.templ`, Line: 71, Col: 75} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -138,52 +142,48 @@ func ClusterFilers(data dash.ClusterFilersData) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</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> ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("window.open('http://%s', '_blank')", filer.Address)}) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</td><td><div class=\"btn-group btn-group-sm\" role=\"group\"><button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" title=\"File Browser\" data-action=\"open-filer\" data-address=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" title=\"File Browser\" onclick=\"") + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(filer.Address) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_filers.templ`, Line: 94, Col: 149} } - var templ_7745c5c3_Var9 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("window.open('http://%s', '_blank')", filer.Address)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9.Call) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\"><i class=\"fas fa-folder-open\"></i></button></div></td></tr>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\"><i class=\"fas fa-folder-open\"></i></button></div></td></tr>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</tbody></table></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</tbody></table></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<div class=\"text-center py-5\"><i class=\"fas fa-folder-open fa-3x text-muted mb-3\"></i><h5 class=\"text-muted\">No Filers Found</h5><p class=\"text-muted\">No filer servers are currently available in the cluster.</p></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"text-center py-5\"><i class=\"fas fa-folder-open fa-3x text-muted mb-3\"></i><h5 class=\"text-muted\">No Filers Found</h5><p class=\"text-muted\">No filer servers are currently available in the cluster.</p></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</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, 15, "</div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"fas fa-clock me-1\"></i> Last updated: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_filers.templ`, Line: 122, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_filers.templ`, Line: 119, Col: 67} } _, 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, 17, "</small></div></div></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</small></div></div></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/cluster_masters_templ.go b/weed/admin/view/app/cluster_masters_templ.go index 693795322..951db551e 100644 --- a/weed/admin/view/app/cluster_masters_templ.go +++ b/weed/admin/view/app/cluster_masters_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -89,8 +89,12 @@ func ClusterMasters(data dash.ClusterMastersData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s", master.Address)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) + var templ_7745c5c3_Var4 templ.SafeURL + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s", master.Address))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_masters.templ`, Line: 113, Col: 76} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/cluster_volume_servers_templ.go b/weed/admin/view/app/cluster_volume_servers_templ.go index 88881e6e5..1bd439974 100644 --- a/weed/admin/view/app/cluster_volume_servers_templ.go +++ b/weed/admin/view/app/cluster_volume_servers_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -100,8 +100,12 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", host.PublicURL)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6))) + var templ_7745c5c3_Var6 templ.SafeURL + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", host.PublicURL))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 118, Col: 122} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/cluster_volumes_templ.go b/weed/admin/view/app/cluster_volumes_templ.go index d2a82c704..c82da952c 100644 --- a/weed/admin/view/app/cluster_volumes_templ.go +++ b/weed/admin/view/app/cluster_volumes_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -329,7 +329,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { return templ_7745c5c3_Err } if len(data.Volumes) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<div class=\"table-responsive\"><table class=\"table table-hover\" id=\"volumesTable\"><thead><tr><th><a href=\"#\" onclick=\"sortTable('id')\" class=\"text-decoration-none text-dark\">Volume ID") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<div class=\"table-responsive\"><table class=\"table table-hover\" id=\"volumesTable\"><thead><tr><th><a href=\"#\" onclick=\"sortTable('id')\" class=\"text-decoration-none text-dark\">Volume ID") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -337,7 +337,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</a></th><th><a href=\"#\" onclick=\"sortTable('server')\" class=\"text-decoration-none text-dark\">Server") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</a></th><th><a href=\"#\" onclick=\"sortTable('server')\" class=\"text-decoration-none text-dark\">Server") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -350,7 +350,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { return templ_7745c5c3_Err } if data.ShowDataCenterColumn { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<th><a href=\"#\" onclick=\"sortTable('datacenter')\" class=\"text-decoration-none text-dark\">Data Center") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<th><a href=\"#\" onclick=\"sortTable('datacenter')\" class=\"text-decoration-none text-dark\">Data Center") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -364,7 +364,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { } } if data.ShowRackColumn { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<th><a href=\"#\" onclick=\"sortTable('rack')\" class=\"text-decoration-none text-dark\">Rack") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<th><a href=\"#\" onclick=\"sortTable('rack')\" class=\"text-decoration-none text-dark\">Rack") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -378,7 +378,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { } } if data.ShowCollectionColumn { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<th><a href=\"#\" onclick=\"sortTable('collection')\" class=\"text-decoration-none text-dark\">Collection") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<th><a href=\"#\" onclick=\"sortTable('collection')\" class=\"text-decoration-none text-dark\">Collection") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -391,7 +391,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<th><a href=\"#\" onclick=\"sortTable('size')\" class=\"text-decoration-none text-dark\">Size") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<th><a href=\"#\" onclick=\"sortTable('size')\" class=\"text-decoration-none text-dark\">Size") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -399,7 +399,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</a></th><th>Storage Usage</th><th><a href=\"#\" onclick=\"sortTable('filecount')\" class=\"text-decoration-none text-dark\">File Count") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</a></th><th>Storage Usage</th><th><a href=\"#\" onclick=\"sortTable('filecount')\" class=\"text-decoration-none text-dark\">File Count") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -407,7 +407,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</a></th><th><a href=\"#\" onclick=\"sortTable('replication')\" class=\"text-decoration-none text-dark\">Replication") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</a></th><th><a href=\"#\" onclick=\"sortTable('replication')\" class=\"text-decoration-none text-dark\">Replication") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -420,7 +420,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { return templ_7745c5c3_Err } if data.ShowDiskTypeColumn { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<th><a href=\"#\" onclick=\"sortTable('disktype')\" class=\"text-decoration-none text-dark\">Disk Type") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<th><a href=\"#\" onclick=\"sortTable('disktype')\" class=\"text-decoration-none text-dark\">Disk Type") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -434,7 +434,7 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { } } if data.ShowVersionColumn { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "<th><a href=\"#\" onclick=\"sortTable('version')\" class=\"text-decoration-none text-dark\">Version") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "<th><a href=\"#\" onclick=\"sortTable('version')\" class=\"text-decoration-none text-dark\">Version") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -482,8 +482,12 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var17 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", volume.Server)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var17))) + var templ_7745c5c3_Var17 templ.SafeURL + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", volume.Server))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volumes.templ`, Line: 323, Col: 121} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -552,8 +556,12 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var21 templ.SafeURL = templ.SafeURL("/cluster/volumes?collection=default") - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var21))) + var templ_7745c5c3_Var21 templ.SafeURL + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("/cluster/volumes?collection=default")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volumes.templ`, Line: 341, Col: 113} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -566,8 +574,12 @@ func ClusterVolumes(data dash.ClusterVolumesData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var22 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", volume.Collection)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var22))) + var templ_7745c5c3_Var22 templ.SafeURL + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", volume.Collection))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volumes.templ`, Line: 345, Col: 140} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/file_browser.templ b/weed/admin/view/app/file_browser.templ index 0108b5768..a1e00555f 100644 --- a/weed/admin/view/app/file_browser.templ +++ b/weed/admin/view/app/file_browser.templ @@ -231,19 +231,19 @@ templ FileBrowser(data dash.FileBrowserData) { <code class="small">{ entry.Mode }</code> </td> <td> - <div class="btn-group btn-group-sm"> + <div class="btn-group btn-group-sm" role="group"> if !entry.IsDirectory { - <button type="button" class="btn btn-outline-primary btn-sm" title="Download" onclick={ templ.ComponentScript{Call: fmt.Sprintf("downloadFile('%s')", entry.FullPath)} }> + <button type="button" class="btn btn-outline-primary btn-sm" title="Download" data-action="download" data-path={ entry.FullPath }> <i class="fas fa-download"></i> </button> - <button type="button" class="btn btn-outline-info btn-sm" title="View" onclick={ templ.ComponentScript{Call: fmt.Sprintf("viewFile('%s')", entry.FullPath)} }> + <button type="button" class="btn btn-outline-info btn-sm" title="View" data-action="view" data-path={ entry.FullPath }> <i class="fas fa-eye"></i> </button> } - <button type="button" class="btn btn-outline-secondary btn-sm" title="Properties" onclick={ templ.ComponentScript{Call: fmt.Sprintf("showProperties('%s')", entry.FullPath)} }> - <i class="fas fa-info"></i> + <button type="button" class="btn btn-outline-secondary btn-sm" title="Properties" data-action="properties" data-path={ entry.FullPath }> + <i class="fas fa-info-circle"></i> </button> - <button type="button" class="btn btn-outline-danger btn-sm" title="Delete" onclick={ templ.ComponentScript{Call: fmt.Sprintf("confirmDelete('%s')", entry.FullPath)} }> + <button type="button" class="btn btn-outline-danger btn-sm" title="Delete" data-action="delete" data-path={ entry.FullPath }> <i class="fas fa-trash"></i> </button> </div> diff --git a/weed/admin/view/app/file_browser_templ.go b/weed/admin/view/app/file_browser_templ.go index 035dfa340..c4367e82d 100644 --- a/weed/admin/view/app/file_browser_templ.go +++ b/weed/admin/view/app/file_browser_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -98,8 +98,12 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/files?path=%s", crumb.Path)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) + var templ_7745c5c3_Var4 templ.SafeURL + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/files?path=%s", crumb.Path))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 52, Col: 72} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -219,8 +223,12 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/files?path=%s", data.ParentPath)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11))) + var templ_7745c5c3_Var11 templ.SafeURL + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/files?path=%s", data.ParentPath))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 166, Col: 75} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -261,8 +269,12 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var13 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/files?path=%s", entry.FullPath)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var13))) + var templ_7745c5c3_Var13 templ.SafeURL + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/files?path=%s", entry.FullPath))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 198, Col: 82} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -393,92 +405,84 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</code></td><td><div class=\"btn-group btn-group-sm\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</code></td><td><div class=\"btn-group btn-group-sm\" role=\"group\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if !entry.IsDirectory { - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("downloadFile('%s')", entry.FullPath)}) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Download\" onclick=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Download\" data-action=\"download\" data-path=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var22 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("downloadFile('%s')", entry.FullPath)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22.Call) + var templ_7745c5c3_Var22 string + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(entry.FullPath) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 236, Col: 139} } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "\"><i class=\"fas fa-download\"></i></button> ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("viewFile('%s')", entry.FullPath)}) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "\"><i class=\"fas fa-download\"></i></button> <button type=\"button\" class=\"btn btn-outline-info btn-sm\" title=\"View\" data-action=\"view\" data-path=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<button type=\"button\" class=\"btn btn-outline-info btn-sm\" title=\"View\" onclick=\"") + var templ_7745c5c3_Var23 string + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(entry.FullPath) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 239, Col: 128} } - var templ_7745c5c3_Var23 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("viewFile('%s')", entry.FullPath)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var23.Call) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "\"><i class=\"fas fa-eye\"></i></button> ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\"><i class=\"fas fa-eye\"></i></button> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("showProperties('%s')", entry.FullPath)}) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" title=\"Properties\" onclick=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" title=\"Properties\" data-action=\"properties\" data-path=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var24 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("showProperties('%s')", entry.FullPath)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24.Call) + var templ_7745c5c3_Var24 string + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(entry.FullPath) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 243, Col: 144} } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\"><i class=\"fas fa-info\"></i></button> ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("confirmDelete('%s')", entry.FullPath)}) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\"><i class=\"fas fa-info-circle\"></i></button> <button type=\"button\" class=\"btn btn-outline-danger btn-sm\" title=\"Delete\" data-action=\"delete\" data-path=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<button type=\"button\" class=\"btn btn-outline-danger btn-sm\" title=\"Delete\" onclick=\"") + var templ_7745c5c3_Var25 string + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(entry.FullPath) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 246, Col: 133} } - var templ_7745c5c3_Var25 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("confirmDelete('%s')", entry.FullPath)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var25.Call) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "\"><i class=\"fas fa-trash\"></i></button></div></td></tr>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\"><i class=\"fas fa-trash\"></i></button></div></td></tr>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</tbody></table></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</tbody></table></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "<div class=\"text-center py-5\"><i class=\"fas fa-folder-open fa-3x text-muted mb-3\"></i><h5 class=\"text-muted\">Empty Directory</h5><p class=\"text-muted\">This directory contains no files or subdirectories.</p></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<div class=\"text-center py-5\"><i class=\"fas fa-folder-open fa-3x text-muted mb-3\"></i><h5 class=\"text-muted\">Empty Directory</h5><p class=\"text-muted\">This directory contains no files or subdirectories.</p></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</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, 50, "</div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"fas fa-clock me-1\"></i> Last updated: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -491,7 +495,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "</small></div></div><!-- Create Folder Modal --><div class=\"modal fade\" id=\"createFolderModal\" tabindex=\"-1\" aria-labelledby=\"createFolderModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"createFolderModalLabel\"><i class=\"fas fa-folder-plus me-2\"></i>Create New Folder</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"createFolderForm\"><div class=\"mb-3\"><label for=\"folderName\" class=\"form-label\">Folder Name</label> <input type=\"text\" class=\"form-control\" id=\"folderName\" name=\"folderName\" required placeholder=\"Enter folder name\" maxlength=\"255\"><div class=\"form-text\">Folder names cannot contain / or \\ characters.</div></div><input type=\"hidden\" id=\"currentPath\" name=\"currentPath\" value=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</small></div></div><!-- Create Folder Modal --><div class=\"modal fade\" id=\"createFolderModal\" tabindex=\"-1\" aria-labelledby=\"createFolderModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"createFolderModalLabel\"><i class=\"fas fa-folder-plus me-2\"></i>Create New Folder</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"createFolderForm\"><div class=\"mb-3\"><label for=\"folderName\" class=\"form-label\">Folder Name</label> <input type=\"text\" class=\"form-control\" id=\"folderName\" name=\"folderName\" required placeholder=\"Enter folder name\" maxlength=\"255\"><div class=\"form-text\">Folder names cannot contain / or \\ characters.</div></div><input type=\"hidden\" id=\"currentPath\" name=\"currentPath\" value=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -504,7 +508,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\"></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"submitCreateFolder()\"><i class=\"fas fa-folder-plus me-1\"></i>Create Folder</button></div></div></div></div><!-- Upload File Modal --><div class=\"modal fade\" id=\"uploadFileModal\" tabindex=\"-1\" aria-labelledby=\"uploadFileModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"uploadFileModalLabel\"><i class=\"fas fa-upload me-2\"></i>Upload Files</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"uploadFileForm\" enctype=\"multipart/form-data\"><div class=\"mb-3\"><label for=\"fileInput\" class=\"form-label\">Select Files</label> <input type=\"file\" class=\"form-control\" id=\"fileInput\" name=\"files\" multiple required><div class=\"form-text\">Choose one or more files to upload to the current directory. You can select multiple files by holding Ctrl (Cmd on Mac) while clicking.</div></div><input type=\"hidden\" id=\"uploadPath\" name=\"path\" value=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\"></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"submitCreateFolder()\"><i class=\"fas fa-folder-plus me-1\"></i>Create Folder</button></div></div></div></div><!-- Upload File Modal --><div class=\"modal fade\" id=\"uploadFileModal\" tabindex=\"-1\" aria-labelledby=\"uploadFileModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"uploadFileModalLabel\"><i class=\"fas fa-upload me-2\"></i>Upload Files</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\"><form id=\"uploadFileForm\" enctype=\"multipart/form-data\"><div class=\"mb-3\"><label for=\"fileInput\" class=\"form-label\">Select Files</label> <input type=\"file\" class=\"form-control\" id=\"fileInput\" name=\"files\" multiple required><div class=\"form-text\">Choose one or more files to upload to the current directory. You can select multiple files by holding Ctrl (Cmd on Mac) while clicking.</div></div><input type=\"hidden\" id=\"uploadPath\" name=\"path\" value=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -517,7 +521,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\"><!-- File List Preview --><div id=\"fileListPreview\" class=\"mb-3\" style=\"display: none;\"><label class=\"form-label\">Selected Files:</label><div id=\"selectedFilesList\" class=\"border rounded p-2 bg-light\"><!-- Files will be listed here --></div></div><!-- Upload Progress --><div class=\"mb-3\" id=\"uploadProgress\" style=\"display: none;\"><label class=\"form-label\">Upload Progress:</label><div class=\"progress mb-2\"><div class=\"progress-bar progress-bar-striped progress-bar-animated\" role=\"progressbar\" style=\"width: 0%\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\">0%</div></div><div id=\"uploadStatus\" class=\"small text-muted\">Preparing upload...</div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"submitUploadFile()\"><i class=\"fas fa-upload me-1\"></i>Upload Files</button></div></div></div></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\"><!-- File List Preview --><div id=\"fileListPreview\" class=\"mb-3\" style=\"display: none;\"><label class=\"form-label\">Selected Files:</label><div id=\"selectedFilesList\" class=\"border rounded p-2 bg-light\"><!-- Files will be listed here --></div></div><!-- Upload Progress --><div class=\"mb-3\" id=\"uploadProgress\" style=\"display: none;\"><label class=\"form-label\">Upload Progress:</label><div class=\"progress mb-2\"><div class=\"progress-bar progress-bar-striped progress-bar-animated\" role=\"progressbar\" style=\"width: 0%\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\">0%</div></div><div id=\"uploadStatus\" class=\"small text-muted\">Preparing upload...</div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"submitUploadFile()\"><i class=\"fas fa-upload me-1\"></i>Upload Files</button></div></div></div></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/maintenance_config_templ.go b/weed/admin/view/app/maintenance_config_templ.go index deb67b010..038597925 100644 --- a/weed/admin/view/app/maintenance_config_templ.go +++ b/weed/admin/view/app/maintenance_config_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -144,8 +144,12 @@ func MaintenanceConfig(data *maintenance.MaintenanceConfigData) templ.Component if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(menuItem.Path) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9))) + var templ_7745c5c3_Var9 templ.SafeURL + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(menuItem.Path)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_config.templ`, Line: 140, Col: 69} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/maintenance_queue_templ.go b/weed/admin/view/app/maintenance_queue_templ.go index 703370b9c..42b5fa220 100644 --- a/weed/admin/view/app/maintenance_queue_templ.go +++ b/weed/admin/view/app/maintenance_queue_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/app/maintenance_workers.templ b/weed/admin/view/app/maintenance_workers.templ index bfaaa7061..37e1cb985 100644 --- a/weed/admin/view/app/maintenance_workers.templ +++ b/weed/admin/view/app/maintenance_workers.templ @@ -202,11 +202,11 @@ templ MaintenanceWorkers(data *dash.MaintenanceWorkersData) { </td> <td> <div class="btn-group btn-group-sm" role="group"> - <button type="button" class="btn btn-outline-info" onclick={ templ.ComponentScript{Call: "showWorkerDetails"} } data-worker-id={ worker.Worker.ID }> + <button type="button" class="btn btn-outline-info" onclick="showWorkerDetails(event)" data-worker-id={ worker.Worker.ID }> <i class="fas fa-info-circle"></i> </button> if worker.Worker.Status == "active" { - <button type="button" class="btn btn-outline-warning" onclick={ templ.ComponentScript{Call: "pauseWorker"} } data-worker-id={ worker.Worker.ID }> + <button type="button" class="btn btn-outline-warning" onclick="pauseWorker(event)" data-worker-id={ worker.Worker.ID }> <i class="fas fa-pause"></i> </button> } @@ -247,50 +247,48 @@ templ MaintenanceWorkers(data *dash.MaintenanceWorkersData) { var modal = new bootstrap.Modal(document.getElementById('workerDetailsModal')); // Load worker details - fetch(`/api/maintenance/workers/${workerID}`) + fetch('/api/maintenance/workers/' + workerID) .then(response => response.json()) .then(data => { const content = document.getElementById('workerDetailsContent'); - content.innerHTML = ` - <div class="row"> - <div class="col-md-6"> - <h6>Worker Information</h6> - <ul class="list-unstyled"> - <li><strong>ID:</strong> ${data.worker.id}</li> - <li><strong>Address:</strong> ${data.worker.address}</li> - <li><strong>Status:</strong> ${data.worker.status}</li> - <li><strong>Max Concurrent:</strong> ${data.worker.max_concurrent}</li> - <li><strong>Current Load:</strong> ${data.worker.current_load}</li> - </ul> - </div> - <div class="col-md-6"> - <h6>Performance Metrics</h6> - <ul class="list-unstyled"> - <li><strong>Tasks Completed:</strong> ${data.performance.tasks_completed}</li> - <li><strong>Tasks Failed:</strong> ${data.performance.tasks_failed}</li> - <li><strong>Success Rate:</strong> ${data.performance.success_rate.toFixed(1)}%</li> - <li><strong>Average Task Time:</strong> ${formatDuration(data.performance.average_task_time)}</li> - <li><strong>Uptime:</strong> ${formatDuration(data.performance.uptime)}</li> - </ul> - </div> - </div> - <hr> - <h6>Current Tasks</h6> - ${data.current_tasks.length === 0 ? - '<p class="text-muted">No current tasks</p>' : - data.current_tasks.map(task => ` - <div class="card mb-2"> - <div class="card-body py-2"> - <div class="d-flex justify-content-between"> - <span><strong>${task.type}</strong> - Volume ${task.volume_id}</span> - <span class="badge bg-info">${task.status}</span> - </div> - <small class="text-muted">${task.reason}</small> - </div> - </div> - `).join('') - } - `; + content.innerHTML = '<div class="row">' + + '<div class="col-md-6">' + + '<h6>Worker Information</h6>' + + '<ul class="list-unstyled">' + + '<li><strong>ID:</strong> ' + data.worker.id + '</li>' + + '<li><strong>Address:</strong> ' + data.worker.address + '</li>' + + '<li><strong>Status:</strong> ' + data.worker.status + '</li>' + + '<li><strong>Max Concurrent:</strong> ' + data.worker.max_concurrent + '</li>' + + '<li><strong>Current Load:</strong> ' + data.worker.current_load + '</li>' + + '</ul>' + + '</div>' + + '<div class="col-md-6">' + + '<h6>Performance Metrics</h6>' + + '<ul class="list-unstyled">' + + '<li><strong>Tasks Completed:</strong> ' + data.performance.tasks_completed + '</li>' + + '<li><strong>Tasks Failed:</strong> ' + data.performance.tasks_failed + '</li>' + + '<li><strong>Success Rate:</strong> ' + data.performance.success_rate.toFixed(1) + '%</li>' + + '<li><strong>Average Task Time:</strong> ' + formatDuration(data.performance.average_task_time) + '</li>' + + '<li><strong>Uptime:</strong> ' + formatDuration(data.performance.uptime) + '</li>' + + '</ul>' + + '</div>' + + '</div>' + + '<hr>' + + '<h6>Current Tasks</h6>' + + (data.current_tasks.length === 0 ? + '<p class="text-muted">No current tasks</p>' : + data.current_tasks.map(task => + '<div class="card mb-2">' + + '<div class="card-body py-2">' + + '<div class="d-flex justify-content-between">' + + '<span><strong>' + task.type + '</strong> - Volume ' + task.volume_id + '</span>' + + '<span class="badge bg-info">' + task.status + '</span>' + + '</div>' + + '<small class="text-muted">' + task.reason + '</small>' + + '</div>' + + '</div>' + ).join('') + ); modal.show(); }) .catch(error => { @@ -305,7 +303,7 @@ templ MaintenanceWorkers(data *dash.MaintenanceWorkersData) { const workerID = event.target.closest('button').getAttribute('data-worker-id'); if (confirm('Are you sure you want to pause this worker?')) { - fetch(`/api/maintenance/workers/${workerID}/pause`, { + fetch('/api/maintenance/workers/' + workerID + '/pause', { method: 'POST' }) .then(response => response.json()) @@ -329,11 +327,11 @@ templ MaintenanceWorkers(data *dash.MaintenanceWorkersData) { const hours = Math.floor(minutes / 60); if (hours > 0) { - return `${hours}h ${minutes % 60}m`; + return hours + 'h ' + (minutes % 60) + 'm'; } else if (minutes > 0) { - return `${minutes}m ${seconds % 60}s`; + return minutes + 'm ' + (seconds % 60) + 's'; } else { - return `${seconds}s`; + return seconds + 's'; } } </script> diff --git a/weed/admin/view/app/maintenance_workers_templ.go b/weed/admin/view/app/maintenance_workers_templ.go index 1cfe112a5..2be85bbc6 100644 --- a/weed/admin/view/app/maintenance_workers_templ.go +++ b/weed/admin/view/app/maintenance_workers_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -344,83 +344,53 @@ func MaintenanceWorkers(data *dash.MaintenanceWorkersData) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</td><td><div class=\"btn-group btn-group-sm\" role=\"group\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</td><td><div class=\"btn-group btn-group-sm\" role=\"group\"><button type=\"button\" class=\"btn btn-outline-info\" onclick=\"showWorkerDetails(event)\" data-worker-id=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: "showWorkerDetails"}) + var templ_7745c5c3_Var20 string + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(worker.Worker.ID) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<button type=\"button\" class=\"btn btn-outline-info\" onclick=\"") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_workers.templ`, Line: 205, Col: 175} } - var templ_7745c5c3_Var20 templ.ComponentScript = templ.ComponentScript{Call: "showWorkerDetails"} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20.Call) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "\" data-worker-id=\"") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var21 string - templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(worker.Worker.ID) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_workers.templ`, Line: 205, Col: 201} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\"><i class=\"fas fa-info-circle\"></i></button> ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\"><i class=\"fas fa-info-circle\"></i></button> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if worker.Worker.Status == "active" { - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: "pauseWorker"}) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<button type=\"button\" class=\"btn btn-outline-warning\" onclick=\"") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var22 templ.ComponentScript = templ.ComponentScript{Call: "pauseWorker"} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22.Call) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\" data-worker-id=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<button type=\"button\" class=\"btn btn-outline-warning\" onclick=\"pauseWorker(event)\" data-worker-id=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var23 string - templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(worker.Worker.ID) + var templ_7745c5c3_Var21 string + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(worker.Worker.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_workers.templ`, Line: 209, Col: 202} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/maintenance_workers.templ`, Line: 209, Col: 176} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\"><i class=\"fas fa-pause\"></i></button>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\"><i class=\"fas fa-pause\"></i></button>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</div></td></tr>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</div></td></tr>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</tbody></table></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</tbody></table></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</div></div></div></div></div><!-- Worker Details Modal --><div class=\"modal fade\" id=\"workerDetailsModal\" tabindex=\"-1\" aria-labelledby=\"workerDetailsModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"workerDetailsModalLabel\">Worker Details</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\" id=\"workerDetailsContent\"><!-- Content will be loaded dynamically --></div></div></div></div><script>\n function showWorkerDetails(event) {\n const workerID = event.target.closest('button').getAttribute('data-worker-id');\n \n // Show modal\n var modal = new bootstrap.Modal(document.getElementById('workerDetailsModal'));\n \n // Load worker details\n fetch(`/api/maintenance/workers/${workerID}`)\n .then(response => response.json())\n .then(data => {\n const content = document.getElementById('workerDetailsContent');\n content.innerHTML = `\n <div class=\"row\">\n <div class=\"col-md-6\">\n <h6>Worker Information</h6>\n <ul class=\"list-unstyled\">\n <li><strong>ID:</strong> ${data.worker.id}</li>\n <li><strong>Address:</strong> ${data.worker.address}</li>\n <li><strong>Status:</strong> ${data.worker.status}</li>\n <li><strong>Max Concurrent:</strong> ${data.worker.max_concurrent}</li>\n <li><strong>Current Load:</strong> ${data.worker.current_load}</li>\n </ul>\n </div>\n <div class=\"col-md-6\">\n <h6>Performance Metrics</h6>\n <ul class=\"list-unstyled\">\n <li><strong>Tasks Completed:</strong> ${data.performance.tasks_completed}</li>\n <li><strong>Tasks Failed:</strong> ${data.performance.tasks_failed}</li>\n <li><strong>Success Rate:</strong> ${data.performance.success_rate.toFixed(1)}%</li>\n <li><strong>Average Task Time:</strong> ${formatDuration(data.performance.average_task_time)}</li>\n <li><strong>Uptime:</strong> ${formatDuration(data.performance.uptime)}</li>\n </ul>\n </div>\n </div>\n <hr>\n <h6>Current Tasks</h6>\n ${data.current_tasks.length === 0 ? \n '<p class=\"text-muted\">No current tasks</p>' :\n data.current_tasks.map(task => `\n <div class=\"card mb-2\">\n <div class=\"card-body py-2\">\n <div class=\"d-flex justify-content-between\">\n <span><strong>${task.type}</strong> - Volume ${task.volume_id}</span>\n <span class=\"badge bg-info\">${task.status}</span>\n </div>\n <small class=\"text-muted\">${task.reason}</small>\n </div>\n </div>\n `).join('')\n }\n `;\n modal.show();\n })\n .catch(error => {\n console.error('Error loading worker details:', error);\n const content = document.getElementById('workerDetailsContent');\n content.innerHTML = '<div class=\"alert alert-danger\">Failed to load worker details</div>';\n modal.show();\n });\n }\n\n function pauseWorker(event) {\n const workerID = event.target.closest('button').getAttribute('data-worker-id');\n \n if (confirm('Are you sure you want to pause this worker?')) {\n fetch(`/api/maintenance/workers/${workerID}/pause`, {\n method: 'POST'\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('Failed to pause worker: ' + data.error);\n }\n })\n .catch(error => {\n console.error('Error pausing worker:', error);\n alert('Failed to pause worker');\n });\n }\n }\n\n function formatDuration(nanoseconds) {\n const seconds = Math.floor(nanoseconds / 1000000000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n \n if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n } else if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n } else {\n return `${seconds}s`;\n }\n }\n </script>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</div></div></div></div></div><!-- Worker Details Modal --><div class=\"modal fade\" id=\"workerDetailsModal\" tabindex=\"-1\" aria-labelledby=\"workerDetailsModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-lg\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"workerDetailsModalLabel\">Worker Details</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><div class=\"modal-body\" id=\"workerDetailsContent\"><!-- Content will be loaded dynamically --></div></div></div></div><script>\n function showWorkerDetails(event) {\n const workerID = event.target.closest('button').getAttribute('data-worker-id');\n \n // Show modal\n var modal = new bootstrap.Modal(document.getElementById('workerDetailsModal'));\n \n // Load worker details\n fetch('/api/maintenance/workers/' + workerID)\n .then(response => response.json())\n .then(data => {\n const content = document.getElementById('workerDetailsContent');\n content.innerHTML = '<div class=\"row\">' +\n '<div class=\"col-md-6\">' +\n '<h6>Worker Information</h6>' +\n '<ul class=\"list-unstyled\">' +\n '<li><strong>ID:</strong> ' + data.worker.id + '</li>' +\n '<li><strong>Address:</strong> ' + data.worker.address + '</li>' +\n '<li><strong>Status:</strong> ' + data.worker.status + '</li>' +\n '<li><strong>Max Concurrent:</strong> ' + data.worker.max_concurrent + '</li>' +\n '<li><strong>Current Load:</strong> ' + data.worker.current_load + '</li>' +\n '</ul>' +\n '</div>' +\n '<div class=\"col-md-6\">' +\n '<h6>Performance Metrics</h6>' +\n '<ul class=\"list-unstyled\">' +\n '<li><strong>Tasks Completed:</strong> ' + data.performance.tasks_completed + '</li>' +\n '<li><strong>Tasks Failed:</strong> ' + data.performance.tasks_failed + '</li>' +\n '<li><strong>Success Rate:</strong> ' + data.performance.success_rate.toFixed(1) + '%</li>' +\n '<li><strong>Average Task Time:</strong> ' + formatDuration(data.performance.average_task_time) + '</li>' +\n '<li><strong>Uptime:</strong> ' + formatDuration(data.performance.uptime) + '</li>' +\n '</ul>' +\n '</div>' +\n '</div>' +\n '<hr>' +\n '<h6>Current Tasks</h6>' +\n (data.current_tasks.length === 0 ? \n '<p class=\"text-muted\">No current tasks</p>' :\n data.current_tasks.map(task => \n '<div class=\"card mb-2\">' +\n '<div class=\"card-body py-2\">' +\n '<div class=\"d-flex justify-content-between\">' +\n '<span><strong>' + task.type + '</strong> - Volume ' + task.volume_id + '</span>' +\n '<span class=\"badge bg-info\">' + task.status + '</span>' +\n '</div>' +\n '<small class=\"text-muted\">' + task.reason + '</small>' +\n '</div>' +\n '</div>'\n ).join('')\n );\n modal.show();\n })\n .catch(error => {\n console.error('Error loading worker details:', error);\n const content = document.getElementById('workerDetailsContent');\n content.innerHTML = '<div class=\"alert alert-danger\">Failed to load worker details</div>';\n modal.show();\n });\n }\n\n function pauseWorker(event) {\n const workerID = event.target.closest('button').getAttribute('data-worker-id');\n \n if (confirm('Are you sure you want to pause this worker?')) {\n fetch('/api/maintenance/workers/' + workerID + '/pause', {\n method: 'POST'\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('Failed to pause worker: ' + data.error);\n }\n })\n .catch(error => {\n console.error('Error pausing worker:', error);\n alert('Failed to pause worker');\n });\n }\n }\n\n function formatDuration(nanoseconds) {\n const seconds = Math.floor(nanoseconds / 1000000000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n \n if (hours > 0) {\n return hours + 'h ' + (minutes % 60) + 'm';\n } else if (minutes > 0) {\n return minutes + 'm ' + (seconds % 60) + 's';\n } else {\n return seconds + 's';\n }\n }\n </script>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/object_store_users.templ b/weed/admin/view/app/object_store_users.templ index 4b54d5684..7c457a3d8 100644 --- a/weed/admin/view/app/object_store_users.templ +++ b/weed/admin/view/app/object_store_users.templ @@ -133,28 +133,20 @@ templ ObjectStoreUsers(data dash.ObjectStoreUsersData) { </td> <td> <div class="btn-group btn-group-sm" role="group"> - <button type="button" - class="btn btn-outline-info btn-sm" - title="View Details" - onclick={ templ.ComponentScript{Call: fmt.Sprintf("showUserDetails('%s')", user.Username)} }> - <i class="fas fa-eye"></i> + <button type="button" class="btn btn-outline-info" + data-action="show-user-details" data-username={ user.Username }> + <i class="fas fa-info-circle"></i> </button> - <button type="button" - class="btn btn-outline-primary btn-sm" - title="Edit User" - onclick={ templ.ComponentScript{Call: fmt.Sprintf("editUser('%s')", user.Username)} }> + <button type="button" class="btn btn-outline-primary" + data-action="edit-user" data-username={ user.Username }> <i class="fas fa-edit"></i> </button> - <button type="button" - class="btn btn-outline-warning btn-sm" - title="Manage Keys" - onclick={ templ.ComponentScript{Call: fmt.Sprintf("manageAccessKeys('%s')", user.Username)} }> + <button type="button" class="btn btn-outline-secondary" + data-action="manage-access-keys" data-username={ user.Username }> <i class="fas fa-key"></i> </button> - <button type="button" - class="btn btn-outline-danger btn-sm" - title="Delete User" - onclick={ templ.ComponentScript{Call: fmt.Sprintf("deleteUser('%s')", user.Username)} }> + <button type="button" class="btn btn-outline-danger" + data-action="delete-user" data-username={ user.Username }> <i class="fas fa-trash"></i> </button> </div> diff --git a/weed/admin/view/app/object_store_users_templ.go b/weed/admin/view/app/object_store_users_templ.go index 83f5aa948..a4a194d59 100644 --- a/weed/admin/view/app/object_store_users_templ.go +++ b/weed/admin/view/app/object_store_users_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -117,99 +117,83 @@ func ObjectStoreUsers(data dash.ObjectStoreUsersData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</code></td><td><div class=\"btn-group btn-group-sm\" role=\"group\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</code></td><td><div class=\"btn-group btn-group-sm\" role=\"group\"><button type=\"button\" class=\"btn btn-outline-info\" data-action=\"show-user-details\" data-username=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("showUserDetails('%s')", user.Username)}) + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<button type=\"button\" class=\"btn btn-outline-info btn-sm\" title=\"View Details\" onclick=\"") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var8 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("showUserDetails('%s')", user.Username)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8.Call) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"><i class=\"fas fa-eye\"></i></button> ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("editUser('%s')", user.Username)}) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 137, Col: 121} } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Edit User\" onclick=\"") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("editUser('%s')", user.Username)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9.Call) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"><i class=\"fas fa-info-circle\"></i></button> <button type=\"button\" class=\"btn btn-outline-primary\" data-action=\"edit-user\" data-username=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\"><i class=\"fas fa-edit\"></i></button> ") + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 141, Col: 113} } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("manageAccessKeys('%s')", user.Username)}) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<button type=\"button\" class=\"btn btn-outline-warning btn-sm\" title=\"Manage Keys\" onclick=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"><i class=\"fas fa-edit\"></i></button> <button type=\"button\" class=\"btn btn-outline-secondary\" data-action=\"manage-access-keys\" data-username=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var10 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("manageAccessKeys('%s')", user.Username)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10.Call) + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 145, Col: 122} } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\"><i class=\"fas fa-key\"></i></button> ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("deleteUser('%s')", user.Username)}) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\"><i class=\"fas fa-key\"></i></button> <button type=\"button\" class=\"btn btn-outline-danger\" data-action=\"delete-user\" data-username=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<button type=\"button\" class=\"btn btn-outline-danger btn-sm\" title=\"Delete User\" onclick=\"") + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 149, Col: 115} } - var templ_7745c5c3_Var11 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("deleteUser('%s')", user.Username)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11.Call) + _, 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, 16, "\"><i class=\"fas fa-trash\"></i></button></div></td></tr>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\"><i class=\"fas fa-trash\"></i></button></div></td></tr>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(data.Users) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<tr><td colspan=\"4\" class=\"text-center text-muted py-4\"><i class=\"fas fa-users fa-3x mb-3 text-muted\"></i><div><h5>No users found</h5><p>Create your first object store user to get started.</p></div></td></tr>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<tr><td colspan=\"4\" class=\"text-center text-muted py-4\"><i class=\"fas fa-users fa-3x mb-3 text-muted\"></i><div><h5>No users found</h5><p>Create your first object store user to get started.</p></div></td></tr>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</tbody></table></div></div></div></div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"fas fa-clock me-1\"></i> Last updated: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</tbody></table></div></div></div></div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"fas fa-clock me-1\"></i> Last updated: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 188, Col: 81} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/object_store_users.templ`, Line: 180, Col: 81} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</small></div></div></div><!-- Create User Modal --><div class=\"modal fade\" id=\"createUserModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user-plus me-2\"></i>Create New User</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"createUserForm\"><div class=\"mb-3\"><label for=\"username\" class=\"form-label\">Username *</label> <input type=\"text\" class=\"form-control\" id=\"username\" name=\"username\" required></div><div class=\"mb-3\"><label for=\"email\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"email\" name=\"email\"></div><div class=\"mb-3\"><label for=\"actions\" class=\"form-label\">Permissions</label> <select multiple class=\"form-control\" id=\"actions\" name=\"actions\"><option value=\"Admin\">Admin (Full Access)</option> <option value=\"Read\">Read</option> <option value=\"Write\">Write</option> <option value=\"List\">List</option> <option value=\"Tagging\">Tagging</option></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple permissions</small></div><div class=\"mb-3 form-check\"><input type=\"checkbox\" class=\"form-check-input\" id=\"generateKey\" name=\"generateKey\" checked> <label class=\"form-check-label\" for=\"generateKey\">Generate access key automatically</label></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleCreateUser()\">Create User</button></div></div></div></div><!-- Edit User Modal --><div class=\"modal fade\" id=\"editUserModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user-edit me-2\"></i>Edit User</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"editUserForm\"><input type=\"hidden\" id=\"editUsername\" name=\"username\"><div class=\"mb-3\"><label for=\"editEmail\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"editEmail\" name=\"email\"></div><div class=\"mb-3\"><label for=\"editActions\" class=\"form-label\">Permissions</label> <select multiple class=\"form-control\" id=\"editActions\" name=\"actions\"><option value=\"Admin\">Admin (Full Access)</option> <option value=\"Read\">Read</option> <option value=\"Write\">Write</option> <option value=\"List\">List</option> <option value=\"Tagging\">Tagging</option></select></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleUpdateUser()\">Update User</button></div></div></div></div><!-- User Details Modal --><div class=\"modal fade\" id=\"userDetailsModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user me-2\"></i>User Details</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\" id=\"userDetailsContent\"><!-- Content will be loaded dynamically --></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div><!-- Access Keys Management Modal --><div class=\"modal fade\" id=\"accessKeysModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-key me-2\"></i>Manage Access Keys</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><div class=\"d-flex justify-content-between align-items-center mb-3\"><h6>Access Keys for <span id=\"accessKeysUsername\"></span></h6><button type=\"button\" class=\"btn btn-primary btn-sm\" onclick=\"createAccessKey()\"><i class=\"fas fa-plus me-1\"></i>Create New Key</button></div><div id=\"accessKeysContent\"><!-- Content will be loaded dynamically --></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div><!-- JavaScript for user management --><script>\n // User management functions will be included in admin.js\n </script>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</small></div></div></div><!-- Create User Modal --><div class=\"modal fade\" id=\"createUserModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user-plus me-2\"></i>Create New User</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"createUserForm\"><div class=\"mb-3\"><label for=\"username\" class=\"form-label\">Username *</label> <input type=\"text\" class=\"form-control\" id=\"username\" name=\"username\" required></div><div class=\"mb-3\"><label for=\"email\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"email\" name=\"email\"></div><div class=\"mb-3\"><label for=\"actions\" class=\"form-label\">Permissions</label> <select multiple class=\"form-control\" id=\"actions\" name=\"actions\"><option value=\"Admin\">Admin (Full Access)</option> <option value=\"Read\">Read</option> <option value=\"Write\">Write</option> <option value=\"List\">List</option> <option value=\"Tagging\">Tagging</option></select> <small class=\"form-text text-muted\">Hold Ctrl/Cmd to select multiple permissions</small></div><div class=\"mb-3 form-check\"><input type=\"checkbox\" class=\"form-check-input\" id=\"generateKey\" name=\"generateKey\" checked> <label class=\"form-check-label\" for=\"generateKey\">Generate access key automatically</label></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleCreateUser()\">Create User</button></div></div></div></div><!-- Edit User Modal --><div class=\"modal fade\" id=\"editUserModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user-edit me-2\"></i>Edit User</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"editUserForm\"><input type=\"hidden\" id=\"editUsername\" name=\"username\"><div class=\"mb-3\"><label for=\"editEmail\" class=\"form-label\">Email</label> <input type=\"email\" class=\"form-control\" id=\"editEmail\" name=\"email\"></div><div class=\"mb-3\"><label for=\"editActions\" class=\"form-label\">Permissions</label> <select multiple class=\"form-control\" id=\"editActions\" name=\"actions\"><option value=\"Admin\">Admin (Full Access)</option> <option value=\"Read\">Read</option> <option value=\"Write\">Write</option> <option value=\"List\">List</option> <option value=\"Tagging\">Tagging</option></select></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"handleUpdateUser()\">Update User</button></div></div></div></div><!-- User Details Modal --><div class=\"modal fade\" id=\"userDetailsModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-user me-2\"></i>User Details</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\" id=\"userDetailsContent\"><!-- Content will be loaded dynamically --></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div><!-- Access Keys Management Modal --><div class=\"modal fade\" id=\"accessKeysModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-key me-2\"></i>Manage Access Keys</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><div class=\"d-flex justify-content-between align-items-center mb-3\"><h6>Access Keys for <span id=\"accessKeysUsername\"></span></h6><button type=\"button\" class=\"btn btn-primary btn-sm\" onclick=\"createAccessKey()\"><i class=\"fas fa-plus me-1\"></i>Create New Key</button></div><div id=\"accessKeysContent\"><!-- Content will be loaded dynamically --></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Close</button></div></div></div></div><!-- JavaScript for user management --><script>\n // User management functions will be included in admin.js\n </script>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/s3_buckets_templ.go b/weed/admin/view/app/s3_buckets_templ.go index 303f2406e..0912a51c5 100644 --- a/weed/admin/view/app/s3_buckets_templ.go +++ b/weed/admin/view/app/s3_buckets_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -82,8 +82,12 @@ func S3Buckets(data dash.S3BucketsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/s3/buckets/%s", bucket.Name)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5))) + var templ_7745c5c3_Var5 templ.SafeURL + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/s3/buckets/%s", bucket.Name))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 129, Col: 114} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -277,8 +281,12 @@ func S3Buckets(data dash.S3BucketsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var16 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/files?path=/buckets/%s", bucket.Name)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var16))) + var templ_7745c5c3_Var16 templ.SafeURL + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/files?path=/buckets/%s", bucket.Name))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 185, Col: 127} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -286,8 +294,12 @@ func S3Buckets(data dash.S3BucketsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var17 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/s3/buckets/%s", bucket.Name)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var17))) + var templ_7745c5c3_Var17 templ.SafeURL + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/s3/buckets/%s", bucket.Name))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 190, Col: 118} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/subscribers_templ.go b/weed/admin/view/app/subscribers_templ.go index 4bb944df0..6a14ff401 100644 --- a/weed/admin/view/app/subscribers_templ.go +++ b/weed/admin/view/app/subscribers_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/app/task_config_templ.go b/weed/admin/view/app/task_config_templ.go index 5465df8a6..d690b2d03 100644 --- a/weed/admin/view/app/task_config_templ.go +++ b/weed/admin/view/app/task_config_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/app/task_config_templ_templ.go b/weed/admin/view/app/task_config_templ_templ.go index c900f132f..bed2e7519 100644 --- a/weed/admin/view/app/task_config_templ_templ.go +++ b/weed/admin/view/app/task_config_templ_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/app/topic_details_templ.go b/weed/admin/view/app/topic_details_templ.go index 4dd53583d..7d8394380 100644 --- a/weed/admin/view/app/topic_details_templ.go +++ b/weed/admin/view/app/topic_details_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/app/topics.templ b/weed/admin/view/app/topics.templ index 47c6625ae..4a69b0c54 100644 --- a/weed/admin/view/app/topics.templ +++ b/weed/admin/view/app/topics.templ @@ -102,8 +102,8 @@ templ Topics(data dash.TopicsData) { } </td> <td> - <button class="btn btn-sm btn-outline-primary" onclick={ templ.ComponentScript{Call: fmt.Sprintf("viewTopicDetails('%s')", topic.Name)} }> - <i class="fas fa-info-circle me-1"></i>Details + <button class="btn btn-sm btn-outline-primary" data-action="view-topic-details" data-topic-name={ topic.Name }> + <i class="fas fa-eye"></i> </button> </td> </tr> @@ -127,297 +127,6 @@ templ Topics(data dash.TopicsData) { </div> </div> - <script> - function viewTopicDetails(topicName) { - const parts = topicName.split('.'); - if (parts.length >= 2) { - const namespace = parts[0]; - const topic = parts.slice(1).join('.'); - window.location.href = `/mq/topics/${namespace}/${topic}`; - } - } - - function toggleTopicDetails(topicName) { - const safeName = topicName.replace(/\./g, '_'); - const detailsRow = document.getElementById(`details-${safeName}`); - if (!detailsRow) return; - - if (detailsRow.style.display === 'none') { - // Show details row and load data - detailsRow.style.display = 'table-row'; - loadTopicDetails(topicName); - } else { - // Hide details row - detailsRow.style.display = 'none'; - } - } - - function loadTopicDetails(topicName) { - const parts = topicName.split('.'); - if (parts.length < 2) return; - - const namespace = parts[0]; - const topic = parts.slice(1).join('.'); - const safeName = topicName.replace(/\./g, '_'); - const contentDiv = document.querySelector(`#details-${safeName} .topic-details-content`); - - if (!contentDiv) return; - - // Show loading spinner - contentDiv.innerHTML = ` - <div class="text-center py-3"> - <i class="fas fa-spinner fa-spin"></i> Loading topic details... - </div> - `; - - // Make AJAX call to get topic details - fetch(`/api/mq/topics/${namespace}/${topic}`) - .then(response => response.json()) - .then(data => { - if (data.error) { - contentDiv.innerHTML = ` - <div class="alert alert-danger" role="alert"> - <i class="fas fa-exclamation-triangle"></i> Error: ${data.error} - </div> - `; - return; - } - - // Render topic details - contentDiv.innerHTML = renderTopicDetails(data); - }) - .catch(error => { - contentDiv.innerHTML = ` - <div class="alert alert-danger" role="alert"> - <i class="fas fa-exclamation-triangle"></i> Failed to load topic details: ${error.message} - </div> - `; - }); - } - - function renderTopicDetails(data) { - const createdAt = new Date(data.created_at).toLocaleString(); - const lastUpdated = new Date(data.last_updated).toLocaleString(); - - let schemaHtml = ''; - if (data.schema && data.schema.length > 0) { - schemaHtml = ` - <div class="col-md-6"> - <h6>Schema Fields</h6> - <div class="table-responsive"> - <table class="table table-sm"> - <thead> - <tr> - <th>Field</th> - <th>Type</th> - <th>Required</th> - </tr> - </thead> - <tbody> - ${data.schema.map(field => ` - <tr> - <td>${field.name}</td> - <td><span class="badge bg-secondary">${field.type}</span></td> - <td>${field.required ? '<span class="badge bg-success">Yes</span>' : '<span class="badge bg-light text-dark">No</span>'}</td> - </tr> - `).join('')} - </tbody> - </table> - </div> - </div> - `; - } - - let partitionsHtml = ''; - if (data.partitions && data.partitions.length > 0) { - partitionsHtml = ` - <div class="col-md-6"> - <h6>Partitions</h6> - <div class="table-responsive"> - <table class="table table-sm"> - <thead> - <tr> - <th>ID</th> - <th>Leader</th> - <th>Follower</th> - </tr> - </thead> - <tbody> - ${data.partitions.map(partition => ` - <tr> - <td>${partition.id}</td> - <td>${partition.leader_broker || 'N/A'}</td> - <td>${partition.follower_broker || 'N/A'}</td> - </tr> - `).join('')} - </tbody> - </table> - </div> - </div> - `; - } - - - - - - return ` - <div class="card"> - <div class="card-header"> - <h5>Topic Details: ${data.namespace}.${data.name}</h5> - </div> - <div class="card-body"> - <div class="row mb-3"> - <div class="col-md-3"> - <strong>Namespace:</strong> ${data.namespace} - </div> - <div class="col-md-3"> - <strong>Topic Name:</strong> ${data.name} - </div> - <div class="col-md-3"> - <strong>Created:</strong> ${createdAt} - </div> - <div class="col-md-3"> - <strong>Last Updated:</strong> ${lastUpdated} - </div> - </div> - <div class="row mb-3"> - ${schemaHtml} - ${partitionsHtml} - </div> - - </div> - </div> - `; - } - - function exportTopicsCSV() { - const table = document.getElementById('topicsTable'); - if (!table) return; - - let csv = 'Namespace,Topic Name,Partitions,Retention\n'; - - const rows = table.querySelectorAll('tbody tr.topic-row'); - rows.forEach(row => { - const cells = row.querySelectorAll('td'); - if (cells.length >= 4) { - const rowData = [ - cells[0].querySelector('.badge')?.textContent || '', // Namespace - cells[1].querySelector('strong')?.textContent || '', // Topic Name - cells[2].querySelector('.badge')?.textContent || '', // Partitions - cells[3].querySelector('.badge')?.textContent || '' // Retention - ]; - csv += rowData.map(field => `"${field.replace(/"/g, '""')}"`).join(',') + '\n'; - } - }); - - const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); - const link = document.createElement('a'); - const url = URL.createObjectURL(blob); - link.setAttribute('href', url); - link.setAttribute('download', 'topics.csv'); - link.style.visibility = 'hidden'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } - - // Topic creation functions - function showCreateTopicModal() { - const modal = new bootstrap.Modal(document.getElementById('createTopicModal')); - modal.show(); - } - - function toggleRetentionFields() { - const enableRetention = document.getElementById('enableRetention'); - const retentionFields = document.getElementById('retentionFields'); - - if (enableRetention.checked) { - retentionFields.style.display = 'block'; - } else { - retentionFields.style.display = 'none'; - } - } - - function createTopic() { - const form = document.getElementById('createTopicForm'); - const formData = new FormData(form); - - // Convert form data to JSON - const data = { - namespace: formData.get('namespace'), - name: formData.get('name'), - partition_count: parseInt(formData.get('partitionCount')), - retention: { - enabled: formData.get('enableRetention') === 'on', - retention_seconds: 0 - } - }; - - // Calculate retention seconds if enabled - if (data.retention.enabled) { - const retentionValue = parseInt(formData.get('retentionValue')); - const retentionUnit = formData.get('retentionUnit'); - - if (retentionUnit === 'hours') { - data.retention.retention_seconds = retentionValue * 3600; - } else if (retentionUnit === 'days') { - data.retention.retention_seconds = retentionValue * 86400; - } - } - - // Validate required fields - if (!data.namespace || !data.name || !data.partition_count) { - alert('Please fill in all required fields'); - return; - } - - // Show loading state - const createButton = document.querySelector('#createTopicModal .btn-primary'); - createButton.disabled = true; - createButton.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Creating...'; - - // Send API request - fetch('/api/mq/topics/create', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data) - }) - .then(response => response.json()) - .then(result => { - if (result.error) { - alert('Failed to create topic: ' + result.error); - } else { - alert('Topic created successfully!'); - // Close modal and refresh page - const modal = bootstrap.Modal.getInstance(document.getElementById('createTopicModal')); - modal.hide(); - window.location.reload(); - } - }) - .catch(error => { - alert('Failed to create topic: ' + error.message); - }) - .finally(() => { - // Reset button state - createButton.disabled = false; - createButton.innerHTML = '<i class="fas fa-plus me-1"></i>Create Topic'; - }); - } - - // Add click event listeners to topic rows - document.addEventListener('DOMContentLoaded', function() { - document.querySelectorAll('.topic-row').forEach(row => { - row.addEventListener('click', function() { - const topicName = this.getAttribute('data-topic-name'); - toggleTopicDetails(topicName); - }); - }); - }); - </script> - <!-- Create Topic Modal --> <div class="modal fade" id="createTopicModal" tabindex="-1" role="dialog"> <div class="modal-dialog modal-lg" role="document"> @@ -508,4 +217,172 @@ templ Topics(data dash.TopicsData) { </div> </div> </div> + + <script type="text/javascript"> + // Topic management functions + function showCreateTopicModal() { + var modal = new bootstrap.Modal(document.getElementById('createTopicModal')); + modal.show(); + } + + function toggleRetentionFields() { + var enableRetention = document.getElementById('enableRetention').checked; + var retentionFields = document.getElementById('retentionFields'); + + if (enableRetention) { + retentionFields.style.display = 'block'; + } else { + retentionFields.style.display = 'none'; + } + } + + function createTopic() { + var form = document.getElementById('createTopicForm'); + var formData = new FormData(form); + + if (!form.checkValidity()) { + form.classList.add('was-validated'); + return; + } + + var namespace = formData.get('namespace'); + var name = formData.get('name'); + var partitionCount = formData.get('partitionCount'); + var enableRetention = formData.get('enableRetention'); + var retentionValue = enableRetention === 'on' ? parseInt(formData.get('retentionValue')) : 0; + var retentionUnit = enableRetention === 'on' ? formData.get('retentionUnit') : 'hours'; + + // Convert retention to seconds + var retentionSeconds = 0; + if (enableRetention === 'on' && retentionValue > 0) { + if (retentionUnit === 'hours') { + retentionSeconds = retentionValue * 3600; + } else if (retentionUnit === 'days') { + retentionSeconds = retentionValue * 86400; + } + } + + var topicData = { + namespace: namespace, + name: name, + partition_count: parseInt(partitionCount), + retention: { + enabled: enableRetention === 'on', + retention_seconds: retentionSeconds + } + }; + + // Create the topic + fetch('/api/mq/topics/create', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(topicData) + }) + .then(response => { + if (response.ok) { + return response.json(); + } + throw new Error('Failed to create topic'); + }) + .then(data => { + // Hide modal and refresh page + var modal = bootstrap.Modal.getInstance(document.getElementById('createTopicModal')); + modal.hide(); + location.reload(); + }) + .catch(error => { + console.error('Error:', error); + alert('Error creating topic: ' + error.message); + }); + } + + function exportTopicsCSV() { + var csvContent = 'Namespace,Topic Name,Partitions,Retention Enabled,Retention Value,Retention Unit\n'; + + var rows = document.querySelectorAll('#topicsTable tbody tr.topic-row'); + rows.forEach(function(row) { + var cells = row.querySelectorAll('td'); + var namespace = cells[0].textContent.trim(); + var topicName = cells[1].textContent.trim(); + var partitions = cells[2].textContent.trim(); + var retention = cells[3].textContent.trim(); + + var retentionEnabled = retention !== 'Disabled'; + var retentionValue = retentionEnabled ? retention.split(' ')[0] : ''; + var retentionUnit = retentionEnabled ? retention.split(' ')[1] : ''; + + csvContent += namespace + ',' + topicName + ',' + partitions + ',' + retentionEnabled + ',' + retentionValue + ',' + retentionUnit + '\n'; + }); + + var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); + var link = document.createElement('a'); + var url = URL.createObjectURL(blob); + link.setAttribute('href', url); + link.setAttribute('download', 'topics_export.csv'); + link.style.visibility = 'hidden'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + + // Topic details functionality + document.addEventListener('DOMContentLoaded', function() { + // Handle view topic details buttons + document.querySelectorAll('[data-action="view-topic-details"]').forEach(function(button) { + button.addEventListener('click', function(e) { + e.stopPropagation(); + var topicName = this.getAttribute('data-topic-name'); + var detailsRow = document.getElementById('details-' + topicName.replace(/\./g, '_')); + + if (detailsRow.style.display === 'none') { + detailsRow.style.display = 'table-row'; + this.innerHTML = '<i class="fas fa-eye-slash"></i>'; + + // Load topic details + loadTopicDetails(topicName); + } else { + detailsRow.style.display = 'none'; + this.innerHTML = '<i class="fas fa-eye"></i>'; + } + }); + }); + }); + + function loadTopicDetails(topicName) { + var detailsRow = document.getElementById('details-' + topicName.replace(/\./g, '_')); + var contentDiv = detailsRow.querySelector('.topic-details-content'); + + fetch('/admin/topics/' + encodeURIComponent(topicName) + '/details') + .then(response => response.json()) + .then(data => { + var html = '<div class="row">'; + html += '<div class="col-md-6">'; + html += '<h6>Topic Configuration</h6>'; + html += '<ul class="list-unstyled">'; + html += '<li><strong>Full Name:</strong> ' + data.name + '</li>'; + html += '<li><strong>Partitions:</strong> ' + data.partitions + '</li>'; + html += '<li><strong>Created:</strong> ' + (data.created || 'N/A') + '</li>'; + html += '</ul>'; + html += '</div>'; + html += '<div class="col-md-6">'; + html += '<h6>Retention Policy</h6>'; + if (data.retention && data.retention.enabled) { + html += '<p><i class="fas fa-check-circle text-success"></i> Enabled</p>'; + html += '<p><strong>Duration:</strong> ' + data.retention.value + ' ' + data.retention.unit + '</p>'; + } else { + html += '<p><i class="fas fa-times-circle text-danger"></i> Disabled</p>'; + } + html += '</div>'; + html += '</div>'; + + contentDiv.innerHTML = html; + }) + .catch(error => { + console.error('Error loading topic details:', error); + contentDiv.innerHTML = '<div class="alert alert-danger">Failed to load topic details</div>'; + }); + } + </script> }
\ No newline at end of file diff --git a/weed/admin/view/app/topics_templ.go b/weed/admin/view/app/topics_templ.go index 2b753adfc..c8e665d32 100644 --- a/weed/admin/view/app/topics_templ.go +++ b/weed/admin/view/app/topics_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -179,24 +179,20 @@ func Topics(data dash.TopicsData) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</td><td>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</td><td><button class=\"btn btn-sm btn-outline-primary\" data-action=\"view-topic-details\" data-topic-name=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.ComponentScript{Call: fmt.Sprintf("viewTopicDetails('%s')", topic.Name)}) + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(topic.Name) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<button class=\"btn btn-sm btn-outline-primary\" onclick=\"") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/topics.templ`, Line: 105, Col: 160} } - var templ_7745c5c3_Var10 templ.ComponentScript = templ.ComponentScript{Call: fmt.Sprintf("viewTopicDetails('%s')", topic.Name)} - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10.Call) + _, 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, 17, "\"><i class=\"fas fa-info-circle me-1\"></i>Details</button></td></tr><tr class=\"topic-details-row\" id=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"><i class=\"fas fa-eye\"></i></button></td></tr><tr class=\"topic-details-row\" id=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -209,17 +205,17 @@ func Topics(data dash.TopicsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" style=\"display: none;\"><td colspan=\"5\"><div class=\"topic-details-content\"><div class=\"text-center py-3\"><i class=\"fas fa-spinner fa-spin\"></i> Loading topic details...</div></div></td></tr>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" style=\"display: none;\"><td colspan=\"5\"><div class=\"topic-details-content\"><div class=\"text-center py-3\"><i class=\"fas fa-spinner fa-spin\"></i> Loading topic details...</div></div></td></tr>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</tbody></table></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</tbody></table></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div></div></div></div></div><script>\n function viewTopicDetails(topicName) {\n const parts = topicName.split('.');\n if (parts.length >= 2) {\n const namespace = parts[0];\n const topic = parts.slice(1).join('.');\n window.location.href = `/mq/topics/${namespace}/${topic}`;\n }\n }\n\n function toggleTopicDetails(topicName) {\n const safeName = topicName.replace(/\\./g, '_');\n const detailsRow = document.getElementById(`details-${safeName}`);\n if (!detailsRow) return;\n\n if (detailsRow.style.display === 'none') {\n // Show details row and load data\n detailsRow.style.display = 'table-row';\n loadTopicDetails(topicName);\n } else {\n // Hide details row\n detailsRow.style.display = 'none';\n }\n }\n\n function loadTopicDetails(topicName) {\n const parts = topicName.split('.');\n if (parts.length < 2) return;\n \n const namespace = parts[0];\n const topic = parts.slice(1).join('.');\n const safeName = topicName.replace(/\\./g, '_');\n const contentDiv = document.querySelector(`#details-${safeName} .topic-details-content`);\n \n if (!contentDiv) return;\n\n // Show loading spinner\n contentDiv.innerHTML = `\n <div class=\"text-center py-3\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading topic details...\n </div>\n `;\n\n // Make AJAX call to get topic details\n fetch(`/api/mq/topics/${namespace}/${topic}`)\n .then(response => response.json())\n .then(data => {\n if (data.error) {\n contentDiv.innerHTML = `\n <div class=\"alert alert-danger\" role=\"alert\">\n <i class=\"fas fa-exclamation-triangle\"></i> Error: ${data.error}\n </div>\n `;\n return;\n }\n\n // Render topic details\n contentDiv.innerHTML = renderTopicDetails(data);\n })\n .catch(error => {\n contentDiv.innerHTML = `\n <div class=\"alert alert-danger\" role=\"alert\">\n <i class=\"fas fa-exclamation-triangle\"></i> Failed to load topic details: ${error.message}\n </div>\n `;\n });\n }\n\n function renderTopicDetails(data) {\n const createdAt = new Date(data.created_at).toLocaleString();\n const lastUpdated = new Date(data.last_updated).toLocaleString();\n\n let schemaHtml = '';\n if (data.schema && data.schema.length > 0) {\n schemaHtml = `\n <div class=\"col-md-6\">\n <h6>Schema Fields</h6>\n <div class=\"table-responsive\">\n <table class=\"table table-sm\">\n <thead>\n <tr>\n <th>Field</th>\n <th>Type</th>\n <th>Required</th>\n </tr>\n </thead>\n <tbody>\n ${data.schema.map(field => `\n <tr>\n <td>${field.name}</td>\n <td><span class=\"badge bg-secondary\">${field.type}</span></td>\n <td>${field.required ? '<span class=\"badge bg-success\">Yes</span>' : '<span class=\"badge bg-light text-dark\">No</span>'}</td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>\n </div>\n `;\n }\n\n let partitionsHtml = '';\n if (data.partitions && data.partitions.length > 0) {\n partitionsHtml = `\n <div class=\"col-md-6\">\n <h6>Partitions</h6>\n <div class=\"table-responsive\">\n <table class=\"table table-sm\">\n <thead>\n <tr>\n <th>ID</th>\n <th>Leader</th>\n <th>Follower</th>\n </tr>\n </thead>\n <tbody>\n ${data.partitions.map(partition => `\n <tr>\n <td>${partition.id}</td>\n <td>${partition.leader_broker || 'N/A'}</td>\n <td>${partition.follower_broker || 'N/A'}</td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>\n </div>\n `;\n }\n\n\n\n\n\n return `\n <div class=\"card\">\n <div class=\"card-header\">\n <h5>Topic Details: ${data.namespace}.${data.name}</h5>\n </div>\n <div class=\"card-body\">\n <div class=\"row mb-3\">\n <div class=\"col-md-3\">\n <strong>Namespace:</strong> ${data.namespace}\n </div>\n <div class=\"col-md-3\">\n <strong>Topic Name:</strong> ${data.name}\n </div>\n <div class=\"col-md-3\">\n <strong>Created:</strong> ${createdAt}\n </div>\n <div class=\"col-md-3\">\n <strong>Last Updated:</strong> ${lastUpdated}\n </div>\n </div>\n <div class=\"row mb-3\">\n ${schemaHtml}\n ${partitionsHtml}\n </div>\n\n </div>\n </div>\n `;\n }\n\n function exportTopicsCSV() {\n const table = document.getElementById('topicsTable');\n if (!table) return;\n \n let csv = 'Namespace,Topic Name,Partitions,Retention\\n';\n \n const rows = table.querySelectorAll('tbody tr.topic-row');\n rows.forEach(row => {\n const cells = row.querySelectorAll('td');\n if (cells.length >= 4) {\n const rowData = [\n cells[0].querySelector('.badge')?.textContent || '', // Namespace\n cells[1].querySelector('strong')?.textContent || '', // Topic Name\n cells[2].querySelector('.badge')?.textContent || '', // Partitions\n cells[3].querySelector('.badge')?.textContent || '' // Retention\n ];\n csv += rowData.map(field => `\"${field.replace(/\"/g, '\"\"')}\"`).join(',') + '\\n';\n }\n });\n \n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const link = document.createElement('a');\n const url = URL.createObjectURL(blob);\n link.setAttribute('href', url);\n link.setAttribute('download', 'topics.csv');\n link.style.visibility = 'hidden';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n\n // Topic creation functions\n function showCreateTopicModal() {\n const modal = new bootstrap.Modal(document.getElementById('createTopicModal'));\n modal.show();\n }\n\n function toggleRetentionFields() {\n const enableRetention = document.getElementById('enableRetention');\n const retentionFields = document.getElementById('retentionFields');\n \n if (enableRetention.checked) {\n retentionFields.style.display = 'block';\n } else {\n retentionFields.style.display = 'none';\n }\n }\n\n function createTopic() {\n const form = document.getElementById('createTopicForm');\n const formData = new FormData(form);\n \n // Convert form data to JSON\n const data = {\n namespace: formData.get('namespace'),\n name: formData.get('name'),\n partition_count: parseInt(formData.get('partitionCount')),\n retention: {\n enabled: formData.get('enableRetention') === 'on',\n retention_seconds: 0\n }\n };\n\n // Calculate retention seconds if enabled\n if (data.retention.enabled) {\n const retentionValue = parseInt(formData.get('retentionValue'));\n const retentionUnit = formData.get('retentionUnit');\n \n if (retentionUnit === 'hours') {\n data.retention.retention_seconds = retentionValue * 3600;\n } else if (retentionUnit === 'days') {\n data.retention.retention_seconds = retentionValue * 86400;\n }\n }\n\n // Validate required fields\n if (!data.namespace || !data.name || !data.partition_count) {\n alert('Please fill in all required fields');\n return;\n }\n\n // Show loading state\n const createButton = document.querySelector('#createTopicModal .btn-primary');\n createButton.disabled = true;\n createButton.innerHTML = '<i class=\"fas fa-spinner fa-spin me-1\"></i>Creating...';\n\n // Send API request\n fetch('/api/mq/topics/create', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data)\n })\n .then(response => response.json())\n .then(result => {\n if (result.error) {\n alert('Failed to create topic: ' + result.error);\n } else {\n alert('Topic created successfully!');\n // Close modal and refresh page\n const modal = bootstrap.Modal.getInstance(document.getElementById('createTopicModal'));\n modal.hide();\n window.location.reload();\n }\n })\n .catch(error => {\n alert('Failed to create topic: ' + error.message);\n })\n .finally(() => {\n // Reset button state\n createButton.disabled = false;\n createButton.innerHTML = '<i class=\"fas fa-plus me-1\"></i>Create Topic';\n });\n }\n\n // Add click event listeners to topic rows\n document.addEventListener('DOMContentLoaded', function() {\n document.querySelectorAll('.topic-row').forEach(row => {\n row.addEventListener('click', function() {\n const topicName = this.getAttribute('data-topic-name');\n toggleTopicDetails(topicName);\n });\n });\n });\n </script><!-- Create Topic Modal --><div class=\"modal fade\" id=\"createTopicModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-plus me-2\"></i>Create New Topic</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"createTopicForm\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicNamespace\" class=\"form-label\">Namespace *</label> <input type=\"text\" class=\"form-control\" id=\"topicNamespace\" name=\"namespace\" required placeholder=\"e.g., default\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicName\" class=\"form-label\">Topic Name *</label> <input type=\"text\" class=\"form-control\" id=\"topicName\" name=\"name\" required placeholder=\"e.g., user-events\"></div></div></div><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"partitionCount\" class=\"form-label\">Partition Count *</label> <input type=\"number\" class=\"form-control\" id=\"partitionCount\" name=\"partitionCount\" required min=\"1\" max=\"100\" value=\"6\"></div></div></div><!-- Retention Configuration --><div class=\"card mt-3\"><div class=\"card-header\"><h6 class=\"mb-0\"><i class=\"fas fa-clock me-2\"></i>Retention Policy</h6></div><div class=\"card-body\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableRetention\" name=\"enableRetention\" onchange=\"toggleRetentionFields()\"> <label class=\"form-check-label\" for=\"enableRetention\">Enable data retention</label></div><div id=\"retentionFields\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionValue\" class=\"form-label\">Retention Duration</label> <input type=\"number\" class=\"form-control\" id=\"retentionValue\" name=\"retentionValue\" min=\"1\" value=\"7\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionUnit\" class=\"form-label\">Unit</label> <select class=\"form-control\" id=\"retentionUnit\" name=\"retentionUnit\"><option value=\"hours\">Hours</option> <option value=\"days\" selected>Days</option></select></div></div></div><div class=\"alert alert-info\"><i class=\"fas fa-info-circle me-2\"></i> Data older than this duration will be automatically purged to save storage space.</div></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"createTopic()\"><i class=\"fas fa-plus me-1\"></i>Create Topic</button></div></div></div></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div></div></div></div></div><!-- Create Topic Modal --><div class=\"modal fade\" id=\"createTopicModal\" tabindex=\"-1\" role=\"dialog\"><div class=\"modal-dialog modal-lg\" role=\"document\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"fas fa-plus me-2\"></i>Create New Topic</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button></div><div class=\"modal-body\"><form id=\"createTopicForm\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicNamespace\" class=\"form-label\">Namespace *</label> <input type=\"text\" class=\"form-control\" id=\"topicNamespace\" name=\"namespace\" required placeholder=\"e.g., default\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"topicName\" class=\"form-label\">Topic Name *</label> <input type=\"text\" class=\"form-control\" id=\"topicName\" name=\"name\" required placeholder=\"e.g., user-events\"></div></div></div><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"partitionCount\" class=\"form-label\">Partition Count *</label> <input type=\"number\" class=\"form-control\" id=\"partitionCount\" name=\"partitionCount\" required min=\"1\" max=\"100\" value=\"6\"></div></div></div><!-- Retention Configuration --><div class=\"card mt-3\"><div class=\"card-header\"><h6 class=\"mb-0\"><i class=\"fas fa-clock me-2\"></i>Retention Policy</h6></div><div class=\"card-body\"><div class=\"form-check mb-3\"><input class=\"form-check-input\" type=\"checkbox\" id=\"enableRetention\" name=\"enableRetention\" onchange=\"toggleRetentionFields()\"> <label class=\"form-check-label\" for=\"enableRetention\">Enable data retention</label></div><div id=\"retentionFields\" style=\"display: none;\"><div class=\"row\"><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionValue\" class=\"form-label\">Retention Duration</label> <input type=\"number\" class=\"form-control\" id=\"retentionValue\" name=\"retentionValue\" min=\"1\" value=\"7\"></div></div><div class=\"col-md-6\"><div class=\"mb-3\"><label for=\"retentionUnit\" class=\"form-label\">Unit</label> <select class=\"form-control\" id=\"retentionUnit\" name=\"retentionUnit\"><option value=\"hours\">Hours</option> <option value=\"days\" selected>Days</option></select></div></div></div><div class=\"alert alert-info\"><i class=\"fas fa-info-circle me-2\"></i> Data older than this duration will be automatically purged to save storage space.</div></div></div></div></form></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"button\" class=\"btn btn-primary\" onclick=\"createTopic()\"><i class=\"fas fa-plus me-1\"></i>Create Topic</button></div></div></div></div><script type=\"text/javascript\">\n // Topic management functions\n function showCreateTopicModal() {\n var modal = new bootstrap.Modal(document.getElementById('createTopicModal'));\n modal.show();\n }\n\n function toggleRetentionFields() {\n var enableRetention = document.getElementById('enableRetention').checked;\n var retentionFields = document.getElementById('retentionFields');\n \n if (enableRetention) {\n retentionFields.style.display = 'block';\n } else {\n retentionFields.style.display = 'none';\n }\n }\n\n function createTopic() {\n var form = document.getElementById('createTopicForm');\n var formData = new FormData(form);\n \n if (!form.checkValidity()) {\n form.classList.add('was-validated');\n return;\n }\n \n var namespace = formData.get('namespace');\n var name = formData.get('name');\n var partitionCount = formData.get('partitionCount');\n var enableRetention = formData.get('enableRetention');\n var retentionValue = enableRetention === 'on' ? parseInt(formData.get('retentionValue')) : 0;\n var retentionUnit = enableRetention === 'on' ? formData.get('retentionUnit') : 'hours';\n \n // Convert retention to seconds\n var retentionSeconds = 0;\n if (enableRetention === 'on' && retentionValue > 0) {\n if (retentionUnit === 'hours') {\n retentionSeconds = retentionValue * 3600;\n } else if (retentionUnit === 'days') {\n retentionSeconds = retentionValue * 86400;\n }\n }\n \n var topicData = {\n namespace: namespace,\n name: name,\n partition_count: parseInt(partitionCount),\n retention: {\n enabled: enableRetention === 'on',\n retention_seconds: retentionSeconds\n }\n };\n \n // Create the topic\n fetch('/api/mq/topics/create', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(topicData)\n })\n .then(response => {\n if (response.ok) {\n return response.json();\n }\n throw new Error('Failed to create topic');\n })\n .then(data => {\n // Hide modal and refresh page\n var modal = bootstrap.Modal.getInstance(document.getElementById('createTopicModal'));\n modal.hide();\n location.reload();\n })\n .catch(error => {\n console.error('Error:', error);\n alert('Error creating topic: ' + error.message);\n });\n }\n\n function exportTopicsCSV() {\n var csvContent = 'Namespace,Topic Name,Partitions,Retention Enabled,Retention Value,Retention Unit\\n';\n \n var rows = document.querySelectorAll('#topicsTable tbody tr.topic-row');\n rows.forEach(function(row) {\n var cells = row.querySelectorAll('td');\n var namespace = cells[0].textContent.trim();\n var topicName = cells[1].textContent.trim();\n var partitions = cells[2].textContent.trim();\n var retention = cells[3].textContent.trim();\n \n var retentionEnabled = retention !== 'Disabled';\n var retentionValue = retentionEnabled ? retention.split(' ')[0] : '';\n var retentionUnit = retentionEnabled ? retention.split(' ')[1] : '';\n \n csvContent += namespace + ',' + topicName + ',' + partitions + ',' + retentionEnabled + ',' + retentionValue + ',' + retentionUnit + '\\n';\n });\n \n var blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n var link = document.createElement('a');\n var url = URL.createObjectURL(blob);\n link.setAttribute('href', url);\n link.setAttribute('download', 'topics_export.csv');\n link.style.visibility = 'hidden';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n\n // Topic details functionality\n document.addEventListener('DOMContentLoaded', function() {\n // Handle view topic details buttons\n document.querySelectorAll('[data-action=\"view-topic-details\"]').forEach(function(button) {\n button.addEventListener('click', function(e) {\n e.stopPropagation();\n var topicName = this.getAttribute('data-topic-name');\n var detailsRow = document.getElementById('details-' + topicName.replace(/\\./g, '_'));\n \n if (detailsRow.style.display === 'none') {\n detailsRow.style.display = 'table-row';\n this.innerHTML = '<i class=\"fas fa-eye-slash\"></i>';\n \n // Load topic details\n loadTopicDetails(topicName);\n } else {\n detailsRow.style.display = 'none';\n this.innerHTML = '<i class=\"fas fa-eye\"></i>';\n }\n });\n });\n });\n\n function loadTopicDetails(topicName) {\n var detailsRow = document.getElementById('details-' + topicName.replace(/\\./g, '_'));\n var contentDiv = detailsRow.querySelector('.topic-details-content');\n \n fetch('/admin/topics/' + encodeURIComponent(topicName) + '/details')\n .then(response => response.json())\n .then(data => {\n var html = '<div class=\"row\">';\n html += '<div class=\"col-md-6\">';\n html += '<h6>Topic Configuration</h6>';\n html += '<ul class=\"list-unstyled\">';\n html += '<li><strong>Full Name:</strong> ' + data.name + '</li>';\n html += '<li><strong>Partitions:</strong> ' + data.partitions + '</li>';\n html += '<li><strong>Created:</strong> ' + (data.created || 'N/A') + '</li>';\n html += '</ul>';\n html += '</div>';\n html += '<div class=\"col-md-6\">';\n html += '<h6>Retention Policy</h6>';\n if (data.retention && data.retention.enabled) {\n html += '<p><i class=\"fas fa-check-circle text-success\"></i> Enabled</p>';\n html += '<p><strong>Duration:</strong> ' + data.retention.value + ' ' + data.retention.unit + '</p>';\n } else {\n html += '<p><i class=\"fas fa-times-circle text-danger\"></i> Disabled</p>';\n }\n html += '</div>';\n html += '</div>';\n \n contentDiv.innerHTML = html;\n })\n .catch(error => {\n console.error('Error loading topic details:', error);\n contentDiv.innerHTML = '<div class=\"alert alert-danger\">Failed to load topic details</div>';\n });\n }\n </script>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/volume_details_templ.go b/weed/admin/view/app/volume_details_templ.go index 2e6bb3782..3662e1cc1 100644 --- a/weed/admin/view/app/volume_details_templ.go +++ b/weed/admin/view/app/volume_details_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package app //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -65,8 +65,12 @@ func VolumeDetails(data dash.VolumeDetailsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", data.Volume.Server)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) + var templ_7745c5c3_Var4 templ.SafeURL + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", data.Volume.Server))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 54, Col: 118} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -118,8 +122,12 @@ func VolumeDetails(data dash.VolumeDetailsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL("/cluster/volumes?collection=default") - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8))) + var templ_7745c5c3_Var8 templ.SafeURL + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("/cluster/volumes?collection=default")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 74, Col: 101} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -132,8 +140,12 @@ func VolumeDetails(data dash.VolumeDetailsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", data.Volume.Collection)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9))) + var templ_7745c5c3_Var9 templ.SafeURL + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/cluster/volumes?collection=%s", data.Volume.Collection))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 78, Col: 133} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -461,8 +473,12 @@ func VolumeDetails(data dash.VolumeDetailsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var28 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", data.Volume.Server)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var28))) + var templ_7745c5c3_Var28 templ.SafeURL + templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", data.Volume.Server))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 301, Col: 130} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -540,8 +556,12 @@ func VolumeDetails(data dash.VolumeDetailsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var34 templ.SafeURL = templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", replica.Server)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var34))) + var templ_7745c5c3_Var34 templ.SafeURL + templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("http://%s/ui/index.html", replica.Server))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 321, Col: 126} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -614,8 +634,12 @@ func VolumeDetails(data dash.VolumeDetailsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var40 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/cluster/volumes/%d/%s", replica.Id, replica.Server)) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var40))) + var templ_7745c5c3_Var40 templ.SafeURL + templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/cluster/volumes/%d/%s", replica.Id, replica.Server))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/volume_details.templ`, Line: 332, Col: 137} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/components/config_sections_templ.go b/weed/admin/view/components/config_sections_templ.go index 3385050e5..acb61bfaa 100644 --- a/weed/admin/view/components/config_sections_templ.go +++ b/weed/admin/view/components/config_sections_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/components/form_fields_templ.go b/weed/admin/view/components/form_fields_templ.go index f640c5575..937082a17 100644 --- a/weed/admin/view/components/form_fields_templ.go +++ b/weed/admin/view/components/form_fields_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/weed/admin/view/layout/layout_templ.go b/weed/admin/view/layout/layout_templ.go index 3ff64975c..c321c7a6b 100644 --- a/weed/admin/view/layout/layout_templ.go +++ b/weed/admin/view/layout/layout_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.906 package layout //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -150,8 +150,12 @@ func Layout(c *gin.Context, content templ.Component) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(menuItem.URL) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3))) + var templ_7745c5c3_Var3 templ.SafeURL + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(menuItem.URL)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 248, Col: 117} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -199,8 +203,12 @@ func Layout(c *gin.Context, content templ.Component) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(menuItem.URL) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7))) + var templ_7745c5c3_Var7 templ.SafeURL + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(menuItem.URL)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 252, Col: 110} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -263,8 +271,12 @@ func Layout(c *gin.Context, content templ.Component) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(menuItem.URL) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11))) + var templ_7745c5c3_Var11 templ.SafeURL + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(menuItem.URL)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 265, Col: 106} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } |
