MM-45899: Insights: least active channels (#20796)
* Add api endpoints, app layers for top inactive channels with dummy store calls * Add store functions for top inactive channels * Add model, store, app tests. * Add client function and api tests * Add participants information to TopInactiveChannel * Translation fix * Style fix while writing response * Return channelmember IDs instead of profiles, query in batch avoiding inside the loop * Make the following changes - move DeleteAt to subqueries, to avoid select, group by - Remove TeamId from response - Count bots and webhook posts * SQL query lint fix, store test fix to include bot messages * make app-layers * Fix empty participant lists being sent as [""] * Track channel joins, to distinguish 0 activity channels vs new channels Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8fd1762c3b
Коммит
6adbcc5d05
@@ -27,6 +27,10 @@ func (api *API) InitInsights() {
|
||||
// user DMs
|
||||
api.BaseRoutes.InsightsForUser.Handle("/dms", api.APISessionRequired(minimumProfessionalLicense(rejectGuests(getTopDMsForUserSince)))).Methods("GET")
|
||||
|
||||
// Inactive channels
|
||||
api.BaseRoutes.InsightsForTeam.Handle("/inactive_channels", api.APISessionRequired(minimumProfessionalLicense(rejectGuests(getTopInactiveChannelsForTeamSince)))).Methods("GET")
|
||||
api.BaseRoutes.InsightsForUser.Handle("/inactive_channels", api.APISessionRequired(minimumProfessionalLicense(rejectGuests(getTopInactiveChannelsForUserSince)))).Methods("GET")
|
||||
|
||||
// New teammembers
|
||||
api.BaseRoutes.InsightsForTeam.Handle("/team_members", api.APISessionRequired(minimumProfessionalLicense(rejectGuests(getNewTeamMembersSince)))).Methods("GET")
|
||||
}
|
||||
@@ -360,6 +364,100 @@ func getTopDMsForUserSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
// Top Channels
|
||||
|
||||
func getTopInactiveChannelsForTeamSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireTeamId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
team, err := c.App.GetTeam(c.Params.TeamId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := c.App.GetUser(c.AppContext.Session().UserId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
loc := user.GetTimezoneLocation()
|
||||
startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, loc)
|
||||
|
||||
topChannels, err := c.App.GetTopInactiveChannelsForTeamSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{
|
||||
StartUnixMilli: startTime.UnixMilli(),
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(topChannels); err != nil {
|
||||
c.Err = model.NewAppError("getTopInactiveChannelsForTeamSince", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// top inactive channels
|
||||
|
||||
func getTopInactiveChannelsForUserSince(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.Params.TeamId = r.URL.Query().Get("team_id")
|
||||
|
||||
// TeamId is an optional parameter
|
||||
if c.Params.TeamId != "" {
|
||||
if !model.IsValidId(c.Params.TeamId) {
|
||||
c.SetInvalidURLParam("team_id")
|
||||
return
|
||||
}
|
||||
|
||||
team, teamErr := c.App.GetTeam(c.Params.TeamId)
|
||||
if teamErr != nil {
|
||||
c.Err = teamErr
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), team.Id, model.PermissionViewTeam) {
|
||||
c.SetPermissionError(model.PermissionViewTeam)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
user, err := c.App.GetUser(c.AppContext.Session().UserId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
loc := user.GetTimezoneLocation()
|
||||
startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, loc)
|
||||
|
||||
topChannels, err := c.App.GetTopInactiveChannelsForUserSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{
|
||||
StartUnixMilli: startTime.UnixMilli(),
|
||||
Page: c.Params.Page,
|
||||
PerPage: c.Params.PerPage,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(topChannels); err != nil {
|
||||
c.Err = model.NewAppError("getTopInactiveChannelsForUserSince", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// postCountByDurationViewModel expects a list of channels that are pre-authorized for the given user to view.
|
||||
func postCountByDurationViewModel(c *Context, topChannelList *model.TopChannelList, startTime *time.Time, timeRange string, userID *string, location *time.Location) (model.ChannelPostCountByDuration, *model.AppError) {
|
||||
if len(topChannelList.Items) == 0 {
|
||||
|
||||
Ссылка в новой задаче
Block a user