From 343c75635713ecbb494b7729558d0ba05eaf85dc Mon Sep 17 00:00:00 2001 From: gordon-- Date: Sat, 20 Feb 2021 23:08:58 +0100 Subject: [PATCH] Heatmap days clickable (#13935) * Heatmap days clickable * Error handling * Unselect filter * better dayclick handler * made linter happy * clickable heatmap for profiles Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: techknowlogick --- models/action.go | 25 +++++++++++++++++------ routers/user/home.go | 1 + routers/user/profile.go | 1 + web_src/js/components/ActivityHeatmap.vue | 21 ++++++++++++++++++- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/models/action.go b/models/action.go index e8a1336566..47d056ae3a 100644 --- a/models/action.go +++ b/models/action.go @@ -289,12 +289,13 @@ func (a *Action) GetIssueContent() string { // GetFeedsOptions options for retrieving feeds type GetFeedsOptions struct { - RequestedUser *User // the user we want activity for - RequestedTeam *Team // the team we want activity for - Actor *User // the user viewing the activity - IncludePrivate bool // include private actions - OnlyPerformedBy bool // only actions performed by requested user - IncludeDeleted bool // include deleted actions + RequestedUser *User // the user we want activity for + RequestedTeam *Team // the team we want activity for + Actor *User // the user viewing the activity + IncludePrivate bool // include private actions + OnlyPerformedBy bool // only actions performed by requested user + IncludeDeleted bool // include deleted actions + Date string // the day we want activity for: YYYY-MM-DD } // GetFeeds returns actions according to the provided options @@ -380,5 +381,17 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) { cond = cond.And(builder.Eq{"is_deleted": false}) } + if opts.Date != "" { + dateLow, err := time.Parse("2006-01-02", opts.Date) + if err != nil { + log.Warn("Unable to parse %s, filter not applied: %v", opts.Date, err) + } else { + dateHigh := dateLow.Add(86399000000000) // 23h59m59s + + cond = cond.And(builder.Gte{"created_unix": dateLow.Unix()}) + cond = cond.And(builder.Lte{"created_unix": dateHigh.Unix()}) + } + } + return cond, nil } diff --git a/routers/user/home.go b/routers/user/home.go index a8a8a5f3d7..a8020b64e0 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -156,6 +156,7 @@ func Dashboard(ctx *context.Context) { IncludePrivate: true, OnlyPerformedBy: false, IncludeDeleted: false, + Date: ctx.Query("date"), }) if ctx.Written() { diff --git a/routers/user/profile.go b/routers/user/profile.go index e19407baa7..5dfee07d76 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -202,6 +202,7 @@ func Profile(ctx *context.Context) { IncludePrivate: showPrivate, OnlyPerformedBy: true, IncludeDeleted: false, + Date: ctx.Query("date"), }) if ctx.Written() { return diff --git a/web_src/js/components/ActivityHeatmap.vue b/web_src/js/components/ActivityHeatmap.vue index 7eb129d139..63e38ea69e 100644 --- a/web_src/js/components/ActivityHeatmap.vue +++ b/web_src/js/components/ActivityHeatmap.vue @@ -10,6 +10,7 @@ :end-date="endDate" :values="values" :range-color="colorRange" + @day-click="handleDayClick($event)" /> @@ -48,7 +49,25 @@ export default { } return s; } - } + }, + methods: { + handleDayClick(e) { + // Reset filter if same date is clicked + const params = new URLSearchParams(document.location.search); + const queryDate = params.get('date'); + // Timezone has to be stripped because toISOString() converts to UTC + const clickedDate = new Date(e.date - (e.date.getTimezoneOffset() * 60000)).toISOString().substring(0, 10); + + if (queryDate && queryDate === clickedDate) { + params.delete('date'); + } else { + params.set('date', clickedDate); + } + + const newSearch = params.toString(); + window.location.search = newSearch.length ? `?${newSearch}` : ''; + } + }, };