mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	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`:    --------- Signed-off-by: Yarden Shoham <git@yardenshoham.com> Co-authored-by: delvh <dev.lh@web.de>
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
|   | ||||
| @@ -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`) | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/container" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| ) | ||||
|  | ||||
| // UI settings | ||||
| @@ -34,6 +35,7 @@ var UI = struct { | ||||
| 	SearchRepoDescription   bool | ||||
| 	OnlyShowRelevantRepos   bool | ||||
| 	ExploreDefaultSort      string `ini:"EXPLORE_PAGING_DEFAULT_SORT"` | ||||
| 	PreferredTimestampTense string | ||||
|  | ||||
| 	AmbiguousUnicodeDetection bool | ||||
|  | ||||
| @@ -84,6 +86,7 @@ var UI = struct { | ||||
| 	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) | ||||
|   | ||||
| @@ -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)) | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Yarden Shoham
					Yarden Shoham