user manager: search by group

UserStore:
modify SearchOffset method signature
modify CountSearch method signature

phrases:
add panel_users_search_group
add panel_users_search_group_none
add panel_users_search_title

add missing paginator_mod template x.x
eliminate bytes here and there
This commit is contained in:
Azareal 2021-01-20 09:47:08 +10:00
parent 0bf1b6dbd3
commit f69e077347
8 changed files with 66 additions and 19 deletions

View File

@ -614,10 +614,14 @@ type PanelMenuItemPage struct {
type PanelUserPageSearch struct {
Name string
Email string
Group int
Any bool
}
type PanelUserPage struct {
*BasePanelPage
ItemList []*User
Groups []*Group
Search PanelUserPageSearch
PaginatorMod
}

View File

@ -21,7 +21,7 @@ type UserStore interface {
Getn(id int) *User
GetByName(name string) (*User, error)
Exists(id int) bool
SearchOffset(name, email string, offset, perPage int) (users []*User, err error)
SearchOffset(name, email string, gid, offset, perPage int) (users []*User, err error)
GetOffset(offset, perPage int) ([]*User, error)
Each(f func(*User) error) error
//BulkGet(ids []int) ([]*User, error)
@ -30,7 +30,7 @@ type UserStore interface {
Create(name, password, email string, group int, active bool) (int, error)
Reload(id int) error
Count() int
CountSearch(name, email string) int
CountSearch(name, email string, gid int) int
SetCache(cache UserCache)
GetCache() UserCache
@ -66,7 +66,7 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
get: acc.Select(u).Columns("name,group,active,is_super_admin,session,email,avatar,message,level,score,posts,liked,last_ip,temp_group,createdAt,enable_embeds,profile_comments,who_can_convo").Where("uid=?").Prepare(),
getByName: acc.Select(u).Columns(allCols).Where("name=?").Prepare(),
searchOffset: acc.Select(u).Columns(allCols).Where("(name=? OR ?='') AND (email=? OR ?='')").Orderby("uid ASC").Limit("?,?").Prepare(),
searchOffset: acc.Select(u).Columns(allCols).Where("(name=? OR ?='') AND (email=? OR ?='') AND (group=? OR ?='')").Orderby("uid ASC").Limit("?,?").Prepare(),
getOffset: acc.Select(u).Columns(allCols).Orderby("uid ASC").Limit("?,?").Prepare(),
getAll: acc.Select(u).Columns(allCols).Prepare(),
@ -75,7 +75,7 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
nameExists: acc.Exists(u, "name").Prepare(),
count: acc.Count(u).Prepare(),
countSearch: acc.Count(u).Where("(name=? OR ?='') AND (email=? OR ?='')").Prepare(),
countSearch: acc.Count(u).Where("(name=? OR ?='') AND (email=? OR ?='') AND (group=? OR ?='')").Prepare(),
}, acc.FirstError()
}
@ -180,8 +180,8 @@ func (s *DefaultUserStore) GetOffset(offset, perPage int) (users []*User, err er
}
return users, rows.Err()
}
func (s *DefaultUserStore) SearchOffset(name, email string, offset, perPage int) (users []*User, err error) {
rows, err := s.searchOffset.Query(name, name, email, email, offset, perPage)
func (s *DefaultUserStore) SearchOffset(name, email string, gid, offset, perPage int) (users []*User, err error) {
rows, err := s.searchOffset.Query(name, name, email, email, gid, gid, offset, perPage)
if err != nil {
return users, err
}
@ -384,8 +384,8 @@ func (s *DefaultUserStore) Count() (count int) {
return Countf(s.count)
}
func (s *DefaultUserStore) CountSearch(name, email string) (count int) {
return Countf(s.countSearch, name, name, email, email)
func (s *DefaultUserStore) CountSearch(name, email string, gid int) (count int) {
return Countf(s.countSearch, name, name, email, email, gid, gid)
}
func (s *DefaultUserStore) SetCache(cache UserCache) {

View File

@ -900,7 +900,10 @@
"panel_users_search_name_placeholder":"John Doe",
"panel_users_search_email":"Email",
"panel_users_search_email_placeholder":"john.doe@example.com",
"panel_users_search_group":"Group",
"panel_users_search_group_none":"None",
"panel_users_search_button":"Search",
"panel_users_search_title":"Search Users",
"panel_user_head":"User Editor",
"panel_user_avatar":"Avatar",

View File

@ -21,20 +21,38 @@ func Users(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
if !u.Perms.EditUserEmail && email != "" {
return c.LocalError("Only users with the EditUserEmail permission can search by email.", w, r, u)
}
hasParam := name != "" || email != ""
group := r.FormValue("s-group")
f := func(l ...string) bool {
for _, ll := range l {
if ll != "" {
return true
}
}
return false
}
hasParam := f(name, email, group)
gid, _ := strconv.Atoi(group)
/*if group == "" {
gid = -1
}*/
hasParam = hasParam && gid > 0
page, _ := strconv.Atoi(r.FormValue("page"))
perPage := 15
userCount := basePage.Stats.Users
if hasParam {
userCount = c.Users.CountSearch(name, email)
userCount = c.Users.CountSearch(name, email, gid)
}
offset, page, lastPage := c.PageOffset(userCount, page, perPage)
allGroups, e := c.Groups.GetAll()
if e != nil {
return c.InternalError(e, w, r)
}
var users []*c.User
var e error
if hasParam {
users, e = c.Users.SearchOffset(name, email, offset, perPage)
users, e = c.Users.SearchOffset(name, email, gid, offset, perPage)
} else {
users, e = c.Users.GetOffset(offset, perPage)
}
@ -44,7 +62,7 @@ func Users(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
name = url.QueryEscape(name)
email = url.QueryEscape(email)
search := c.PanelUserPageSearch{name, email}
search := c.PanelUserPageSearch{name, email, gid, hasParam}
var params string
if hasParam {
@ -56,7 +74,7 @@ func Users(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
}
}
pageList := c.Paginate(page, lastPage, 5)
pi := c.PanelUserPage{basePage, users, search, c.PaginatorMod{template.URL(params), pageList, page, lastPage}}
pi := c.PanelUserPage{basePage, users, allGroups, search, c.PaginatorMod{template.URL(params), pageList, page, lastPage}}
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_users", &pi})
}

View File

@ -6,7 +6,7 @@
<div class="rowblock">
{{range .GuildList}}<div class="rowitem datarow">
<span style="float:left;">
<a href="{{.Link}}" style="">{{.Name}}</a>
<a href="{{.Link}}"style="">{{.Name}}</a>
<br><span class="rowsmall">{{.Desc}}</span>
</span>
<span style="float:right;">

View File

@ -0,0 +1,14 @@
{{if gt .LastPage 1}}
<div class="pageset">
{{if gt .Page 1}}<div class="pageitem pagefirst"><a href="?{{.Params}}page=1"aria-label="{{lang "paginator.first_page_aria"}}">{{lang "paginator.first_page"}}</a></div>
<div class="pageitem pageprev"><a href="?{{.Params}}page={{subtract .Page 1}}"rel="prev"aria-label="{{lang "paginator.prev_page_aria"}}">{{lang "paginator.prev_page"}}</a></div>
<link rel="prev"href="?{{.Params}}page={{subtract .Page 1}}">{{end}}
{{range .PageList}}
<div class="pageitem{{if eq . $.Page}} pagecurrent{{end}}"><a href="?{{$.Params}}page={{.}}">{{.}}</a></div>
{{end}}
{{if ne .LastPage .Page}}
<link rel="next"href="?{{.Params}}page={{add .Page 1}}">
<div class="pageitem pagenext"><a href="?{{.Params}}page={{add .Page 1}}"rel="next"aria-label="{{lang "paginator.next_page_aria"}}">{{lang "paginator.next_page"}}</a></div>
<div class="pageitem pagelast"><a href="?{{.Params}}page={{.LastPage}}"aria-label="{{lang "paginator.last_page_aria"}}">{{lang "paginator.last_page"}}</a></div>{{end}}
</div>
{{end}}

View File

@ -10,7 +10,7 @@
<div class="formitem avataritem">
{{if .User.RawAvatar}}<img src="{{.User.Avatar}}"height=56 width=56>{{end}}
<div class="avatarbuttons">
<input form="avatar_form"id="select_avatar"name="avatar_file"type="file" required class="auto_hide">
<input form="avatar_form"id="select_avatar"name="avatar_file"type="file"required class="auto_hide">
<label for="select_avatar"class="formbutton">{{lang "panel_user_avatar_select"}}</label>
<button form="avatar_form"name="avatar_action"value=0>{{lang "panel_user_avatar_upload"}}</button>
{{if .User.RawAvatar}}<button form="remove_avatar_form"name="avatar_action"value=1>{{lang "panel_user_avatar_remove"}}</button>{{end}}

View File

@ -1,5 +1,5 @@
<div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_users_head"}}</h1></div>
<div class="rowitem"><h1>{{if .Search.Any}}{{lang "panel_users_search_title"}}{{else}}{{lang "panel_users_head"}}{{end}}</h1></div>
</div>
<div id="panel_users"class="colstack_item rowlist bgavatars">
{{range .ItemList}}
@ -32,6 +32,14 @@
<div class="formitem formlabel"><a>{{lang "panel_users_search_email"}}</a></div>
<div class="formitem"><input name="s-email"type="email"{{if .Search.Email}}value="{{.Search.Email}}"{{end}}placeholder="{{lang "panel_users_search_email_placeholder"}}"></div>
</div>{{end}}
{{if .CurrentUser.Perms.EditUserGroup}}<div class="formrow">
<div class="formitem formlabel"><a>{{lang "panel_users_search_group"}}</a></div>
<div class="formitem"><select name="s-group">
<option value="0"{{if eq $.Search.Group 0}}selected{{end}}>{{lang "panel_users_search_group_none"}}</option>
{{range .Groups}}{{if ne .ID 0}}
<option value="{{.ID}}"{{if eq $.Search.Group .ID}}selected{{end}}>{{.Name}}</option>
{{end}}{{end}}</select></div>
</div>{{end}}
<div class="formrow form_button_row">
<div class="formitem"><button class="formbutton">{{lang "panel_users_search_button"}}</button></div>
</div>