diff --git a/routers/user/home.go b/routers/user/home.go
index f7f1786b330..779971ca97d 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -114,8 +114,14 @@ func Dashboard(ctx *context.Context) {
ctx.Data["SearchLimit"] = setting.UI.User.RepoPagingNum
// no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user
// so everyone would get the same empty heatmap
- ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate
- ctx.Data["HeatmapUser"] = ctxUser.Name
+ if setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate {
+ data, err := models.GetUserHeatmapDataByUser(ctxUser)
+ if err != nil {
+ ctx.ServerError("GetUserHeatmapDataByUser", err)
+ return
+ }
+ ctx.Data["HeatmapData"] = data
+ }
var err error
var mirrors []*models.Repository
diff --git a/routers/user/profile.go b/routers/user/profile.go
index 8bf5cacc566..36f3d0735d6 100644
--- a/routers/user/profile.go
+++ b/routers/user/profile.go
@@ -94,10 +94,18 @@ func Profile(ctx *context.Context) {
ctx.Data["PageIsUserProfile"] = true
ctx.Data["Owner"] = ctxUser
ctx.Data["OpenIDs"] = openIDs
+
// no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user
// so everyone would get the same empty heatmap
- ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate
- ctx.Data["HeatmapUser"] = ctxUser.Name
+ if setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate {
+ data, err := models.GetUserHeatmapDataByUser(ctxUser)
+ if err != nil {
+ ctx.ServerError("GetUserHeatmapDataByUser", err)
+ return
+ }
+ ctx.Data["HeatmapData"] = data
+ }
+
if len(ctxUser.Description) != 0 {
ctx.Data["RenderedDescription"] = string(markdown.Render([]byte(ctxUser.Description), ctx.Repo.RepoLink, map[string]string{"mode": "document"}))
}
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index 4738b914635..c8e669387b6 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -36,8 +36,6 @@
SimpleMDE: {{if .RequireSimpleMDE}}true{{else}}false{{end}},
Tribute: {{if .RequireTribute}}true{{else}}false{{end}},
U2F: {{if .RequireU2F}}true{{else}}false{{end}},
- Heatmap: {{if .EnableHeatmap}}true{{else}}false{{end}},
- heatmapUser: {{if .HeatmapUser}}'{{.HeatmapUser}}'{{else}}null{{end}},
NotificationSettings: {
MinTimeout: {{NotificationSettings.MinTimeout}},
TimeoutStep: {{NotificationSettings.TimeoutStep}},
diff --git a/templates/user/dashboard/dashboard.tmpl b/templates/user/dashboard/dashboard.tmpl
index 7a4968ebe6a..dc04d656518 100644
--- a/templates/user/dashboard/dashboard.tmpl
+++ b/templates/user/dashboard/dashboard.tmpl
@@ -5,10 +5,7 @@
{{template "base/alert" .}}
- {{if .EnableHeatmap}}
- {{template "user/dashboard/heatmap" .}}
-
- {{end}}
+ {{template "user/heatmap" .}}
{{template "user/dashboard/feeds" .}}
{{template "user/dashboard/repolist" .}}
diff --git a/templates/user/dashboard/heatmap.tmpl b/templates/user/heatmap.tmpl
similarity index 51%
rename from templates/user/dashboard/heatmap.tmpl
rename to templates/user/heatmap.tmpl
index 626c70dd8db..a569405d16f 100644
--- a/templates/user/dashboard/heatmap.tmpl
+++ b/templates/user/heatmap.tmpl
@@ -1,7 +1,8 @@
-
-
+{{if .HeatmapData}}
+
{{.i18n.Tr "user.heatmap.loading"}}
-
-
+
+
+{{end}}
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index 3a3192a8283..d6b99b38614 100644
--- a/templates/user/profile.tmpl
+++ b/templates/user/profile.tmpl
@@ -108,10 +108,7 @@
{{.i18n.Tr "user.disabled_public_activity"}}
{{end}}
- {{if .EnableHeatmap}}
- {{template "user/dashboard/heatmap" .}}
-
- {{end}}
+ {{template "user/heatmap" .}}
{{template "user/dashboard/feeds" .}}
diff --git a/web_src/js/components/ActivityHeatmap.vue b/web_src/js/components/ActivityHeatmap.vue
index 1970cb609a2..943bf704e28 100644
--- a/web_src/js/components/ActivityHeatmap.vue
+++ b/web_src/js/components/ActivityHeatmap.vue
@@ -1,13 +1,9 @@
-
-
-
-
-
+
+
{{ values.length }} contributions in the last 12 months
diff --git a/web_src/js/features/heatmap.js b/web_src/js/features/heatmap.js
new file mode 100644
index 00000000000..d1cb43dde0e
--- /dev/null
+++ b/web_src/js/features/heatmap.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+
+import ActivityHeatmap from '../components/ActivityHeatmap.vue';
+
+export default async function initHeatmap() {
+ const el = document.getElementById('user-heatmap');
+ if (!el) return;
+
+ try {
+ const values = JSON.parse(el.dataset.heatmapData).map(({contributions, timestamp}) => {
+ return {date: new Date(timestamp * 1000), count: contributions};
+ });
+
+ const View = Vue.extend({
+ render: (createElement) => createElement(ActivityHeatmap, {props: {values}}),
+ });
+
+ new View().$mount(el);
+ } catch (err) {
+ console.error(err);
+ el.textContent = 'Heatmap failed to load';
+ }
+}
diff --git a/web_src/js/features/userheatmap.js b/web_src/js/features/userheatmap.js
deleted file mode 100644
index f7e0d1a75f1..00000000000
--- a/web_src/js/features/userheatmap.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import Vue from 'vue';
-
-import ActivityHeatmap from '../components/ActivityHeatmap.vue';
-
-export default async function initUserHeatmap() {
- const el = document.getElementById('user-heatmap');
- if (!el) return;
- const View = Vue.extend(ActivityHeatmap);
- new View().$mount(el);
-}
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 1f4c9a509a2..fc491956071 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -12,7 +12,7 @@ import initMigration from './features/migration.js';
import initContextPopups from './features/contextpopup.js';
import initGitGraph from './features/gitgraph.js';
import initClipboard from './features/clipboard.js';
-import initUserHeatmap from './features/userheatmap.js';
+import initHeatmap from './features/heatmap.js';
import initProject from './features/projects.js';
import initServiceWorker from './features/serviceworker.js';
import initMarkdownAnchors from './markdown/anchors.js';
@@ -2553,7 +2553,7 @@ $(document).ready(async () => {
attachTribute(document.querySelectorAll('#content, .emoji-input')),
initGitGraph(),
initClipboard(),
- initUserHeatmap(),
+ initHeatmap(),
initProject(),
initServiceWorker(),
initNotificationCount(),
diff --git a/web_src/less/features/heatmap.less b/web_src/less/features/heatmap.less
index 5383847387c..61db5c81b02 100644
--- a/web_src/less/features/heatmap.less
+++ b/web_src/less/features/heatmap.less
@@ -1,49 +1,50 @@
#user-heatmap {
- width: 107%; // Fixes newest contributions not showing
+ width: 100%;
text-align: center;
+ position: relative;
+ min-height: 125px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
svg:not(:root) {
overflow: inherit;
padding: 0 !important;
}
+ text {
+ fill: currentColor !important;
+ }
+
@media @mediaLgAndDown {
- & {
+ &,
+ & + .divider {
display: none;
}
}
.total-contributions {
- text-align: left;
- margin-top: 0;
+ font-size: 11px;
+ position: absolute;
+ bottom: 0;
+ left: 25px;
+ }
+
+ @media @mediaLgAndDown {
+ .total-contributions {
+ left: 21px;
+ }
+ }
+
+ @media (max-width: 1000px) {
+ .total-contributions {
+ font-size: 10px;
+ left: 17px;
+ bottom: -2px;
+ }
}
}
-.heatmap-container {
- position: relative;
-}
-
-.heatmap-container .total-contributions {
- font-size: 11px;
- position: absolute;
- bottom: 0;
- left: 25px;
-}
-
-@media @mediaLgAndDown {
- .heatmap-container .total-contributions {
- left: 21px;
- }
-}
-
-@media (max-width: 1000px) {
- .heatmap-container .total-contributions {
- font-size: 10px;
- left: 17px;
- bottom: -2px;
- }
-}
-
-.heatmap-container text {
- fill: currentColor !important;
+.user.profile #user-heatmap {
+ min-height: 135px;
}