gitea源码

user_heatmap.go 2.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2018 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package activities
  4. import (
  5. "context"
  6. "code.gitea.io/gitea/models/db"
  7. "code.gitea.io/gitea/models/organization"
  8. user_model "code.gitea.io/gitea/models/user"
  9. "code.gitea.io/gitea/modules/setting"
  10. "code.gitea.io/gitea/modules/timeutil"
  11. )
  12. // UserHeatmapData represents the data needed to create a heatmap
  13. type UserHeatmapData struct {
  14. Timestamp timeutil.TimeStamp `json:"timestamp"`
  15. Contributions int64 `json:"contributions"`
  16. }
  17. // GetUserHeatmapDataByUser returns an array of UserHeatmapData
  18. func GetUserHeatmapDataByUser(ctx context.Context, user, doer *user_model.User) ([]*UserHeatmapData, error) {
  19. return getUserHeatmapData(ctx, user, nil, doer)
  20. }
  21. // GetUserHeatmapDataByUserTeam returns an array of UserHeatmapData
  22. func GetUserHeatmapDataByUserTeam(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
  23. return getUserHeatmapData(ctx, user, team, doer)
  24. }
  25. func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
  26. hdata := make([]*UserHeatmapData, 0)
  27. if !ActivityReadable(user, doer) {
  28. return hdata, nil
  29. }
  30. // Group by 15 minute intervals which will allow the client to accurately shift the timestamp to their timezone.
  31. // The interval is based on the fact that there are timezones such as UTC +5:30 and UTC +12:45.
  32. groupBy := "created_unix / 900 * 900"
  33. groupByName := "timestamp" // We need this extra case because mssql doesn't allow grouping by alias
  34. switch {
  35. case setting.Database.Type.IsMySQL():
  36. groupBy = "created_unix DIV 900 * 900"
  37. case setting.Database.Type.IsMSSQL():
  38. groupByName = groupBy
  39. }
  40. cond, err := ActivityQueryCondition(ctx, GetFeedsOptions{
  41. RequestedUser: user,
  42. RequestedTeam: team,
  43. Actor: doer,
  44. IncludePrivate: true, // don't filter by private, as we already filter by repo access
  45. IncludeDeleted: true,
  46. // * Heatmaps for individual users only include actions that the user themself did.
  47. // * For organizations actions by all users that were made in owned
  48. // repositories are counted.
  49. OnlyPerformedBy: !user.IsOrganization(),
  50. })
  51. if err != nil {
  52. return nil, err
  53. }
  54. return hdata, db.GetEngine(ctx).
  55. Select(groupBy+" AS timestamp, count(user_id) as contributions").
  56. Table("action").
  57. Where(cond).
  58. And("created_unix > ?", timeutil.TimeStampNow()-(366+7)*86400). // (366+7) days to include the first week for the heatmap
  59. GroupBy(groupByName).
  60. OrderBy("timestamp").
  61. Find(&hdata)
  62. }
  63. // GetTotalContributionsInHeatmap returns the total number of contributions in a heatmap
  64. func GetTotalContributionsInHeatmap(hdata []*UserHeatmapData) int64 {
  65. var total int64
  66. for _, v := range hdata {
  67. total += v.Contributions
  68. }
  69. return total
  70. }