From 9cab4a716bbd551321102ffb7b883e39ed15c508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Niclas=20Oelschl=C3=A4ger?= Date: Thu, 22 Feb 2024 00:45:15 +0100 Subject: [PATCH] feature: heatmap visibility options --- models/activities/action.go | 19 +++++----- models/activities/user_heatmap.go | 5 +-- models/user/user.go | 7 ++-- modules/structs/heatmap_visibility.go | 50 +++++++++++++++++++++++++++ options/locale/locale_en-US.ini | 9 +++++ routers/web/user/setting/profile.go | 1 + services/forms/user_form.go | 1 + services/user/update.go | 6 ++++ templates/user/profile.tmpl | 11 ++++-- templates/user/settings/profile.tmpl | 18 ++++++++++ 10 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 modules/structs/heatmap_visibility.go diff --git a/models/activities/action.go b/models/activities/action.go index 15bd9a52ac..95d5c1d085 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -425,14 +425,15 @@ func (a *Action) GetIssueContent(ctx context.Context) string { // GetFeedsOptions options for retrieving feeds type GetFeedsOptions struct { db.ListOptions - RequestedUser *user_model.User // the user we want activity for - RequestedTeam *organization.Team // the team we want activity for - RequestedRepo *repo_model.Repository // the repo we want activity for - Actor *user_model.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 + RequestedUser *user_model.User // the user we want activity for + RequestedTeam *organization.Team // the team we want activity for + RequestedRepo *repo_model.Repository // the repo we want activity for + Actor *user_model.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 + IncludePrivateRepos bool // include private repos } // GetFeeds returns actions according to the provided options @@ -515,7 +516,7 @@ func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder. } // check readable repositories by doer/actor - if opts.Actor == nil || !opts.Actor.IsAdmin { + if opts.Actor == nil || !opts.IncludePrivateRepos && !opts.Actor.IsAdmin { cond = cond.And(builder.In("repo_id", repo_model.AccessibleRepoIDsQuery(opts.Actor))) } diff --git a/models/activities/user_heatmap.go b/models/activities/user_heatmap.go index 78fcd76d43..709480bfe8 100644 --- a/models/activities/user_heatmap.go +++ b/models/activities/user_heatmap.go @@ -32,7 +32,7 @@ func GetUserHeatmapDataByUserTeam(ctx context.Context, user *user_model.User, te func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) { hdata := make([]*UserHeatmapData, 0) - if !ActivityReadable(user, doer) { + if !ActivityReadable(user, doer) || user.HeatmapVisibility.ShowNone() { return hdata, nil } @@ -56,7 +56,8 @@ func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organi // * Heatmaps for individual users only include actions that the user themself did. // * For organizations actions by all users that were made in owned // repositories are counted. - OnlyPerformedBy: !user.IsOrganization(), + OnlyPerformedBy: !user.IsOrganization(), + IncludePrivateRepos: user.HeatmapVisibility.ShowAll(), }) if err != nil { return nil, err diff --git a/models/user/user.go b/models/user/user.go index f31dfb76bb..8137515e6a 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -142,9 +142,10 @@ type User struct { RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"` // Preferences - DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` - Theme string `xorm:"NOT NULL DEFAULT ''"` - KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` + DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` + Theme string `xorm:"NOT NULL DEFAULT ''"` + KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` + HeatmapVisibility structs.HeatmapVisibility `xorm:"NOT NULL DEFAULT 0"` } func init() { diff --git a/modules/structs/heatmap_visibility.go b/modules/structs/heatmap_visibility.go new file mode 100644 index 0000000000..a5b178e5d8 --- /dev/null +++ b/modules/structs/heatmap_visibility.go @@ -0,0 +1,50 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +// HeatmapVisibility defines the activities shown in heatmap +type HeatmapVisibility int + +const ( + // HeatmapVisibilityPublic show public activities in heatmap + HeatmapVisibilityPublic HeatmapVisibility = iota + + // HeatmapVisibilityAll shows all activities in heatmap + HeatmapVisibilityAll + + // HeatmapVisibilityNone show no activities in heatmap + HeatmapVisibilityNone +) + +// HeatmapVisibilities is a map of HeatmapVisibility types +var HeatmapVisibilities = map[string]HeatmapVisibility{ + "public": HeatmapVisibilityPublic, + "all": HeatmapVisibilityAll, + "none": HeatmapVisibilityNone, +} + +// ShowPublic returns true if HeatmapVisibility is public +func (vt HeatmapVisibility) ShowPublic() bool { + return vt == HeatmapVisibilityPublic +} + +// ShowAll returns true if HeatmapVisibility is all +func (vt HeatmapVisibility) ShowAll() bool { + return vt == HeatmapVisibilityAll +} + +// ShowNone returns true if HeatmapVisibility is none +func (vt HeatmapVisibility) ShowNone() bool { + return vt == HeatmapVisibilityNone +} + +// String provides the mode string of the visibility type (public, all, none) +func (vt HeatmapVisibility) String() string { + for k, v := range HeatmapVisibilities { + if vt == v { + return k + } + } + return "" +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 574e99e654..2a2af95088 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -608,6 +608,7 @@ follow = Follow unfollow = Unfollow user_bio = Biography disabled_public_activity = This user has disabled the public visibility of the activity. +disabled_public_heatmap = This user has disabled the public visibility of the heatmap. email_visibility.limited = Your email address is visible to all authenticated users email_visibility.private = Your email address is only visible to you and administrators show_on_map = Show this place on a map @@ -679,6 +680,14 @@ saved_successfully = Your settings were saved successfully. privacy = Privacy keep_activity_private = Hide Activity from profile page keep_activity_private_popup = Makes the activity visible only for you and the admins +heatmap_visibility_popup = Specify which activities are visible in heatmap +heatmap_visibility = Visible activities in heatmap +heatmap_visibility.public_popup = Only activies from repositories which can be visited from the viewer are in the heatmap +heatmap_visibility.public = Public +heatmap_visibility.all_popup = Only activies from repositories which can be visited from the viewer are in the heatmap +heatmap_visibility.all = All +heatmap_visibility.none_popup = Don't show the heatmap +heatmap_visibility.none = None lookup_avatar_by_mail = Look Up Avatar by Email Address federated_avatar_lookup = Federated Avatar Lookup diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 24a807d518..b5ecda73f9 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -93,6 +93,7 @@ func ProfilePost(ctx *context.Context) { Website: optional.Some(form.Website), Location: optional.Some(form.Location), Visibility: optional.Some(form.Visibility), + HeatmapVisibility: optional.Some(form.HeatmapVisibility), KeepActivityPrivate: optional.Some(form.KeepActivityPrivate), } if err := user_service.UpdateUser(ctx, ctx.Doer, opts); err != nil { diff --git a/services/forms/user_form.go b/services/forms/user_form.go index cbab274238..bc8eb1e7a6 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -224,6 +224,7 @@ type UpdateProfileForm struct { Location string `binding:"MaxSize(50)"` Description string `binding:"MaxSize(255)"` Visibility structs.VisibleType + HeatmapVisibility structs.HeatmapVisibility KeepActivityPrivate bool } diff --git a/services/user/update.go b/services/user/update.go index cbaf90053a..6328627566 100644 --- a/services/user/update.go +++ b/services/user/update.go @@ -27,6 +27,7 @@ type UpdateOptions struct { MaxRepoCreation optional.Option[int] IsRestricted optional.Option[bool] Visibility optional.Option[structs.VisibleType] + HeatmapVisibility optional.Option[structs.HeatmapVisibility] KeepActivityPrivate optional.Option[bool] Language optional.Option[string] Theme optional.Option[string] @@ -129,6 +130,11 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er cols = append(cols, "visibility") } + if opts.HeatmapVisibility.Has() { + u.HeatmapVisibility = opts.HeatmapVisibility.Value() + + cols = append(cols, "heatmap_visibility") + } if opts.KeepActivityPrivate.Has() { u.KeepActivityPrivate = opts.KeepActivityPrivate.Value() diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 426b5f042a..7e96ab6608 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -15,9 +15,16 @@

{{ctx.Locale.Tr "user.disabled_public_activity"}}

+ {{else}} + {{if .ContextUser.HeatmapVisibility.ShowNone}} +
+

{{ctx.Locale.Tr "user.disabled_public_heatmap"}}

+
+ {{else}} + {{template "user/heatmap" .}} + {{end}} + {{template "user/dashboard/feeds" .}} {{end}} - {{template "user/heatmap" .}} - {{template "user/dashboard/feeds" .}} {{else if eq .TabName "stars"}}
{{template "explore/repo_search" .}} diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index d1c68656b6..cebf4a2390 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -85,6 +85,24 @@
+
+ + +
+