Make template DateTime show proper tooltip (#28677) (#28683)

Backport #28677

(cherry picked from commit 83457805bba667532fa45e9d610f76be056a3f6e)
This commit is contained in:
wxiaoguang 2024-01-03 18:41:03 +08:00 committed by Earl Warren
parent f5764bbf26
commit d537b63521
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
3 changed files with 24 additions and 16 deletions

View file

@ -7,11 +7,12 @@ import (
"fmt" "fmt"
"html" "html"
"html/template" "html/template"
"strings"
"time" "time"
) )
// DateTime renders an absolute time HTML element by datetime. // DateTime renders an absolute time HTML element by datetime.
func DateTime(format string, datetime any) template.HTML { func DateTime(format string, datetime any, extraAttrs ...string) template.HTML {
if p, ok := datetime.(*time.Time); ok { if p, ok := datetime.(*time.Time); ok {
datetime = *p datetime = *p
} }
@ -48,13 +49,20 @@ func DateTime(format string, datetime any) template.HTML {
panic(fmt.Sprintf("Unsupported time type %T", datetime)) panic(fmt.Sprintf("Unsupported time type %T", datetime))
} }
attrs := make([]string, 0, 10+len(extraAttrs))
attrs = append(attrs, extraAttrs...)
attrs = append(attrs, `data-tooltip-content`, `data-tooltip-interactive="true"`)
attrs = append(attrs, `format="datetime"`, `weekday=""`, `year="numeric"`)
switch format { switch format {
case "short": 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)) attrs = append(attrs, `month="short"`, `day="numeric"`)
case "long": 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)) attrs = append(attrs, `month="long"`, `day="numeric"`)
case "full": 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)) attrs = append(attrs, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`)
default:
panic(fmt.Sprintf("Unsupported format %s", format))
} }
panic(fmt.Sprintf("Unsupported format %s", format)) return template.HTML(fmt.Sprintf(`<relative-time %s datetime="%s">%s</relative-time>`, strings.Join(attrs, " "), datetimeEscaped, textEscaped))
} }

View file

@ -8,16 +8,14 @@ import (
"time" "time"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestDateTime(t *testing.T) { func TestDateTime(t *testing.T) {
oldTz := setting.DefaultUILocation testTz, _ := time.LoadLocation("America/New_York")
setting.DefaultUILocation, _ = time.LoadLocation("America/New_York") defer test.MockVariableValue(&setting.DefaultUILocation, testTz)()
defer func() {
setting.DefaultUILocation = oldTz
}()
refTimeStr := "2018-01-01T00:00:00Z" refTimeStr := "2018-01-01T00:00:00Z"
refTime, _ := time.Parse(time.RFC3339, refTimeStr) refTime, _ := time.Parse(time.RFC3339, refTimeStr)
@ -29,17 +27,17 @@ func TestDateTime(t *testing.T) {
assert.EqualValues(t, "-", DateTime("short", TimeStamp(0))) assert.EqualValues(t, "-", DateTime("short", TimeStamp(0)))
actual := DateTime("short", "invalid") 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 data-tooltip-content data-tooltip-interactive="true" format="datetime" weekday="" year="numeric" month="short" day="numeric" datetime="invalid">invalid</relative-time>`, actual)
actual = DateTime("short", refTimeStr) 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 data-tooltip-content data-tooltip-interactive="true" format="datetime" weekday="" year="numeric" month="short" day="numeric" datetime="2018-01-01T00:00:00Z">2018-01-01T00:00:00Z</relative-time>`, actual)
actual = DateTime("short", refTime) 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 data-tooltip-content data-tooltip-interactive="true" format="datetime" weekday="" year="numeric" month="short" day="numeric" datetime="2018-01-01T00:00:00Z">2018-01-01</relative-time>`, actual)
actual = DateTime("short", refTimeStamp) 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 data-tooltip-content data-tooltip-interactive="true" format="datetime" weekday="" year="numeric" month="short" day="numeric" datetime="2017-12-31T19:00:00-05:00">2017-12-31</relative-time>`, actual)
actual = DateTime("full", refTimeStamp) 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 data-tooltip-content data-tooltip-interactive="true" 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)
} }

View file

@ -10,7 +10,9 @@
</div> </div>
<div class="flex-item-main"> <div class="flex-item-main">
<div class="flex-item-title">{{.Name}}</div> <div class="flex-item-title">{{.Name}}</div>
<span class="flex-item-body time">{{TimeSinceUnix .CreatedUnix ctx.Locale}}</span> <div class="flex-item-body">
<i>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix) | Safe}}</i>
</div>
</div> </div>
<div class="flex-item-trailing"> <div class="flex-item-trailing">
<button class="ui red tiny button delete-button" data-modal-id="delete-registration" data-url="{{$.Link}}/webauthn/delete" data-id="{{.ID}}"> <button class="ui red tiny button delete-button" data-modal-id="delete-registration" data-url="{{$.Link}}/webauthn/delete" data-id="{{.ID}}">