2026-05-31 19:52:46 +03:00
{{define "admin_storage_tests.html"}}{{template "base" .}}{{end}}
{{define "content"}}
< section class = "app-shell admin-shell" aria-labelledby = "admin-storage-tests-title" >
< aside class = "app-sidebar" >
< nav class = "sidebar-nav" >
< a class = "sidebar-link" href = "/admin" > {{template "icon-dashboard" .}}< span > Overview< / span > < / a >
< a class = "sidebar-link" href = "/admin/files" > {{template "icon-folder" .}}< span > Files< / span > < / a >
< a class = "sidebar-link" href = "/admin/users" > {{template "icon-user-circle" .}}< span > Users< / span > < / a >
< a class = "sidebar-link" href = "/admin/settings" > {{template "icon-settings" .}}< span > Settings< / span > < / a >
< a class = "sidebar-link is-active" href = "/admin/storage" > {{template "icon-database" .}}< span > Storage< / span > < / a >
2026-05-31 21:52:56 +03:00
< a class = "sidebar-link" href = "/admin/logs" > {{template "icon-database" .}}< span > Logs< / span > < / a >
< a class = "sidebar-link" href = "/admin/bans" > {{template "icon-settings" .}}< span > Bans< / span > < / a >
2026-05-31 19:52:46 +03:00
< / nav >
< hr class = "sidebar-sep" >
< nav class = "sidebar-nav" >
< a class = "sidebar-link" href = "/app" > {{template "icon-home-simple" .}}< span > My Files< / span > < / a >
< / nav >
< hr class = "sidebar-sep" >
< form class = "sidebar-logout" action = "/admin/logout" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
< button class = "button button-outline" type = "submit" > {{template "icon-log-out" .}}< span > Sign out< / span > < / button >
< / form >
< / aside >
< div class = "app-main" >
< div class = "admin-header" >
< div >
< p class = "kicker" > Storage testing< / p >
< h1 id = "admin-storage-tests-title" > {{.Data.PageTitle}}< / h1 >
< p class = "muted-copy" > Connection status, speed-test history, and background benchmark runs for this backend.< / p >
< / div >
< div class = "storage-tests-header-actions" >
< a class = "button button-outline" href = "/admin/storage" > Back< / a >
{{if .Data.StorageTest.CanRun}}
< button class = "button button-primary" type = "button" data-storage-speed-open > New Test< / button >
{{end}}
< / div >
< / div >
{{if .Data.Notice}}< p class = "form-success" > {{.Data.Notice}}< / p > {{end}}
{{if .Data.Error}}< p class = "form-error" > {{.Data.Error}}< / p > {{end}}
< div class = "storage-card" >
< div class = "storage-card-header" >
< div class = "storage-card-identity" >
< div class = "storage-card-icon" >
{{if eq .Data.StorageTest.Config.Type "local"}}{{template "icon-hard-drive" .}}
{{else if eq .Data.StorageTest.Config.Type "sftp"}}{{template "icon-database" .}}
{{else if eq .Data.StorageTest.Config.Type "smb"}}{{template "icon-folder" .}}
{{else if eq .Data.StorageTest.Config.Type "webdav"}}{{template "icon-cloud-sync" .}}
{{else}}{{template "icon-cloud-upload" .}}{{end}}
< / div >
< div >
< strong class = "storage-card-name" > {{.Data.StorageTest.Config.Name}}< / strong >
< div class = "storage-card-meta" >
< span class = "badge" > {{if eq .Data.StorageTest.Config.Provider "contabo"}}Contabo{{else if eq .Data.StorageTest.Config.Type "sftp"}}SFTP{{else if eq .Data.StorageTest.Config.Type "smb"}}Samba{{else if eq .Data.StorageTest.Config.Type "webdav"}}WebDAV{{else if eq .Data.StorageTest.Config.Type "s3"}}S3{{else if eq .Data.StorageTest.Config.Type "local"}}Local files{{else}}{{.Data.StorageTest.Config.Type}}{{end}}< / span >
{{if .Data.StorageTest.Config.LastTestSuccess}}< span class = "badge badge-active" > Connection OK< / span > {{else}}< span class = "badge badge-disabled" > Needs connection test< / span > {{end}}
{{if .Data.StorageTest.UsageLabel}}< span class = "storage-card-usage" > {{.Data.StorageTest.UsageLabel}}< / span > {{end}}
< / div >
< / div >
< / div >
< form action = "/admin/storage/{{.Data.StorageTest.Config.ID}}/test" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
< input type = "hidden" name = "next" value = "tests" >
< button class = "button button-outline button-sm" type = "submit" > Test Connection< / button >
< / form >
< / div >
{{if not (.Data.StorageTest.Config.LastTestedAt.IsZero)}}
< div class = "storage-card-summary" >
< div class = "storage-detail storage-detail-test {{if .Data.StorageTest.Config.LastTestSuccess}}is-ok{{else}}is-err{{end}}" >
< span > Last test< / span >
< span > {{.Data.StorageTest.Config.LastTestedAt.Format "Jan 2, 15:04"}} · {{if .Data.StorageTest.Config.LastTestSuccess}}Passed{{else}}{{if .Data.StorageTest.Config.LastTestError}}{{.Data.StorageTest.Config.LastTestError}}{{else}}Failed{{end}}{{end}}< / span >
< / div >
< / div >
{{end}}
< / div >
{{if not .Data.StorageTest.CanRun}}
< p class = "form-error" > Run a successful connection test before starting speed tests.< / p >
{{end}}
< div class = "storage-results-list storage-results-page" data-storage-tests-page data-storage-tests-url = "/admin/storage/{{.Data.StorageTest.Config.ID}}/tests.json" >
{{if .Data.StorageTest.Tests}}
{{range .Data.StorageTest.Tests}}
< details class = "storage-result-row" data-storage-test-id = "{{.ID}}" >
< summary >
< span > {{.StartedLabel}}< / span >
< span > {{if eq .Mode "custom"}}{{.CustomFileCount}} files × {{.CustomFileSizeMB}} MB{{else}}{{.ModeLabel}}{{end}}< / span >
< span class = "storage-result-status is-{{.Status}}" > {{.Status}}< / span >
< / summary >
< div class = "storage-test-progress" aria-label = "Test progress" >
< div class = "storage-test-progress-bar" > < span style = "width: {{.ProgressPercent}}%" > < / span > < / div >
< small > {{.ProgressPercent}}%{{if .Stage}} · {{.Stage}}{{end}}< / small >
< / div >
< div class = "storage-result-detail" >
< span > < strong > Finished< / strong > {{.FinishedLabel}}< / span >
< span > < strong > Files< / strong > {{.FilesWritten}}< / span >
< span > < strong > Size< / strong > {{.TotalSizeLabel}}< / span >
< span > < strong > Write< / strong > {{.WriteSpeedLabel}}< / span >
< span > < strong > Read< / strong > {{.ReadSpeedLabel}}< / span >
{{if .Error}}< span class = "storage-result-error" > < strong > Error< / strong > {{.Error}}< / span > {{end}}
< / div >
< / details >
{{end}}
{{else}}
< p class = "muted-copy" > No speed tests have been run for this backend yet.< / p >
{{end}}
< / div >
< div class = "storage-modal" data-storage-speed-modal hidden >
< div class = "storage-modal-backdrop" data-storage-modal-close > < / div >
< div class = "storage-modal-card" role = "dialog" aria-modal = "true" aria-label = "Run storage speed test" >
< div class = "storage-modal-header" >
< strong > New speed test< / strong >
< button type = "button" class = "button button-outline button-sm" data-storage-modal-close > Close< / button >
< / div >
< form action = "/admin/storage/{{.Data.StorageTest.Config.ID}}/speed-test" method = "post" class = "storage-speed-form" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
< label class = "storage-speed-option" >
< input type = "radio" name = "mode" value = "small" >
< span > < strong > Many small files test< / strong > < small > Writes, reads, and deletes many tiny objects.< / small > < / span >
< / label >
< label class = "storage-speed-option" >
< input type = "radio" name = "mode" value = "big" >
< span > < strong > One big file test< / strong > < small > Uses one larger object for sequential throughput.< / small > < / span >
< / label >
< label class = "storage-speed-option" >
< input type = "radio" name = "mode" value = "mixed" checked >
< span > < strong > Average Test ( mix )< / strong > < small > Balances small object overhead and larger transfer speed.< / small > < / span >
< / label >
< label class = "storage-speed-option" >
< input type = "radio" name = "mode" value = "custom" data-storage-custom-radio >
< span > < strong > Custom< / strong > < small > Choose how many mock files to create and the size of each file.< / small > < / span >
< / label >
< div class = "storage-custom-fields" data-storage-custom-fields hidden >
< label > < span > Files< / span > < input type = "number" name = "custom_file_count" min = "1" max = "500" value = "10" > < / label >
< label > < span > Size per file (MB)< / span > < input type = "number" name = "custom_file_size_mb" min = "0.001" step = "0.001" value = "1" > < / label >
< / div >
< button class = "button button-primary button-sm" type = "submit" > Run in background< / button >
< / form >
< / div >
< / div >
< / div >
< / section >
{{end}}