MM-43956: Adds post counts by duration. (#20131)

* MM-43956: Adds post counts by day.

* MM-43956: Test data cleanup. Switch from Unix to UnixMilli.

* MM-43956: Changes from selecting date data types to strings in SQL.

* MM-43956: Fixes date format key.

* MM-43956: Adds missing user id scope for 'my' top channels graph.

* MM-43956: Adds the ability to group post counts by hour.

* MM-43956: Require enterprise or professional license. Reject guests.

* MM-43956: Adds license for tests.

* MM-43956: Renames function.

* MM-43956: Omits future hours from post counts by hour.

* MM-43956: Adjust API response grouping to users timezone.

* MM-43956: Adds translation.

* MM-43956: Adds user's timezone to the data tier for the grouping by day and hour.

* MM-43956: Fixes layers.

* MM-43956: Lint fix.

* MM-43956: Fix store layers.

* MM-43956: Switches to default name for time package; changes parameter names to avoid naming conflict.

* MM-43956: Updates mocks.

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Martin Kraft
2022-06-13 16:22:34 -04:00
коммит произвёл GitHub
родитель c03eb778c8
Коммит 182ae1234a
29 изменённых файлов: 2055 добавлений и 1533 удалений

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

@@ -4297,3 +4297,53 @@ func (s SqlChannelStore) GetTopChannelsForUserSince(userID string, teamID string
return model.GetTopChannelListWithPagination(channels, limit), nil
}
func (s SqlChannelStore) PostCountsByDuration(channelIDs []string, sinceUnixMillis int64, userID *string, duration model.PostCountGrouping, atLocation *time.Location) ([]*model.DurationPostCount, error) {
var unixSelect string
var propsQuery string
loc := atLocation.String()
if loc == "Local" {
loc = "UTC"
}
if s.DriverName() == model.DatabaseDriverMysql {
if duration == model.PostsByDay {
unixSelect = `DATE_FORMAT(CONVERT_TZ(FROM_UNIXTIME(Posts.CreateAt / 1000), 'GMT', '` + loc + `'),'%Y-%m-%d') AS duration`
} else {
unixSelect = `DATE_FORMAT(CONVERT_TZ(FROM_UNIXTIME(Posts.CreateAt / 1000), 'GMT', '` + loc + `'),'%Y-%m-%dT%H') AS duration`
}
propsQuery = `(JSON_EXTRACT(Posts.Props, '$.from_bot') IS NULL OR JSON_EXTRACT(Posts.Props, '$.from_bot') = 'false')`
} else if s.DriverName() == model.DatabaseDriverPostgres {
if duration == model.PostsByDay {
unixSelect = fmt.Sprintf(`TO_CHAR(TO_TIMESTAMP(Posts.CreateAt / 1000) AT TIME ZONE '%s', 'YYYY-MM-DD') AS duration`, loc)
} else {
unixSelect = fmt.Sprintf(`TO_CHAR(TO_TIMESTAMP(Posts.CreateAt / 1000) AT TIME ZONE '%s', 'YYYY-MM-DD"T"HH24') AS duration`, loc)
}
propsQuery = `(Posts.Props ->> 'from_bot' IS NULL OR Posts.Props ->> 'from_bot' = 'false')`
}
query := sq.
Select("Posts.ChannelId AS channelid", unixSelect, "count(Posts.Id) AS postcount").
From("Posts").
LeftJoin("Channels ON Posts.ChannelId = Channels.Id").
Where(sq.And{
sq.Eq{"Posts.DeleteAt": 0},
sq.Gt{"Posts.CreateAt": sinceUnixMillis},
sq.Eq{"Posts.Type": ""},
sq.Eq{"Channels.Id": channelIDs},
}).
Where(propsQuery).
GroupBy("channelid", "duration").
OrderBy("channelid", "duration")
if userID != nil && model.IsValidId(*userID) {
query = query.Where(sq.And{sq.Eq{"Posts.UserId": *userID}})
}
queryString, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrap(err, "failed to parse query")
}
dailyPostCounts := make([]*model.DurationPostCount, 0)
if err := s.GetReplicaX().Select(&dailyPostCounts, queryString, args...); err != nil {
return nil, errors.Wrap(err, "failed to get post counts by duration")
}
return dailyPostCounts, nil
}