feat(ui): add quota overview (#6602)
Add UI to the quota feature to see what quotas applies to you and if you're exceeding any quota, it's designed to be a general size overview although it's exclusively filled with quota features for now. There's also no UI to see what item is actually taking in the most size. Purely an quota overview. Screenshots:   With inspiration from concept by 0ko:  Co-authored-by: Otto Richter <git@otto.splvs.net> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6602 Reviewed-by: Otto <otto@codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
parent
6dad457552
commit
77a1af5ab8
24 changed files with 348 additions and 33 deletions
20
routers/web/org/setting/storage_overview.go
Normal file
20
routers/web/org/setting/storage_overview.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/routers/web/shared"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
const (
|
||||
tplSettingsStorageOverview base.TplName = "org/settings/storage_overview"
|
||||
)
|
||||
|
||||
// StorageOverview render a size overview of the organization, as well as relevant
|
||||
// quota limits of the instance.
|
||||
func StorageOverview(ctx *context.Context) {
|
||||
shared.StorageOverview(ctx, ctx.Org.Organization.ID, tplSettingsStorageOverview)
|
||||
}
|
90
routers/web/shared/storage_overview.go
Normal file
90
routers/web/shared/storage_overview.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package shared
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
quota_model "code.gitea.io/gitea/models/quota"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
// StorageOverview render a size overview of the user, as well as relevant
|
||||
// quota limits of the instance.
|
||||
func StorageOverview(ctx *context.Context, userID int64, tpl base.TplName) {
|
||||
if !setting.Quota.Enabled {
|
||||
ctx.NotFound("MustEnableQuota", nil)
|
||||
}
|
||||
ctx.Data["Title"] = ctx.Tr("settings.storage_overview")
|
||||
ctx.Data["PageIsStorageOverview"] = true
|
||||
|
||||
ctx.Data["Color"] = func(subject quota_model.LimitSubject) float64 {
|
||||
return float64(subject) * 137.50776405003785 // Golden angle.
|
||||
}
|
||||
|
||||
ctx.Data["PrettySubject"] = func(subject quota_model.LimitSubject) template.HTML {
|
||||
switch subject {
|
||||
case quota_model.LimitSubjectSizeAll:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.all")
|
||||
case quota_model.LimitSubjectSizeReposAll:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.repos.all")
|
||||
case quota_model.LimitSubjectSizeReposPublic:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.repos.public")
|
||||
case quota_model.LimitSubjectSizeReposPrivate:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.repos.private")
|
||||
case quota_model.LimitSubjectSizeGitAll:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.git.all")
|
||||
case quota_model.LimitSubjectSizeGitLFS:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.git.lfs")
|
||||
case quota_model.LimitSubjectSizeAssetsAll:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.assets.all")
|
||||
case quota_model.LimitSubjectSizeAssetsAttachmentsAll:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.assets.attachments.all")
|
||||
case quota_model.LimitSubjectSizeAssetsAttachmentsIssues:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.assets.attachments.issues")
|
||||
case quota_model.LimitSubjectSizeAssetsAttachmentsReleases:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.assets.attachments.releases")
|
||||
case quota_model.LimitSubjectSizeAssetsArtifacts:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.assets.artifacts")
|
||||
case quota_model.LimitSubjectSizeAssetsPackagesAll:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.assets.packages.all")
|
||||
case quota_model.LimitSubjectSizeWiki:
|
||||
return ctx.Locale.Tr("settings.quota.sizes.wiki")
|
||||
default:
|
||||
panic("unrecognized subject: " + subject.String())
|
||||
}
|
||||
}
|
||||
|
||||
sizeUsed, err := quota_model.GetUsedForUser(ctx, userID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUsedForUser", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["SizeUsed"] = sizeUsed
|
||||
|
||||
quotaGroups, err := quota_model.GetGroupsForUser(ctx, userID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetGroupsForUser", err)
|
||||
return
|
||||
}
|
||||
if len(quotaGroups) == 0 {
|
||||
quotaGroups = append(quotaGroups, "a_model.Group{
|
||||
Name: "Global quota",
|
||||
Rules: []quota_model.Rule{
|
||||
{
|
||||
Name: "Default",
|
||||
Limit: setting.Quota.Default.Total,
|
||||
Subjects: quota_model.LimitSubjects{quota_model.LimitSubjectSizeAll},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
ctx.Data["QuotaGroups"] = quotaGroups
|
||||
|
||||
ctx.HTML(http.StatusOK, tpl)
|
||||
}
|
20
routers/web/user/setting/storage_overview.go
Normal file
20
routers/web/user/setting/storage_overview.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/routers/web/shared"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
const (
|
||||
tplSettingsStorageOverview base.TplName = "user/settings/storage_overview"
|
||||
)
|
||||
|
||||
// StorageOverview render a size overview of the user, as well as relevant
|
||||
// quota limits of the instance.
|
||||
func StorageOverview(ctx *context.Context) {
|
||||
shared.StorageOverview(ctx, ctx.Doer.ID, tplSettingsStorageOverview)
|
||||
}
|
|
@ -644,7 +644,8 @@ func registerRoutes(m *web.Route) {
|
|||
m.Get("", user_setting.BlockedUsers)
|
||||
m.Post("/unblock", user_setting.UnblockUser)
|
||||
})
|
||||
}, reqSignIn, ctxDataSet("PageIsUserSettings", true, "AllThemes", setting.UI.Themes, "EnablePackages", setting.Packages.Enabled))
|
||||
m.Get("/storage_overview", user_setting.StorageOverview)
|
||||
}, reqSignIn, ctxDataSet("PageIsUserSettings", true, "AllThemes", setting.UI.Themes, "EnablePackages", setting.Packages.Enabled, "EnableQuota", setting.Quota.Enabled))
|
||||
|
||||
m.Group("/user", func() {
|
||||
m.Get("/activate", auth.Activate)
|
||||
|
@ -930,6 +931,7 @@ func registerRoutes(m *web.Route) {
|
|||
m.Post("/block", org_setting.BlockedUsersBlock)
|
||||
m.Post("/unblock", org_setting.BlockedUsersUnblock)
|
||||
})
|
||||
m.Get("/storage_overview", org_setting.StorageOverview)
|
||||
|
||||
m.Group("/packages", func() {
|
||||
m.Get("", org.Packages)
|
||||
|
@ -949,7 +951,7 @@ func registerRoutes(m *web.Route) {
|
|||
m.Post("/rebuild", org.RebuildCargoIndex)
|
||||
})
|
||||
}, packagesEnabled)
|
||||
}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true))
|
||||
}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "EnableQuota", setting.Quota.Enabled, "PageIsOrgSettings", true))
|
||||
}, context.OrgAssignment(true, true))
|
||||
}, reqSignIn)
|
||||
// ***** END: Organization *****
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue