aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYarden Shoham <git@yardenshoham.com>2024-01-02 03:25:30 +0200
committerGitHub <noreply@github.com>2024-01-02 09:25:30 +0800
commitcdc33b29a012e61b42f192d79f9486fa8e21b2ed (patch)
tree12e779fa67cbc257c888814e9c6056a0208db1bc
parentf8f394cb0eebd5254c6df9e12e309dc92acc58e1 (diff)
downloadgitea-cdc33b29a012e61b42f192d79f9486fa8e21b2ed.tar.gz
gitea-cdc33b29a012e61b42f192d79f9486fa8e21b2ed.zip
Add global setting how timestamps should be rendered (#28657)
- Resolves https://github.com/go-gitea/gitea/issues/22493 - Related to https://github.com/go-gitea/gitea/issues/4520 Some admins prefer all timestamps to display the full date instead of relative time. They can do that now by setting ```ini [ui] PREFERRED_TIMESTAMP_TENSE = absolute ``` This setting is set to `mixed` by default, allowing dates to render as "5 hours ago". Here are some screenshots of the UI with this setting set to `absolute`: ![image](https://github.com/go-gitea/gitea/assets/20454870/f496457f-6afa-44be-a1e7-249ee5fe0706) ![image](https://github.com/go-gitea/gitea/assets/20454870/c03b14f5-063d-4e13-9780-76ab002d76a9) ![image](https://github.com/go-gitea/gitea/assets/20454870/f4b34e28-1546-4374-9199-c43348844edd) --------- Signed-off-by: Yarden Shoham <git@yardenshoham.com> Co-authored-by: delvh <dev.lh@web.de>
-rw-r--r--custom/conf/app.example.ini4
-rw-r--r--docs/content/administration/config-cheat-sheet.en-us.md1
-rw-r--r--modules/setting/ui.go87
-rw-r--r--modules/timeutil/datetime.go11
-rw-r--r--modules/timeutil/datetime_test.go10
-rw-r--r--modules/timeutil/since.go4
-rw-r--r--web_src/js/components/DiffCommitSelector.vue1
7 files changed, 69 insertions, 49 deletions
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 08f2e0d63f..d58309f141 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -1244,6 +1244,10 @@ LEVEL = Info
;; Change the sort type of the explore pages.
;; Default is "recentupdate", but you also have "alphabetically", "reverselastlogin", "newest", "oldest".
;EXPLORE_PAGING_DEFAULT_SORT = recentupdate
+;;
+;; The tense all timestamps should be rendered in. Possible values are `absolute` time (i.e. 1970-01-01, 11:59) and `mixed`.
+;; `mixed` means most timestamps are rendered in relative time (i.e. 2 days ago).
+;PREFERRED_TIMESTAMP_TENSE = mixed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md
index beaa8cfb30..e111ff6db6 100644
--- a/docs/content/administration/config-cheat-sheet.en-us.md
+++ b/docs/content/administration/config-cheat-sheet.en-us.md
@@ -231,6 +231,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `ONLY_SHOW_RELEVANT_REPOS`: **false**: Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
- `EXPLORE_PAGING_DEFAULT_SORT`: **recentupdate**: Change the sort type of the explore pages. Valid values are "recentupdate", "alphabetically", "reverselastlogin", "newest" and "oldest"
+- `PREFERRED_TIMESTAMP_TENSE`: **mixed**: The tense all timestamps should be rendered in. Possible values are `absolute` time (i.e. 1970-01-01, 11:59) and `mixed`. `mixed` means most timestamps are rendered in relative time (i.e. 2 days ago).
### UI - Admin (`ui.admin`)
diff --git a/modules/setting/ui.go b/modules/setting/ui.go
index f94e6206cd..2f9eef93c3 100644
--- a/modules/setting/ui.go
+++ b/modules/setting/ui.go
@@ -7,33 +7,35 @@ import (
"time"
"code.gitea.io/gitea/modules/container"
+ "code.gitea.io/gitea/modules/log"
)
// UI settings
var UI = struct {
- ExplorePagingNum int
- SitemapPagingNum int
- IssuePagingNum int
- RepoSearchPagingNum int
- MembersPagingNum int
- FeedMaxCommitNum int
- FeedPagingNum int
- PackagesPagingNum int
- GraphMaxCommitNum int
- CodeCommentLines int
- ReactionMaxUserNum int
- MaxDisplayFileSize int64
- ShowUserEmail bool
- DefaultShowFullName bool
- DefaultTheme string
- Themes []string
- Reactions []string
- ReactionsLookup container.Set[string] `ini:"-"`
- CustomEmojis []string
- CustomEmojisMap map[string]string `ini:"-"`
- SearchRepoDescription bool
- OnlyShowRelevantRepos bool
- ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
+ ExplorePagingNum int
+ SitemapPagingNum int
+ IssuePagingNum int
+ RepoSearchPagingNum int
+ MembersPagingNum int
+ FeedMaxCommitNum int
+ FeedPagingNum int
+ PackagesPagingNum int
+ GraphMaxCommitNum int
+ CodeCommentLines int
+ ReactionMaxUserNum int
+ MaxDisplayFileSize int64
+ ShowUserEmail bool
+ DefaultShowFullName bool
+ DefaultTheme string
+ Themes []string
+ Reactions []string
+ ReactionsLookup container.Set[string] `ini:"-"`
+ CustomEmojis []string
+ CustomEmojisMap map[string]string `ini:"-"`
+ SearchRepoDescription bool
+ OnlyShowRelevantRepos bool
+ ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
+ PreferredTimestampTense string
AmbiguousUnicodeDetection bool
@@ -67,23 +69,24 @@ var UI = struct {
Keywords string
} `ini:"ui.meta"`
}{
- ExplorePagingNum: 20,
- SitemapPagingNum: 20,
- IssuePagingNum: 20,
- RepoSearchPagingNum: 20,
- MembersPagingNum: 20,
- FeedMaxCommitNum: 5,
- FeedPagingNum: 20,
- PackagesPagingNum: 20,
- GraphMaxCommitNum: 100,
- CodeCommentLines: 4,
- ReactionMaxUserNum: 10,
- MaxDisplayFileSize: 8388608,
- DefaultTheme: `gitea-auto`,
- Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`},
- Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
- CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
- CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
+ ExplorePagingNum: 20,
+ SitemapPagingNum: 20,
+ IssuePagingNum: 20,
+ RepoSearchPagingNum: 20,
+ MembersPagingNum: 20,
+ FeedMaxCommitNum: 5,
+ FeedPagingNum: 20,
+ PackagesPagingNum: 20,
+ GraphMaxCommitNum: 100,
+ CodeCommentLines: 4,
+ ReactionMaxUserNum: 10,
+ MaxDisplayFileSize: 8388608,
+ DefaultTheme: `gitea-auto`,
+ Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`},
+ Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
+ CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
+ CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
+ PreferredTimestampTense: "mixed",
AmbiguousUnicodeDetection: true,
@@ -142,6 +145,10 @@ func loadUIFrom(rootCfg ConfigProvider) {
UI.DefaultShowFullName = sec.Key("DEFAULT_SHOW_FULL_NAME").MustBool(false)
UI.SearchRepoDescription = sec.Key("SEARCH_REPO_DESCRIPTION").MustBool(true)
+ if UI.PreferredTimestampTense != "mixed" && UI.PreferredTimestampTense != "absolute" {
+ log.Fatal("ui.PREFERRED_TIMESTAMP_TENSE must be either 'mixed' or 'absolute'")
+ }
+
// OnlyShowRelevantRepos=false is important for many private/enterprise instances,
// because many private repositories do not have "description/topic", users just want to search by their names.
UI.OnlyShowRelevantRepos = sec.Key("ONLY_SHOW_RELEVANT_REPOS").MustBool(false)
diff --git a/modules/timeutil/datetime.go b/modules/timeutil/datetime.go
index 83170b374b..d254a56a74 100644
--- a/modules/timeutil/datetime.go
+++ b/modules/timeutil/datetime.go
@@ -7,11 +7,12 @@ import (
"fmt"
"html"
"html/template"
+ "strings"
"time"
)
// DateTime renders an absolute time HTML element by datetime.
-func DateTime(format string, datetime any) template.HTML {
+func DateTime(format string, datetime any, attrs ...string) template.HTML {
if p, ok := datetime.(*time.Time); ok {
datetime = *p
}
@@ -48,13 +49,15 @@ func DateTime(format string, datetime any) template.HTML {
panic(fmt.Sprintf("Unsupported time type %T", datetime))
}
+ extraAttrs := strings.Join(attrs, " ")
+
switch format {
case "short":
- return template.HTML(fmt.Sprintf(`<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="%s">%s</relative-time>`, datetimeEscaped, textEscaped))
+ return template.HTML(fmt.Sprintf(`<relative-time %s format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="%s">%s</relative-time>`, extraAttrs, datetimeEscaped, textEscaped))
case "long":
- return template.HTML(fmt.Sprintf(`<relative-time format="datetime" year="numeric" month="long" day="numeric" weekday="" datetime="%s">%s</relative-time>`, datetimeEscaped, textEscaped))
+ return template.HTML(fmt.Sprintf(`<relative-time %s format="datetime" year="numeric" month="long" day="numeric" weekday="" datetime="%s">%s</relative-time>`, extraAttrs, datetimeEscaped, textEscaped))
case "full":
- return template.HTML(fmt.Sprintf(`<relative-time format="datetime" weekday="" year="numeric" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" datetime="%s">%s</relative-time>`, datetimeEscaped, textEscaped))
+ return template.HTML(fmt.Sprintf(`<relative-time %s format="datetime" weekday="" year="numeric" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" datetime="%s">%s</relative-time>`, extraAttrs, datetimeEscaped, textEscaped))
}
panic(fmt.Sprintf("Unsupported format %s", format))
}
diff --git a/modules/timeutil/datetime_test.go b/modules/timeutil/datetime_test.go
index f44b7aaae3..387e6274a7 100644
--- a/modules/timeutil/datetime_test.go
+++ b/modules/timeutil/datetime_test.go
@@ -29,17 +29,17 @@ func TestDateTime(t *testing.T) {
assert.EqualValues(t, "-", DateTime("short", TimeStamp(0)))
actual := DateTime("short", "invalid")
- assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="invalid">invalid</relative-time>`, actual)
+ assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="invalid">invalid</relative-time>`, actual)
actual = DateTime("short", refTimeStr)
- assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="2018-01-01T00:00:00Z">2018-01-01T00:00:00Z</relative-time>`, actual)
+ assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="2018-01-01T00:00:00Z">2018-01-01T00:00:00Z</relative-time>`, actual)
actual = DateTime("short", refTime)
- assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="2018-01-01T00:00:00Z">2018-01-01</relative-time>`, actual)
+ assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="2018-01-01T00:00:00Z">2018-01-01</relative-time>`, actual)
actual = DateTime("short", refTimeStamp)
- assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="2017-12-31T19:00:00-05:00">2017-12-31</relative-time>`, actual)
+ assert.EqualValues(t, `<relative-time format="datetime" year="numeric" month="short" day="numeric" weekday="" datetime="2017-12-31T19:00:00-05:00">2017-12-31</relative-time>`, actual)
actual = DateTime("full", refTimeStamp)
- assert.EqualValues(t, `<relative-time format="datetime" weekday="" year="numeric" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
+ assert.EqualValues(t, `<relative-time format="datetime" weekday="" year="numeric" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
}
diff --git a/modules/timeutil/since.go b/modules/timeutil/since.go
index 04fcff54a3..1cb3c4f288 100644
--- a/modules/timeutil/since.go
+++ b/modules/timeutil/since.go
@@ -9,6 +9,7 @@ import (
"strings"
"time"
+ "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
)
@@ -132,6 +133,9 @@ func timeSinceUnix(then, now time.Time, lang translation.Locale) template.HTML {
// TimeSince renders relative time HTML given a time.Time
func TimeSince(then time.Time, lang translation.Locale) template.HTML {
+ if setting.UI.PreferredTimestampTense == "absolute" {
+ return DateTime("full", then, `class="time-since"`)
+ }
return timeSinceUnix(then, time.Now(), lang)
}
diff --git a/web_src/js/components/DiffCommitSelector.vue b/web_src/js/components/DiffCommitSelector.vue
index 439840c306..54877a18c0 100644
--- a/web_src/js/components/DiffCommitSelector.vue
+++ b/web_src/js/components/DiffCommitSelector.vue
@@ -247,6 +247,7 @@ export default {
<div class="gt-ellipsis text light-2">
{{ commit.committer_or_author_name }}
<span class="text right">
+ <!-- TODO: make this respect the PreferredTimestampTense setting -->
<relative-time class="time-since" prefix="" :datetime="commit.time" data-tooltip-content data-tooltip-interactive="true">{{ commit.time }}</relative-time>
</span>
</div>