Skip to content

Commit 12c2efb

Browse files
authored
Remove fetch request from heatmap (#13623)
* Remove fetch request from heatmap Render heatmap data directly to HTML, eliminating one HTTP request on frontpage and user profile. Also added min-height to the container so the page content will no longer move after loading. * rename and error display * also log the js error * add error handler * remove useless inline style and hide divider on small screens * Update routers/user/home.go * Update routers/user/profile.go
1 parent d02c350 commit 12c2efb

File tree

11 files changed

+86
-74
lines changed

11 files changed

+86
-74
lines changed

routers/user/home.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,14 @@ func Dashboard(ctx *context.Context) {
114114
ctx.Data["SearchLimit"] = setting.UI.User.RepoPagingNum
115115
// no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user
116116
// so everyone would get the same empty heatmap
117-
ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate
118-
ctx.Data["HeatmapUser"] = ctxUser.Name
117+
if setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate {
118+
data, err := models.GetUserHeatmapDataByUser(ctxUser)
119+
if err != nil {
120+
ctx.ServerError("GetUserHeatmapDataByUser", err)
121+
return
122+
}
123+
ctx.Data["HeatmapData"] = data
124+
}
119125

120126
var err error
121127
var mirrors []*models.Repository

routers/user/profile.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,18 @@ func Profile(ctx *context.Context) {
9494
ctx.Data["PageIsUserProfile"] = true
9595
ctx.Data["Owner"] = ctxUser
9696
ctx.Data["OpenIDs"] = openIDs
97+
9798
// no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user
9899
// so everyone would get the same empty heatmap
99-
ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate
100-
ctx.Data["HeatmapUser"] = ctxUser.Name
100+
if setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate {
101+
data, err := models.GetUserHeatmapDataByUser(ctxUser)
102+
if err != nil {
103+
ctx.ServerError("GetUserHeatmapDataByUser", err)
104+
return
105+
}
106+
ctx.Data["HeatmapData"] = data
107+
}
108+
101109
if len(ctxUser.Description) != 0 {
102110
ctx.Data["RenderedDescription"] = string(markdown.Render([]byte(ctxUser.Description), ctx.Repo.RepoLink, map[string]string{"mode": "document"}))
103111
}

templates/base/head.tmpl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
SimpleMDE: {{if .RequireSimpleMDE}}true{{else}}false{{end}},
3737
Tribute: {{if .RequireTribute}}true{{else}}false{{end}},
3838
U2F: {{if .RequireU2F}}true{{else}}false{{end}},
39-
Heatmap: {{if .EnableHeatmap}}true{{else}}false{{end}},
40-
heatmapUser: {{if .HeatmapUser}}'{{.HeatmapUser}}'{{else}}null{{end}},
4139
NotificationSettings: {
4240
MinTimeout: {{NotificationSettings.MinTimeout}},
4341
TimeoutStep: {{NotificationSettings.TimeoutStep}},

templates/user/dashboard/dashboard.tmpl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
{{template "base/alert" .}}
66
<div class="ui mobile reversed stackable grid">
77
<div class="ui container ten wide column">
8-
{{if .EnableHeatmap}}
9-
{{template "user/dashboard/heatmap" .}}
10-
<div class="ui divider"></div>
11-
{{end}}
8+
{{template "user/heatmap" .}}
129
{{template "user/dashboard/feeds" .}}
1310
</div>
1411
{{template "user/dashboard/repolist" .}}
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
<div id="user-heatmap" style="padding-right: 40px">
2-
<activity-heatmap :locale="locale" :suburl="suburl" :user="heatmapUser">
1+
{{if .HeatmapData}}
2+
<div id="user-heatmap" data-heatmap-data="{{Json .HeatmapData}}">
33
<div slot="loading">
44
<div class="ui active centered inline indeterminate text loader" id="loading-heatmap">{{.i18n.Tr "user.heatmap.loading"}}</div>
55
</div>
6-
</activity-heatmap>
7-
</div>
6+
</div>
7+
<div class="ui divider"></div>
8+
{{end}}

templates/user/profile.tmpl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,7 @@
108108
<p>{{.i18n.Tr "user.disabled_public_activity"}}</p>
109109
</div>
110110
{{end}}
111-
{{if .EnableHeatmap}}
112-
{{template "user/dashboard/heatmap" .}}
113-
<div class="ui divider"></div>
114-
{{end}}
111+
{{template "user/heatmap" .}}
115112
<div class="feeds">
116113
{{template "user/dashboard/feeds" .}}
117114
</div>
Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
<template>
2-
<div class="heatmap-container">
3-
<div v-show="isLoading">
4-
<slot name="loading"/>
5-
</div>
6-
<div v-if="!isLoading" class="total-contributions">
2+
<div id="user-heatmap">
3+
<div class="total-contributions">
74
{{ values.length }} contributions in the last 12 months
85
</div>
96
<calendar-heatmap
10-
v-show="!isLoading"
117
:locale="locale"
128
:no-data-text="locale.no_contributions"
139
:tooltip-unit="locale.contributions"
@@ -19,13 +15,17 @@
1915
</template>
2016
<script>
2117
import {CalendarHeatmap} from 'vue-calendar-heatmap';
22-
const {AppSubUrl, heatmapUser} = window.config;
2318
2419
export default {
2520
name: 'ActivityHeatmap',
2621
components: {CalendarHeatmap},
22+
props: {
23+
values: {
24+
type: Array,
25+
default: () => [],
26+
},
27+
},
2728
data: () => ({
28-
isLoading: true,
2929
colorRange: [
3030
'var(--color-secondary-alpha-70)',
3131
'var(--color-primary-light-4)',
@@ -35,20 +35,11 @@ export default {
3535
'var(--color-primary-dark-4)',
3636
],
3737
endDate: new Date(),
38-
values: [],
3938
locale: {
4039
contributions: 'contributions',
4140
no_contributions: 'No contributions',
4241
},
4342
}),
44-
async mounted() {
45-
const res = await fetch(`${AppSubUrl}/api/v1/users/${heatmapUser}/heatmap`);
46-
const data = await res.json();
47-
this.values = data.map(({contributions, timestamp}) => {
48-
return {date: new Date(timestamp * 1000), count: contributions};
49-
});
50-
this.isLoading = false;
51-
},
5243
};
5344
</script>
5445
<style scoped/>

web_src/js/features/heatmap.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Vue from 'vue';
2+
3+
import ActivityHeatmap from '../components/ActivityHeatmap.vue';
4+
5+
export default async function initHeatmap() {
6+
const el = document.getElementById('user-heatmap');
7+
if (!el) return;
8+
9+
try {
10+
const values = JSON.parse(el.dataset.heatmapData).map(({contributions, timestamp}) => {
11+
return {date: new Date(timestamp * 1000), count: contributions};
12+
});
13+
14+
const View = Vue.extend({
15+
render: (createElement) => createElement(ActivityHeatmap, {props: {values}}),
16+
});
17+
18+
new View().$mount(el);
19+
} catch (err) {
20+
console.error(err);
21+
el.textContent = 'Heatmap failed to load';
22+
}
23+
}

web_src/js/features/userheatmap.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

web_src/js/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import initMigration from './features/migration.js';
1212
import initContextPopups from './features/contextpopup.js';
1313
import initGitGraph from './features/gitgraph.js';
1414
import initClipboard from './features/clipboard.js';
15-
import initUserHeatmap from './features/userheatmap.js';
15+
import initHeatmap from './features/heatmap.js';
1616
import initProject from './features/projects.js';
1717
import initServiceWorker from './features/serviceworker.js';
1818
import initMarkdownAnchors from './markdown/anchors.js';
@@ -2553,7 +2553,7 @@ $(document).ready(async () => {
25532553
attachTribute(document.querySelectorAll('#content, .emoji-input')),
25542554
initGitGraph(),
25552555
initClipboard(),
2556-
initUserHeatmap(),
2556+
initHeatmap(),
25572557
initProject(),
25582558
initServiceWorker(),
25592559
initNotificationCount(),

web_src/less/features/heatmap.less

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,50 @@
11
#user-heatmap {
2-
width: 107%; // Fixes newest contributions not showing
2+
width: 100%;
33
text-align: center;
4+
position: relative;
5+
min-height: 125px;
6+
display: flex;
7+
align-items: center;
8+
justify-content: center;
49

510
svg:not(:root) {
611
overflow: inherit;
712
padding: 0 !important;
813
}
914

15+
text {
16+
fill: currentColor !important;
17+
}
18+
1019
@media @mediaLgAndDown {
11-
& {
20+
&,
21+
& + .divider {
1222
display: none;
1323
}
1424
}
1525

1626
.total-contributions {
17-
text-align: left;
18-
margin-top: 0;
27+
font-size: 11px;
28+
position: absolute;
29+
bottom: 0;
30+
left: 25px;
1931
}
20-
}
21-
22-
.heatmap-container {
23-
position: relative;
24-
}
2532

26-
.heatmap-container .total-contributions {
27-
font-size: 11px;
28-
position: absolute;
29-
bottom: 0;
30-
left: 25px;
31-
}
32-
33-
@media @mediaLgAndDown {
34-
.heatmap-container .total-contributions {
35-
left: 21px;
33+
@media @mediaLgAndDown {
34+
.total-contributions {
35+
left: 21px;
36+
}
3637
}
37-
}
3838

39-
@media (max-width: 1000px) {
40-
.heatmap-container .total-contributions {
41-
font-size: 10px;
42-
left: 17px;
43-
bottom: -2px;
39+
@media (max-width: 1000px) {
40+
.total-contributions {
41+
font-size: 10px;
42+
left: 17px;
43+
bottom: -2px;
44+
}
4445
}
4546
}
4647

47-
.heatmap-container text {
48-
fill: currentColor !important;
48+
.user.profile #user-heatmap {
49+
min-height: 135px;
4950
}

0 commit comments

Comments
 (0)