Skip to content

Commit

Permalink
Fix heatmap activity (go-gitea#15252)
Browse files Browse the repository at this point in the history
* Group heatmap actions by 15 minute intervals

Signed-off-by: Sidd Weiker <siddweiker@gmail.com>

* Add multi-contribution test for user heatmap

Signed-off-by: Sidd Weiker <siddweiker@gmail.com>

* Add timezone aware summation for activity heatmap

Signed-off-by: Sidd Weiker <siddweiker@gmail.com>

* Fix api user heatmap test

Signed-off-by: Sidd Weiker <siddweiker@gmail.com>

* Update variable declaration style

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
  • Loading branch information
4 people authored and AbdulrhmnGhanem committed Aug 10, 2021
1 parent fc2eb5d commit f9218bb
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 18 deletions.
2 changes: 1 addition & 1 deletion integrations/api_user_heatmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestUserHeatmap(t *testing.T) {
var heatmap []*models.UserHeatmapData
DecodeJSON(t, resp, &heatmap)
var dummyheatmap []*models.UserHeatmapData
dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1603152000, Contributions: 1})
dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1603227600, Contributions: 1})

assert.Equal(t, dummyheatmap, heatmap)
}
24 changes: 24 additions & 0 deletions models/fixtures/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,27 @@
repo_id: 22
is_private: true
created_unix: 1603267920

- id: 5
user_id: 10
op_type: 1 # create repo
act_user_id: 10
repo_id: 6
is_private: true
created_unix: 1603010100

- id: 6
user_id: 10
op_type: 1 # create repo
act_user_id: 10
repo_id: 7
is_private: true
created_unix: 1603011300

- id: 7
user_id: 10
op_type: 1 # create repo
act_user_id: 10
repo_id: 8
is_private: false
created_unix: 1603011540 # grouped with id:7
11 changes: 4 additions & 7 deletions models/user_heatmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,14 @@ func getUserHeatmapData(user *User, team *Team, doer *User) ([]*UserHeatmapData,
return hdata, nil
}

var groupBy string
// Group by 15 minute intervals which will allow the client to accurately shift the timestamp to their timezone.
// The interval is based on the fact that there are timezones such as UTC +5:30 and UTC +12:45.
groupBy := "created_unix / 900 * 900"
groupByName := "timestamp" // We need this extra case because mssql doesn't allow grouping by alias
switch {
case setting.Database.UseSQLite3:
groupBy = "strftime('%s', strftime('%Y-%m-%d', created_unix, 'unixepoch'))"
case setting.Database.UseMySQL:
groupBy = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(created_unix)))"
case setting.Database.UsePostgreSQL:
groupBy = "extract(epoch from date_trunc('day', to_timestamp(created_unix)))"
groupBy = "created_unix DIV 900 * 900"
case setting.Database.UseMSSQL:
groupBy = "datediff(SECOND, '19700101', dateadd(DAY, 0, datediff(day, 0, dateadd(s, created_unix, '19700101'))))"
groupByName = groupBy
}

Expand Down
28 changes: 20 additions & 8 deletions models/user_heatmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
CountResult int
JSONResult string
}{
{2, 2, 1, `[{"timestamp":1603152000,"contributions":1}]`}, // self looks at action in private repo
{2, 1, 1, `[{"timestamp":1603152000,"contributions":1}]`}, // admin looks at action in private repo
{2, 3, 0, `[]`}, // other user looks at action in private repo
{2, 0, 0, `[]`}, // nobody looks at action in private repo
{16, 15, 1, `[{"timestamp":1603238400,"contributions":1}]`}, // collaborator looks at action in private repo
{3, 3, 0, `[]`}, // no action action not performed by target user
// self looks at action in private repo
{2, 2, 1, `[{"timestamp":1603227600,"contributions":1}]`},
// admin looks at action in private repo
{2, 1, 1, `[{"timestamp":1603227600,"contributions":1}]`},
// other user looks at action in private repo
{2, 3, 0, `[]`},
// nobody looks at action in private repo
{2, 0, 0, `[]`},
// collaborator looks at action in private repo
{16, 15, 1, `[{"timestamp":1603267200,"contributions":1}]`},
// no action action not performed by target user
{3, 3, 0, `[]`},
// multiple actions performed with two grouped together
{10, 10, 3, `[{"timestamp":1603009800,"contributions":1},{"timestamp":1603010700,"contributions":2}]`},
}
// Prepare
assert.NoError(t, PrepareTestDatabase())
Expand All @@ -51,9 +59,13 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {

// Get the heatmap and compare
heatmap, err := GetUserHeatmapDataByUser(user, doer)
var contributions int
for _, hm := range heatmap {
contributions += int(hm.Contributions)
}
assert.NoError(t, err)
assert.Len(t, heatmap, len(actions), "invalid action count: did the test data became too old?")
assert.Len(t, heatmap, tc.CountResult, fmt.Sprintf("testcase %d", i))
assert.Len(t, actions, contributions, "invalid action count: did the test data became too old?")
assert.Equal(t, tc.CountResult, contributions, fmt.Sprintf("testcase %d", i))

// Test JSON rendering
json := jsoniter.ConfigCompatibleWithStandardLibrary
Expand Down
11 changes: 9 additions & 2 deletions web_src/js/features/heatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ export default async function initHeatmap() {
if (!el) return;

try {
const values = JSON.parse(el.dataset.heatmapData).map(({contributions, timestamp}) => {
return {date: new Date(timestamp * 1000), count: contributions};
const heatmap = {};
JSON.parse(el.dataset.heatmapData).forEach(({contributions, timestamp}) => {
// Convert to user timezone and sum contributions by date
const dateStr = new Date(timestamp * 1000).toDateString();
heatmap[dateStr] = (heatmap[dateStr] || 0) + contributions;
});

const values = Object.keys(heatmap).map((v) => {
return {date: new Date(v), count: heatmap[v]};
});

const View = Vue.extend({
Expand Down

0 comments on commit f9218bb

Please sign in to comment.