[MM-56206] Allow for proper paging and sorting (#25726)

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Devin Binnie
2023-12-17 19:26:06 -05:00
коммит произвёл GitHub
родитель 485ae6ae4e
Коммит 5c061a6f75
7 изменённых файлов: 114 добавлений и 35 удалений

Просмотреть файл

@@ -20,6 +20,12 @@
schema: schema:
type: string type: string
default: 'Username' default: 'Username'
- name: direction
in: query
description: The direction in which to accept paging values from. Will return values ahead of the cursor if "up", and below the cursor if "down". Default is "down".
schema:
type: string
default: 'down'
- name: sort_direction - name: sort_direction
in: query in: query
description: The sorting direction. Must be one of ("asc", "desc"). Will default to 'asc' if not specified or the input is invalid. description: The sorting direction. Must be one of ("asc", "desc"). Will default to 'asc' if not specified or the input is invalid.
@@ -34,14 +40,14 @@
default: 50 default: 50
minimum: 1 minimum: 1
maximum: 100 maximum: 100
- name: last_column_value - name: from_column_value
in: query in: query
description: The value of the sorted column belonging to the last user returned in the page. Should be blank for the first page asked for. description: The value of the sorted column corresponding to the cursor to read from. Should be blank for the first page asked for.
schema: schema:
type: string type: string
- name: last_id - name: from_id
in: query in: query
description: The value of the user id belonging to the last user returned in the page. Should be blank for the first page asked for. description: The value of the user id corresponding to the cursor to read from. Should be blank for the first page asked for.
schema: schema:
type: string type: string
- name: date_range - name: date_range

Просмотреть файл

@@ -28,6 +28,11 @@ func getUsersForReporting(c *Context, w http.ResponseWriter, r *http.Request) {
sortColumn = r.URL.Query().Get("sort_column") sortColumn = r.URL.Query().Get("sort_column")
} }
direction := "down"
if r.URL.Query().Get("direction") == "up" {
direction = "up"
}
pageSize := 50 pageSize := 50
if pageSizeStr, err := strconv.ParseInt(r.URL.Query().Get("page_size"), 10, 64); err == nil { if pageSizeStr, err := strconv.ParseInt(r.URL.Query().Get("page_size"), 10, 64); err == nil {
pageSize = int(pageSizeStr) pageSize = int(pageSizeStr)
@@ -48,14 +53,15 @@ func getUsersForReporting(c *Context, w http.ResponseWriter, r *http.Request) {
options := &model.UserReportOptions{ options := &model.UserReportOptions{
ReportingBaseOptions: model.ReportingBaseOptions{ ReportingBaseOptions: model.ReportingBaseOptions{
Direction: direction,
SortColumn: sortColumn, SortColumn: sortColumn,
SortDesc: r.URL.Query().Get("sort_direction") == "desc", SortDesc: r.URL.Query().Get("sort_direction") == "desc",
PageSize: pageSize, PageSize: pageSize,
LastSortColumnValue: r.URL.Query().Get("last_column_value"), FromColumnValue: r.URL.Query().Get("from_column_value"),
FromId: r.URL.Query().Get("from_id"),
DateRange: r.URL.Query().Get("date_range"), DateRange: r.URL.Query().Get("date_range"),
}, },
Team: teamFilter, Team: teamFilter,
LastUserId: r.URL.Query().Get("last_id"),
Role: r.URL.Query().Get("role_filter"), Role: r.URL.Query().Get("role_filter"),
HasNoTeam: r.URL.Query().Get("has_no_team") == "true", HasNoTeam: r.URL.Query().Get("has_no_team") == "true",
HideActive: hideActive, HideActive: hideActive,

Просмотреть файл

@@ -2297,17 +2297,28 @@ func (us SqlUserStore) GetUserReport(filter *model.UserReportOptions) ([]*model.
Select(selectColumns...). Select(selectColumns...).
From("Users u"). From("Users u").
LeftJoin("Status s ON s.UserId = u.Id"). LeftJoin("Status s ON s.UserId = u.Id").
Where(sq.Or{
sq.Gt{filter.SortColumn: filter.LastSortColumnValue},
sq.And{
sq.Eq{filter.SortColumn: filter.LastSortColumnValue},
sq.Gt{"u.Id": filter.LastUserId},
},
}).
Where(sq.Expr("u.Id NOT IN (SELECT UserId FROM Bots)")). Where(sq.Expr("u.Id NOT IN (SELECT UserId FROM Bots)")).
GroupBy("u.Id"). GroupBy("u.Id").
OrderBy(sortColumnValue, "u.Id") OrderBy(sortColumnValue, "u.Id")
if (filter.Direction == "up" && !filter.SortDesc) || (filter.Direction == "down" && filter.SortDesc) {
query = query.Where(sq.Or{
sq.Lt{filter.SortColumn: filter.FromColumnValue},
sq.And{
sq.Eq{filter.SortColumn: filter.FromColumnValue},
sq.Lt{"u.Id": filter.FromId},
},
})
} else {
query = query.Where(sq.Or{
sq.Gt{filter.SortColumn: filter.FromColumnValue},
sq.And{
sq.Eq{filter.SortColumn: filter.FromColumnValue},
sq.Gt{"u.Id": filter.FromId},
},
})
}
if filter.PageSize > 0 { if filter.PageSize > 0 {
query = query.Limit(uint64(filter.PageSize)) query = query.Limit(uint64(filter.PageSize))
} }

Просмотреть файл

@@ -6322,10 +6322,61 @@ func testGetUserReport(t *testing.T, rctx request.CTX, ss store.Store) {
userReport, err := ss.User().GetUserReport(&model.UserReportOptions{ userReport, err := ss.User().GetUserReport(&model.UserReportOptions{
ReportingBaseOptions: model.ReportingBaseOptions{ ReportingBaseOptions: model.ReportingBaseOptions{
SortColumn: "Username", SortColumn: "Username",
Direction: "down",
PageSize: 50, PageSize: 50,
LastSortColumnValue: u2.Username, FromColumnValue: u2.Username,
FromId: u2.Id,
},
})
require.NoError(t, err)
require.NotNil(t, userReport)
require.Equal(t, 1, len(userReport))
require.NotNil(t, userReport[0])
require.Equal(t, u3.Username, userReport[0].Username)
userReport, err = ss.User().GetUserReport(&model.UserReportOptions{
ReportingBaseOptions: model.ReportingBaseOptions{
SortColumn: "Username",
SortDesc: true,
Direction: "down",
PageSize: 50,
FromColumnValue: u2.Username,
FromId: u2.Id,
},
})
require.NoError(t, err)
require.NotNil(t, userReport)
require.Equal(t, 1, len(userReport))
require.NotNil(t, userReport[0])
require.Equal(t, u1.Username, userReport[0].Username)
userReport, err = ss.User().GetUserReport(&model.UserReportOptions{
ReportingBaseOptions: model.ReportingBaseOptions{
SortColumn: "Username",
Direction: "up",
PageSize: 50,
FromColumnValue: u2.Username,
FromId: u2.Id,
},
})
require.NoError(t, err)
require.NotNil(t, userReport)
require.Equal(t, 1, len(userReport))
require.NotNil(t, userReport[0])
require.Equal(t, u1.Username, userReport[0].Username)
userReport, err = ss.User().GetUserReport(&model.UserReportOptions{
ReportingBaseOptions: model.ReportingBaseOptions{
SortColumn: "Username",
SortDesc: true,
Direction: "up",
PageSize: 50,
FromColumnValue: u2.Username,
FromId: u2.Id,
}, },
LastUserId: u2.Id,
}) })
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, userReport) require.NotNil(t, userReport)

Просмотреть файл

@@ -1924,6 +1924,9 @@ func (c *Client4) EnableUserAccessToken(ctx context.Context, tokenId string) (*R
func (c *Client4) GetUsersForReporting(ctx context.Context, options *UserReportOptions) ([]*UserReport, *Response, error) { func (c *Client4) GetUsersForReporting(ctx context.Context, options *UserReportOptions) ([]*UserReport, *Response, error) {
values := url.Values{} values := url.Values{}
if options.Direction != "" {
values.Set("direction", options.Direction)
}
if options.SortColumn != "" { if options.SortColumn != "" {
values.Set("sort_column", options.SortColumn) values.Set("sort_column", options.SortColumn)
} }
@@ -1942,11 +1945,11 @@ func (c *Client4) GetUsersForReporting(ctx context.Context, options *UserReportO
if options.SortDesc { if options.SortDesc {
values.Set("sort_direction", "desc") values.Set("sort_direction", "desc")
} }
if options.LastSortColumnValue != "" { if options.FromColumnValue != "" {
values.Set("last_column_value", options.LastSortColumnValue) values.Set("from_column_value", options.FromColumnValue)
} }
if options.LastUserId != "" { if options.FromId != "" {
values.Set("last_id", options.LastUserId) values.Set("from_id", options.FromId)
} }
if options.Role != "" { if options.Role != "" {
values.Set("role_filter", options.Role) values.Set("role_filter", options.Role)

Просмотреть файл

@@ -24,9 +24,11 @@ var (
type ReportingBaseOptions struct { type ReportingBaseOptions struct {
SortDesc bool SortDesc bool
Direction string // Accepts only "up" or "down"
PageSize int PageSize int
SortColumn string SortColumn string
LastSortColumnValue string FromColumnValue string
FromId string
DateRange string DateRange string
StartAt int64 StartAt int64
EndAt int64 EndAt int64
@@ -75,7 +77,6 @@ type UserReport struct {
type UserReportOptions struct { type UserReportOptions struct {
ReportingBaseOptions ReportingBaseOptions
LastUserId string
Role string Role string
Team string Team string
HasNoTeam bool HasNoTeam bool

Просмотреть файл

@@ -48,9 +48,10 @@ export type UserReportOptions = {
sort_column: 'CreateAt' | 'Username' | 'FirstName' | 'LastName' | 'Nickname' | 'Email', sort_column: 'CreateAt' | 'Username' | 'FirstName' | 'LastName' | 'Nickname' | 'Email',
page_size: number, page_size: number,
sort_direction?: 'asc' | 'desc', sort_direction?: 'asc' | 'desc',
direction?: 'up' | 'down',
date_range?: ReportDuration, date_range?: ReportDuration,
last_column_value?: string, from_column_value?: string,
last_id?: string, from_id?: string,
role_filter?: string, role_filter?: string,
has_no_team?: boolean, has_no_team?: boolean,
team_filter?: string, team_filter?: string,