mirror of https://github.com/go-gitea/gitea.git
User details page (#26713)
This PR implements a proposal to clean up the admin users table by moving some information out to a separate user details page (which also displays some additional information). Other changes: - move edit user page from `/admin/users/{id}` to `/admin/users/{id}/edit` -> `/admin/users/{id}` now shows the user details page - show if user is instance administrator as a label instead of a separate column - separate explore users template into a page- and a shared one, to make it possible to use it on the user details page - fix issue where there was no margin between alert message and following content on admin pages <details> <summary>Screenshots</summary> ![grafik](https://github.com/go-gitea/gitea/assets/47871822/1ad57ac9-f20a-45a4-8477-ffe572a41e9e) ![grafik](https://github.com/go-gitea/gitea/assets/47871822/25786ecd-cb9d-4c92-90f4-e7f4292c073b) </details> Partially resolves #25939 --------- Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
parent
3d109861dd
commit
5b5bb8d354
|
@ -2823,6 +2823,7 @@ users.list_status_filter.is_prohibit_login = Prohibit Login
|
||||||
users.list_status_filter.not_prohibit_login = Allow Login
|
users.list_status_filter.not_prohibit_login = Allow Login
|
||||||
users.list_status_filter.is_2fa_enabled = 2FA Enabled
|
users.list_status_filter.is_2fa_enabled = 2FA Enabled
|
||||||
users.list_status_filter.not_2fa_enabled = 2FA Disabled
|
users.list_status_filter.not_2fa_enabled = 2FA Disabled
|
||||||
|
users.details = User Details
|
||||||
|
|
||||||
emails.email_manage_panel = User Email Management
|
emails.email_manage_panel = User Email Management
|
||||||
emails.primary = Primary
|
emails.primary = Primary
|
||||||
|
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/auth"
|
"code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
org_model "code.gitea.io/gitea/models/organization"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
system_model "code.gitea.io/gitea/models/system"
|
system_model "code.gitea.io/gitea/models/system"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/auth/password"
|
"code.gitea.io/gitea/modules/auth/password"
|
||||||
|
@ -32,6 +34,7 @@ import (
|
||||||
const (
|
const (
|
||||||
tplUsers base.TplName = "admin/user/list"
|
tplUsers base.TplName = "admin/user/list"
|
||||||
tplUserNew base.TplName = "admin/user/new"
|
tplUserNew base.TplName = "admin/user/new"
|
||||||
|
tplUserView base.TplName = "admin/user/view"
|
||||||
tplUserEdit base.TplName = "admin/user/edit"
|
tplUserEdit base.TplName = "admin/user/edit"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -249,6 +252,61 @@ func prepareUserInfo(ctx *context.Context) *user_model.User {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ViewUser(ctx *context.Context) {
|
||||||
|
ctx.Data["Title"] = ctx.Tr("admin.users.details")
|
||||||
|
ctx.Data["PageIsAdminUsers"] = true
|
||||||
|
ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation
|
||||||
|
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
|
||||||
|
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||||
|
|
||||||
|
u := prepareUserInfo(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
|
||||||
|
ListOptions: db.ListOptions{
|
||||||
|
ListAll: true,
|
||||||
|
},
|
||||||
|
OwnerID: u.ID,
|
||||||
|
OrderBy: db.SearchOrderByAlphabetically,
|
||||||
|
Private: true,
|
||||||
|
Collaborate: util.OptionalBoolFalse,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("SearchRepository", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data["Repos"] = repos
|
||||||
|
ctx.Data["ReposTotal"] = int(count)
|
||||||
|
|
||||||
|
emails, err := user_model.GetEmailAddresses(ctx.Doer.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetEmailAddresses", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["Emails"] = emails
|
||||||
|
ctx.Data["EmailsTotal"] = len(emails)
|
||||||
|
|
||||||
|
orgs, err := org_model.FindOrgs(org_model.FindOrgOptions{
|
||||||
|
ListOptions: db.ListOptions{
|
||||||
|
ListAll: true,
|
||||||
|
},
|
||||||
|
UserID: u.ID,
|
||||||
|
IncludePrivate: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("FindOrgs", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data["Users"] = orgs // needed to be able to use explore/user_list template
|
||||||
|
ctx.Data["OrgsTotal"] = len(orgs)
|
||||||
|
|
||||||
|
ctx.HTML(http.StatusOK, tplUserView)
|
||||||
|
}
|
||||||
|
|
||||||
// EditUser show editing user page
|
// EditUser show editing user page
|
||||||
func EditUser(ctx *context.Context) {
|
func EditUser(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("admin.users.edit_account")
|
ctx.Data["Title"] = ctx.Tr("admin.users.edit_account")
|
||||||
|
|
|
@ -573,7 +573,8 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Group("/users", func() {
|
m.Group("/users", func() {
|
||||||
m.Get("", admin.Users)
|
m.Get("", admin.Users)
|
||||||
m.Combo("/new").Get(admin.NewUser).Post(web.Bind(forms.AdminCreateUserForm{}), admin.NewUserPost)
|
m.Combo("/new").Get(admin.NewUser).Post(web.Bind(forms.AdminCreateUserForm{}), admin.NewUserPost)
|
||||||
m.Combo("/{userid}").Get(admin.EditUser).Post(web.Bind(forms.AdminEditUserForm{}), admin.EditUserPost)
|
m.Get("/{userid}", admin.ViewUser)
|
||||||
|
m.Combo("/{userid}/edit").Get(admin.EditUser).Post(web.Bind(forms.AdminEditUserForm{}), admin.EditUserPost)
|
||||||
m.Post("/{userid}/delete", admin.DeleteUser)
|
m.Post("/{userid}/delete", admin.DeleteUser)
|
||||||
m.Post("/{userid}/avatar", web.Bind(forms.AvatarForm{}), admin.AvatarPost)
|
m.Post("/{userid}/avatar", web.Bind(forms.AvatarForm{}), admin.AvatarPost)
|
||||||
m.Post("/{userid}/avatar/delete", admin.DeleteAvatar)
|
m.Post("/{userid}/avatar/delete", admin.DeleteAvatar)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{template "base/head" .ctxData}}
|
{{template "base/head" .ctxData}}
|
||||||
<div role="main" aria-label="{{.ctxData.Title}}" class="page-content {{.pageClass}}">
|
<div role="main" aria-label="{{.ctxData.Title}}" class="page-content {{.pageClass}}">
|
||||||
<div class="ui container">
|
<div class="ui container gt-mb-4">
|
||||||
{{template "base/alert" .ctxData}}
|
{{template "base/alert" .ctxData}}
|
||||||
</div>
|
</div>
|
||||||
<div class="ui container flex-container">
|
<div class="ui container flex-container">
|
||||||
|
|
|
@ -68,36 +68,35 @@
|
||||||
</th>
|
</th>
|
||||||
<th>{{.locale.Tr "email"}}</th>
|
<th>{{.locale.Tr "email"}}</th>
|
||||||
<th>{{.locale.Tr "admin.users.activated"}}</th>
|
<th>{{.locale.Tr "admin.users.activated"}}</th>
|
||||||
<th>{{.locale.Tr "admin.users.admin"}}</th>
|
|
||||||
<th>{{.locale.Tr "admin.users.restricted"}}</th>
|
<th>{{.locale.Tr "admin.users.restricted"}}</th>
|
||||||
<th>{{.locale.Tr "admin.users.2fa"}}</th>
|
<th>{{.locale.Tr "admin.users.2fa"}}</th>
|
||||||
<th>{{.locale.Tr "admin.users.repos"}}</th>
|
|
||||||
<th>{{.locale.Tr "admin.users.created"}}</th>
|
<th>{{.locale.Tr "admin.users.created"}}</th>
|
||||||
<th data-sortt-asc="lastlogin" data-sortt-desc="reverselastlogin">
|
<th data-sortt-asc="lastlogin" data-sortt-desc="reverselastlogin">
|
||||||
{{.locale.Tr "admin.users.last_login"}}
|
{{.locale.Tr "admin.users.last_login"}}
|
||||||
{{SortArrow "lastlogin" "reverselastlogin" $.SortType false}}
|
{{SortArrow "lastlogin" "reverselastlogin" $.SortType false}}
|
||||||
</th>
|
</th>
|
||||||
<th>{{.locale.Tr "admin.users.edit"}}</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Users}}
|
{{range .Users}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.ID}}</td>
|
<td>{{.ID}}</td>
|
||||||
<td><a href="{{.HomeLink}}">{{.Name}}</a></td>
|
<td>
|
||||||
|
<a href="{{$.Link}}/{{.ID}}">{{.Name}}</a>
|
||||||
|
{{if .IsAdmin}}
|
||||||
|
<span class="ui basic label">{{$.locale.Tr "admin.users.admin"}}</span>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
<td class="gt-ellipsis gt-max-width-12rem">{{.Email}}</td>
|
<td class="gt-ellipsis gt-max-width-12rem">{{.Email}}</td>
|
||||||
<td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
<td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||||
<td>{{if .IsAdmin}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
|
||||||
<td>{{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
<td>{{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||||
<td>{{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
<td>{{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
|
||||||
<td>{{.NumRepos}}</td>
|
|
||||||
<td>{{DateTime "short" .CreatedUnix}}</td>
|
<td>{{DateTime "short" .CreatedUnix}}</td>
|
||||||
{{if .LastLoginUnix}}
|
{{if .LastLoginUnix}}
|
||||||
<td>{{DateTime "short" .LastLoginUnix}}</td>
|
<td>{{DateTime "short" .LastLoginUnix}}</td>
|
||||||
{{else}}
|
{{else}}
|
||||||
<td><span>{{$.locale.Tr "admin.users.never_login"}}</span></td>
|
<td><span>{{$.locale.Tr "admin.users.never_login"}}</span></td>
|
||||||
{{end}}
|
{{end}}
|
||||||
<td><a href="{{$.Link}}/{{.ID}}">{{svg "octicon-pencil"}}</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin view user")}}
|
||||||
|
|
||||||
|
<div class="admin-setting-content">
|
||||||
|
<div class="admin-responsive-columns">
|
||||||
|
<div class="gt-f1">
|
||||||
|
<h4 class="ui top attached header">
|
||||||
|
{{.Title}}
|
||||||
|
<div class="ui right">
|
||||||
|
<a class="ui primary tiny button" href="{{.Link}}/edit">{{ctx.Locale.Tr "admin.users.edit"}}</a>
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
<div class="ui attached segment">
|
||||||
|
{{template "admin/user/view_details" .}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gt-f1">
|
||||||
|
<h4 class="ui top attached header">
|
||||||
|
{{ctx.Locale.Tr "admin.emails"}}
|
||||||
|
<div class="ui right">
|
||||||
|
{{.EmailsTotal}}
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
<div class="ui attached segment">
|
||||||
|
{{template "admin/user/view_emails" .}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4 class="ui top attached header">
|
||||||
|
{{ctx.Locale.Tr "admin.repositories"}}
|
||||||
|
<div class="ui right">
|
||||||
|
{{.ReposTotal}}
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
<div class="ui attached segment">
|
||||||
|
{{template "explore/repo_list" .}}
|
||||||
|
</div>
|
||||||
|
<h4 class="ui top attached header">
|
||||||
|
{{ctx.Locale.Tr "settings.organization"}}
|
||||||
|
<div class="ui right">
|
||||||
|
{{.OrgsTotal}}
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
<div class="ui attached segment">
|
||||||
|
{{template "explore/user_list" .}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{template "admin/layout_footer" .}}
|
|
@ -0,0 +1,65 @@
|
||||||
|
<div class="flex-list">
|
||||||
|
<div class="flex-item">
|
||||||
|
<div class="flex-item-leading">
|
||||||
|
{{ctx.AvatarUtils.Avatar .User 48}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-main">
|
||||||
|
<div class="flex-item-title">
|
||||||
|
{{template "shared/user/name" .User}}
|
||||||
|
{{if .User.IsAdmin}}
|
||||||
|
<span class="ui basic label">{{ctx.Locale.Tr "admin.users.admin"}}</span>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<b>{{ctx.Locale.Tr "admin.users.auth_source"}}:</b>
|
||||||
|
{{if eq .LoginSource.ID 0}}
|
||||||
|
{{ctx.Locale.Tr "admin.users.local"}}
|
||||||
|
{{else}}
|
||||||
|
{{.LoginSource.Name}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<b>{{ctx.Locale.Tr "admin.users.activated"}}:</b>
|
||||||
|
{{if .User.IsActive}}
|
||||||
|
{{svg "octicon-check"}}
|
||||||
|
{{else}}
|
||||||
|
{{svg "octicon-x"}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<b>{{ctx.Locale.Tr "admin.users.restricted"}}:</b>
|
||||||
|
{{if .User.IsRestricted}}
|
||||||
|
{{svg "octicon-check"}}
|
||||||
|
{{else}}
|
||||||
|
{{svg "octicon-x"}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<b>{{ctx.Locale.Tr "settings.visibility"}}:</b>
|
||||||
|
{{if .User.Visibility.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}}
|
||||||
|
{{if .User.Visibility.IsPrivate}}{{ctx.Locale.Tr "settings.visibility.private"}}{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<b>{{ctx.Locale.Tr "admin.users.2fa"}}:</b>
|
||||||
|
{{if .TwoFactorEnabled}}
|
||||||
|
<span class="text green">{{svg "octicon-check"}}</span>
|
||||||
|
{{else}}
|
||||||
|
{{svg "octicon-x"}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{if .User.Location}}
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<span class="flex-text-inline">{{svg "octicon-location"}}{{.User.Location}}</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .User.Website}}
|
||||||
|
<div class="flex-item-body">
|
||||||
|
<span class="flex-text-inline">
|
||||||
|
{{svg "octicon-link"}}
|
||||||
|
<a target="_blank" href="{{.User.Website}}">{{.User.Website}}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="flex-list">
|
||||||
|
{{range .Emails}}
|
||||||
|
<div class="flex-item">
|
||||||
|
<div class="flex-item-main">
|
||||||
|
<div class="flex-text-block">
|
||||||
|
{{.Email}}
|
||||||
|
{{if .IsPrimary}}
|
||||||
|
<div class="ui primary label">{{ctx.Locale.Tr "settings.primary"}}</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .IsActivated}}
|
||||||
|
<div class="ui green label">{{ctx.Locale.Tr "settings.activated"}}</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="ui label">{{ctx.Locale.Tr "settings.requires_activation"}}</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<div class="flex-list">
|
||||||
|
{{range .Users}}
|
||||||
|
<div class="flex-item flex-item-center">
|
||||||
|
<div class="flex-item-leading">
|
||||||
|
{{ctx.AvatarUtils.Avatar . 48}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-main">
|
||||||
|
<div class="flex-item-title">
|
||||||
|
{{template "shared/user/name" .}}
|
||||||
|
{{if .Visibility.IsPrivate}}
|
||||||
|
<span class="ui basic tiny label">{{ctx.Locale.Tr "repo.desc.private"}}</span>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
{{if .Location}}
|
||||||
|
<span class="flex-text-inline">{{svg "octicon-location"}}{{.Location}}</span>
|
||||||
|
{{end}}
|
||||||
|
{{if and .Email (or (and $.ShowUserEmail $.IsSigned (not .KeepEmailPrivate)) $.PageIsAdminUsers)}}
|
||||||
|
<span class="flex-text-inline">
|
||||||
|
{{svg "octicon-mail"}}
|
||||||
|
<a href="mailto:{{.Email}}">{{.Email}}</a>
|
||||||
|
</span>
|
||||||
|
{{end}}
|
||||||
|
<span class="flex-text-inline">{{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix) | Safe}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="flex-item">{{ctx.Locale.Tr "explore.user_no_results"}}</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
|
@ -4,37 +4,7 @@
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "explore/search" .}}
|
{{template "explore/search" .}}
|
||||||
|
|
||||||
<div class="flex-list">
|
{{template "explore/user_list" .}}
|
||||||
{{range .Users}}
|
|
||||||
<div class="flex-item flex-item-center">
|
|
||||||
<div class="flex-item-leading">
|
|
||||||
{{ctx.AvatarUtils.Avatar . 48}}
|
|
||||||
</div>
|
|
||||||
<div class="flex-item-main">
|
|
||||||
<div class="flex-item-title">
|
|
||||||
{{template "shared/user/name" .}}
|
|
||||||
{{if .Visibility.IsPrivate}}
|
|
||||||
<span class="ui basic tiny label">{{$.locale.Tr "repo.desc.private"}}</span>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
<div class="flex-item-body">
|
|
||||||
{{if .Location}}
|
|
||||||
<span class="flex-text-inline">{{svg "octicon-location"}}{{.Location}}</span>
|
|
||||||
{{end}}
|
|
||||||
{{if and $.ShowUserEmail .Email $.IsSigned (not .KeepEmailPrivate)}}
|
|
||||||
<span class="flex-text-inline">
|
|
||||||
{{svg "octicon-mail"}}
|
|
||||||
<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a>
|
|
||||||
</span>
|
|
||||||
{{end}}
|
|
||||||
<span class="flex-text-inline">{{svg "octicon-calendar"}}{{$.locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix) | Safe}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="flex-item">{{$.locale.Tr "explore.user_no_results"}}</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{template "base/paginate" .}}
|
{{template "base/paginate" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,8 +51,8 @@ func testSuccessfullEdit(t *testing.T, formData user_model.User) {
|
||||||
|
|
||||||
func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
|
func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
csrf := GetCSRF(t, session, "/admin/users/"+strconv.Itoa(int(formData.ID)))
|
csrf := GetCSRF(t, session, "/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit")
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/users/"+strconv.Itoa(int(formData.ID)), map[string]string{
|
req := NewRequestWithValues(t, "POST", "/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit", map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"user_name": formData.Name,
|
"user_name": formData.Name,
|
||||||
"login_name": formData.LoginName,
|
"login_name": formData.LoginName,
|
||||||
|
@ -72,7 +72,7 @@ func TestAdminDeleteUser(t *testing.T) {
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
|
||||||
csrf := GetCSRF(t, session, "/admin/users/8")
|
csrf := GetCSRF(t, session, "/admin/users/8/edit")
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/users/8/delete", map[string]string{
|
req := NewRequestWithValues(t, "POST", "/admin/users/8/delete", map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
})
|
})
|
||||||
|
|
|
@ -42,3 +42,10 @@
|
||||||
.admin .table th {
|
.admin .table th {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.admin-responsive-columns {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue