2026-05-31 02:14:10 +03:00
{{define "admin_storage.html"}}{{template "base" .}}{{end}}
{{define "content"}}
< section class = "app-shell admin-shell" aria-labelledby = "admin-storage-title" >
< aside class = "app-sidebar" >
< nav class = "sidebar-nav" >
2026-05-31 04:54:27 +03:00
< 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 02:14:10 +03:00
</ nav >
< hr class = "sidebar-sep" >
2026-05-31 04:54:27 +03:00
< nav class = "sidebar-nav" >
< a class = "sidebar-link" href = "/app" > {{template "icon-home-simple" .}}< span > My Files</ span ></ a >
</ nav >
2026-05-31 02:14:10 +03:00
< hr class = "sidebar-sep" >
< form class = "sidebar-logout" action = "/admin/logout" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
2026-05-31 04:54:27 +03:00
< button class = "button button-outline" type = "submit" > {{template "icon-log-out" .}}< span > Sign out</ span ></ button >
2026-05-31 02:14:10 +03:00
</ form >
</ aside >
< div class = "app-main" >
< div class = "admin-header" >
< div >
< p class = "kicker" > Operator console</ p >
< h1 id = "admin-storage-title" > {{.Data.PageTitle}}</ h1 >
2026-05-31 04:54:27 +03:00
< p class = "muted-copy" > Local storage is always active. Remote backends are proxied through Warpbox.</ p >
2026-05-31 02:14:10 +03:00
</ div >
2026-05-31 19:52:46 +03:00
< a class = "button button-primary" href = "/admin/storage/new" > {{template "icon-plus-circle" .}}< span > Add storage</ span ></ a >
2026-05-31 02:14:10 +03:00
</ div >
2026-05-31 19:52:46 +03:00
{{if .Data.Notice}}< p class = "form-success" > {{.Data.Notice}}</ p > {{end}}
2026-05-31 02:14:10 +03:00
{{if .Data.Error}}< p class = "form-error" > {{.Data.Error}}</ p > {{end}}
2026-05-31 19:52:46 +03:00
< div class = "storage-ops-grid" >
< form class = "storage-op-card" action = "/admin/storage/jobs/cleanup" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
< strong > Run cleanup now</ strong >
< span > Remove expired boxes and boxes that reached their download limit.</ span >
< button class = "button button-outline button-sm" type = "submit" > Run cleanup</ button >
</ form >
< form class = "storage-op-card" action = "/admin/storage/jobs/thumbnails" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
< strong > Generate thumbnails now</ strong >
< span > Scan active boxes and create missing image or video thumbnails.</ span >
< button class = "button button-outline button-sm" type = "submit" > Generate</ button >
</ form >
< form class = "storage-op-card" action = "/admin/storage/jobs/verify" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{.CSRFToken}}" >
< strong > Verify storage now</ strong >
< span > Test every enabled backend and update its last-test status.</ span >
< button class = "button button-outline button-sm" type = "submit" > Verify all</ button >
</ form >
</ div >
2026-05-31 02:14:10 +03:00
2026-05-31 19:52:46 +03:00
< div class = "storage-stack" >
2026-05-31 04:54:27 +03:00
{{range .Data.Storage}}
< div class = "storage-card {{if eq .Config.ID " local "}} is-local {{ end }}" data-storage-id = "{{.Config.ID}}" >
< div class = "storage-card-header" >
< div class = "storage-card-identity" >
< div class = "storage-card-icon" >
{{if eq .Config.Type "local"}}{{template "icon-hard-drive" $}}
{{else if eq .Config.Type "sftp"}}{{template "icon-database" $}}
{{else if eq .Config.Type "smb"}}{{template "icon-folder" $}}
{{else if eq .Config.Type "webdav"}}{{template "icon-cloud-sync" $}}
{{else}}{{template "icon-cloud-upload" $}}{{end}}
</ div >
< div >
< strong class = "storage-card-name" > {{.Config.Name}}</ strong >
< div class = "storage-card-meta" >
< span class = "badge" > {{if eq .Config.Provider "contabo"}}Contabo{{else if eq .Config.Type "sftp"}}SFTP{{else if eq .Config.Type "smb"}}Samba{{else if eq .Config.Type "webdav"}}WebDAV{{else if eq .Config.Type "s3"}}S3{{else if eq .Config.Type "local"}}Local files{{else}}{{.Config.Type}}{{end}}</ span >
{{if eq .Config.ID "local"}}< span class = "badge" > Required</ span >
{{else if .Config.Enabled}}< span class = "badge badge-active" > Enabled</ span >
{{else}}< span class = "badge badge-disabled" > Disabled</ span > {{end}}
{{if .UsageLabel}}< span class = "storage-card-usage" > {{.UsageLabel}}</ span > {{end}}
</ div >
</ div >
</ div >
< div class = "storage-card-actions" >
2026-05-31 19:52:46 +03:00
{{if .CanSpeedTest}}
< a class = "button button-outline button-sm" href = "/admin/storage/{{.Config.ID}}/tests" > Testing</ a >
{{else}}
2026-05-31 04:54:27 +03:00
< form action = "/admin/storage/{{.Config.ID}}/test" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{$.CSRFToken}}" >
< button class = "button button-outline button-sm" type = "submit" > Test</ button >
</ form >
2026-05-31 19:52:46 +03:00
{{end}}
2026-05-31 04:54:27 +03:00
{{if ne .Config.ID "local"}}
2026-05-31 19:52:46 +03:00
< a class = "button button-outline button-sm" href = "/admin/storage/{{.Config.ID}}/edit" > Edit</ a >
2026-05-31 04:54:27 +03:00
{{if .Config.Enabled}}
< form action = "/admin/storage/{{.Config.ID}}/disable" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{$.CSRFToken}}" >
< button class = "button button-outline button-sm" type = "submit" {{ if . InUse }} disabled title = "Backend is in use" {{ end }} > Disable</ button >
</ form >
{{end}}
< form action = "/admin/storage/{{.Config.ID}}/delete" method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{$.CSRFToken}}" >
< button class = "button button-danger button-sm" type = "submit" {{ if . InUse }} disabled title = "Backend is in use" {{ end }} > Delete</ button >
</ form >
{{end}}
2026-05-31 02:14:10 +03:00
</ div >
</ div >
2026-05-31 04:54:27 +03:00
< div class = "storage-card-summary" >
{{if eq .Config.Type "local"}}
< div class = "storage-detail" >< span > Path</ span >< code > {{.Config.LocalPath}}</ code ></ div >
{{else if or (eq .Config.Type "s3") (eq .Config.Provider "contabo")}}
{{if .Config.Endpoint}}< div class = "storage-detail" >< span > Endpoint</ span >< span > {{.Config.Endpoint}}</ span ></ div > {{end}}
{{if .Config.Bucket}}< div class = "storage-detail" >< span > Bucket</ span >< span > {{.Config.Bucket}}</ span ></ div > {{end}}
{{if .Config.Region}}< div class = "storage-detail" >< span > Region</ span >< span > {{.Config.Region}}</ span ></ div > {{end}}
{{if .Config.AccessKey}}< div class = "storage-detail" >< span > Access key</ span >< span > {{.Config.AccessKey}}</ span ></ div > {{end}}
{{else if eq .Config.Type "sftp"}}
{{if .Config.Host}}< div class = "storage-detail" >< span > Host</ span >< span > {{.Config.Host}}{{if .Config.Port}}:{{.Config.Port}}{{end}}</ span ></ div > {{end}}
{{if .Config.Username}}< div class = "storage-detail" >< span > Username</ span >< span > {{.Config.Username}}</ span ></ div > {{end}}
{{if .Config.RemotePath}}< div class = "storage-detail" >< span > Remote path</ span >< span > {{.Config.RemotePath}}</ span ></ div > {{end}}
{{else if eq .Config.Type "smb"}}
{{if .Config.Host}}< div class = "storage-detail" >< span > Host</ span >< span > {{if .Config.Domain}}{{.Config.Domain}}\{{end}}{{.Config.Username}}@{{.Config.Host}}/{{.Config.Share}}</ span ></ div > {{end}}
{{if .Config.RemotePath}}< div class = "storage-detail" >< span > Remote path</ span >< span > {{.Config.RemotePath}}</ span ></ div > {{end}}
{{else if eq .Config.Type "webdav"}}
{{if .Config.Endpoint}}< div class = "storage-detail" >< span > URL</ span >< span > {{.Config.Endpoint}}</ span ></ div > {{end}}
{{if .Config.Username}}< div class = "storage-detail" >< span > Username</ span >< span > {{.Config.Username}}</ span ></ div > {{end}}
{{if .Config.RemotePath}}< div class = "storage-detail" >< span > Remote path</ span >< span > {{.Config.RemotePath}}</ span ></ div > {{end}}
{{end}}
{{if not (.Config.LastTestedAt.IsZero)}}
< div class = "storage-detail storage-detail-test {{if .Config.LastTestSuccess}}is-ok{{else}}is-err{{end}}" >
< span > Last test</ span >
< span > {{.Config.LastTestedAt.Format "Jan 2, 15:04"}} · {{if .Config.LastTestSuccess}}Passed{{else}}{{if .Config.LastTestError}}{{.Config.LastTestError}}{{else}}Failed{{end}}{{end}}</ span >
2026-05-31 02:14:10 +03:00
</ div >
2026-05-31 04:54:27 +03:00
{{end}}
</ div >
2026-05-31 02:14:10 +03:00
</ div >
2026-05-31 04:54:27 +03:00
{{end}}
2026-05-31 02:14:10 +03:00
</ div >
</ div >
</ section >
{{end}}