Merge template functions "dict/Dict/mergeinto" (#23932)
One of the steps in #23328 Before there were 3 different but similar functions: dict/Dict/mergeinto The code was just copied & pasted, no test. This PR defines a new stable `dict` function, it covers all the 3 old functions behaviors, only +160 -171 Future developers do not need to think about or guess the different dict functions, just use one: `dict` Why use `dict` but not `Dict`? Because there are far more `dict` than `Dict` in code already ......
This commit is contained in:
parent
5b89670a31
commit
36c0840cf1
|
@ -8,7 +8,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
|
@ -219,20 +218,6 @@ func NewFuncMap() []template.FuncMap {
|
|||
"DisableImportLocal": func() bool {
|
||||
return !setting.ImportLocalPaths
|
||||
},
|
||||
"Dict": func(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, errors.New("invalid dict call")
|
||||
}
|
||||
dict := make(map[string]interface{}, len(values)/2)
|
||||
for i := 0; i < len(values); i += 2 {
|
||||
key, ok := values[i].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("dict keys must be strings")
|
||||
}
|
||||
dict[key] = values[i+1]
|
||||
}
|
||||
return dict, nil
|
||||
},
|
||||
"Printf": fmt.Sprintf,
|
||||
"Escape": Escape,
|
||||
"Sec2Time": util.SecToTime,
|
||||
|
@ -242,35 +227,7 @@ func NewFuncMap() []template.FuncMap {
|
|||
"DefaultTheme": func() string {
|
||||
return setting.UI.DefaultTheme
|
||||
},
|
||||
// pass key-value pairs to a partial template which receives them as a dict
|
||||
"dict": func(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values) == 0 {
|
||||
return nil, errors.New("invalid dict call")
|
||||
}
|
||||
|
||||
dict := make(map[string]interface{})
|
||||
return util.MergeInto(dict, values...)
|
||||
},
|
||||
/* like dict but merge key-value pairs into the first dict and return it */
|
||||
"mergeinto": func(root map[string]interface{}, values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values) == 0 {
|
||||
return nil, errors.New("invalid mergeinto call")
|
||||
}
|
||||
|
||||
dict := make(map[string]interface{})
|
||||
for key, value := range root {
|
||||
dict[key] = value
|
||||
}
|
||||
|
||||
return util.MergeInto(dict, values...)
|
||||
},
|
||||
"percentage": func(n int, values ...int) float32 {
|
||||
sum := 0
|
||||
for i := 0; i < len(values); i++ {
|
||||
sum += values[i]
|
||||
}
|
||||
return float32(n) * 100 / float32(sum)
|
||||
},
|
||||
"dict": dict,
|
||||
"CommentMustAsDiff": gitdiff.CommentMustAsDiff,
|
||||
"MirrorRemoteAddress": mirrorRemoteAddress,
|
||||
"NotificationSettings": func() map[string]interface{} {
|
||||
|
@ -413,52 +370,13 @@ func NewTextFuncMap() []texttmpl.FuncMap {
|
|||
},
|
||||
"EllipsisString": base.EllipsisString,
|
||||
"URLJoin": util.URLJoin,
|
||||
"Dict": func(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, errors.New("invalid dict call")
|
||||
}
|
||||
dict := make(map[string]interface{}, len(values)/2)
|
||||
for i := 0; i < len(values); i += 2 {
|
||||
key, ok := values[i].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("dict keys must be strings")
|
||||
}
|
||||
dict[key] = values[i+1]
|
||||
}
|
||||
return dict, nil
|
||||
},
|
||||
"Printf": fmt.Sprintf,
|
||||
"Escape": Escape,
|
||||
"Sec2Time": util.SecToTime,
|
||||
"ParseDeadline": func(deadline string) []string {
|
||||
return strings.Split(deadline, "|")
|
||||
},
|
||||
"dict": func(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values) == 0 {
|
||||
return nil, errors.New("invalid dict call")
|
||||
}
|
||||
|
||||
dict := make(map[string]interface{})
|
||||
|
||||
for i := 0; i < len(values); i++ {
|
||||
switch key := values[i].(type) {
|
||||
case string:
|
||||
i++
|
||||
if i == len(values) {
|
||||
return nil, errors.New("specify the key for non array values")
|
||||
}
|
||||
dict[key] = values[i]
|
||||
case map[string]interface{}:
|
||||
m := values[i].(map[string]interface{})
|
||||
for i, v := range m {
|
||||
dict[i] = v
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("dict values must be maps")
|
||||
}
|
||||
}
|
||||
return dict, nil
|
||||
},
|
||||
"dict": dict,
|
||||
"QueryEscape": url.QueryEscape,
|
||||
"Eval": Eval,
|
||||
}}
|
||||
|
|
47
modules/templates/util.go
Normal file
47
modules/templates/util.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func dictMerge(base map[string]any, arg any) bool {
|
||||
if arg == nil {
|
||||
return true
|
||||
}
|
||||
rv := reflect.ValueOf(arg)
|
||||
if rv.Kind() == reflect.Map {
|
||||
for _, k := range rv.MapKeys() {
|
||||
base[k.String()] = rv.MapIndex(k).Interface()
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// dict is a helper function for creating a map[string]any from a list of key-value pairs.
|
||||
// If the key is dot ".", the value is merged into the base map, just like Golang template's dot syntax: dot means current
|
||||
// The dot syntax is highly discouraged because it might cause unclear key conflicts. It's always good to use explicit keys.
|
||||
func dict(args ...any) (map[string]any, error) {
|
||||
if len(args)%2 != 0 {
|
||||
return nil, fmt.Errorf("invalid dict constructor syntax: must have key-value pairs")
|
||||
}
|
||||
m := make(map[string]any, len(args)/2)
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
key, ok := args[i].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid dict constructor syntax: unable to merge args[%d]", i)
|
||||
}
|
||||
if key == "." {
|
||||
if ok = dictMerge(m, args[i+1]); !ok {
|
||||
return nil, fmt.Errorf("invalid dict constructor syntax: dot arg[%d] must be followed by a dict", i)
|
||||
}
|
||||
} else {
|
||||
m[key] = args[i+1]
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
43
modules/templates/util_test.go
Normal file
43
modules/templates/util_test.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDict(t *testing.T) {
|
||||
type M map[string]any
|
||||
cases := []struct {
|
||||
args []any
|
||||
want map[string]any
|
||||
}{
|
||||
{[]any{"a", 1, "b", 2}, M{"a": 1, "b": 2}},
|
||||
{[]any{".", M{"base": 1}, "b", 2}, M{"base": 1, "b": 2}},
|
||||
{[]any{"a", 1, ".", M{"extra": 2}}, M{"a": 1, "extra": 2}},
|
||||
{[]any{"a", 1, ".", map[string]int{"int": 2}}, M{"a": 1, "int": 2}},
|
||||
{[]any{".", nil, "b", 2}, M{"b": 2}},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
got, err := dict(c.args...)
|
||||
if assert.NoError(t, err) {
|
||||
assert.EqualValues(t, c.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
bads := []struct {
|
||||
args []any
|
||||
}{
|
||||
{[]any{"a", 1, "b"}},
|
||||
{[]any{1}},
|
||||
{[]any{struct{}{}}},
|
||||
}
|
||||
for _, c := range bads {
|
||||
_, err := dict(c.args...)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ package util
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
@ -117,29 +116,6 @@ func NormalizeEOL(input []byte) []byte {
|
|||
return tmp[:pos]
|
||||
}
|
||||
|
||||
// MergeInto merges pairs of values into a "dict"
|
||||
func MergeInto(dict map[string]interface{}, values ...interface{}) (map[string]interface{}, error) {
|
||||
for i := 0; i < len(values); i++ {
|
||||
switch key := values[i].(type) {
|
||||
case string:
|
||||
i++
|
||||
if i == len(values) {
|
||||
return nil, errors.New("specify the key for non array values")
|
||||
}
|
||||
dict[key] = values[i]
|
||||
case map[string]interface{}:
|
||||
m := values[i].(map[string]interface{})
|
||||
for i, v := range m {
|
||||
dict[i] = v
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("dict values must be maps")
|
||||
}
|
||||
}
|
||||
|
||||
return dict, nil
|
||||
}
|
||||
|
||||
// CryptoRandomInt returns a crypto random integer between 0 and limit, inclusive
|
||||
func CryptoRandomInt(limit int64) (int64, error) {
|
||||
rInt, err := rand.Int(rand.Reader, big.NewInt(limit))
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
<div class="ui attached segment members">
|
||||
{{range .Members}}
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui bottom attached header">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{if .OriginalAuthor}}
|
||||
<span class="avatar"><img src="{{AppSubUrl}}/assets/img/avatar_default.png"></span>
|
||||
{{else}}
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.root.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.root.Context "user" .Poster}}
|
||||
{{end}}
|
||||
<div class="content comment-container">
|
||||
<div class="ui top attached header comment-header gt-df gt-ac gt-sb">
|
||||
|
@ -42,8 +42,8 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{template "repo/issue/view_content/add_reaction" Dict "ctxData" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" Dict "ctxData" $.root "item" . "delete" true "issue" false "diff" true "IsCommentPoster" (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}
|
||||
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" dict "ctxData" $.root "item" . "delete" true "issue" false "diff" true "IsCommentPoster" (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached segment comment-body">
|
||||
|
@ -60,7 +60,7 @@
|
|||
{{$reactions := .Reactions.GroupByType}}
|
||||
{{if $reactions}}
|
||||
<div class="ui attached segment reactions">
|
||||
{{template "repo/issue/view_content/reactions" Dict "ctxData" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions}}
|
||||
{{template "repo/issue/view_content/reactions" dict "ctxData" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
|
|
@ -111,22 +111,22 @@
|
|||
<td class="add-comment-left" colspan="4">
|
||||
{{if gt (len $line.Comments) 0}}
|
||||
{{if eq $line.GetCommentSide "previous"}}
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if gt (len $match.Comments) 0}}
|
||||
{{if eq $match.GetCommentSide "previous"}}
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $match.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $match.Comments}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="add-comment-right" colspan="4">
|
||||
{{if eq $line.GetCommentSide "proposed"}}
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
|
||||
{{end}}
|
||||
{{if gt (len $match.Comments) 0}}
|
||||
{{if eq $match.GetCommentSide "proposed"}}
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $match.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $match.Comments}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</td>
|
||||
|
@ -137,13 +137,13 @@
|
|||
<td class="add-comment-left" colspan="4">
|
||||
{{if gt (len $line.Comments) 0}}
|
||||
{{if eq $line.GetCommentSide "previous"}}
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="add-comment-right" colspan="4">
|
||||
{{if eq $line.GetCommentSide "proposed"}}
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
{{if gt (len $line.Comments) 0}}
|
||||
<tr class="add-comment" data-line-type="{{DiffLineTypeToStr .GetType}}">
|
||||
<td class="add-comment-left add-comment-right" colspan="5">
|
||||
{{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
|
||||
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
|
|
@ -307,7 +307,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "shared/issuelist" mergeinto . "listType" "repo"}}
|
||||
{{template "shared/issuelist" dict "." . "listType" "repo"}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "shared/issuelist" mergeinto . "listType" "milestone"}}
|
||||
{{template "shared/issuelist" dict "." . "listType" "milestone"}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="twelve wide column">
|
||||
<div class="ui comments">
|
||||
<div class="comment">
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .SignedUser}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .SignedUser}}
|
||||
<div class="ui segment content">
|
||||
<div class="field">
|
||||
<input name="title" id="issue_title" placeholder="{{.locale.Tr "repo.milestones.title"}}" value="{{if .TitleQuery}}{{.TitleQuery}}{{else if .IssueTemplateTitle}}{{.IssueTemplateTitle}}{{else}}{{.title}}{{end}}" tabindex="3" autofocus required maxlength="255" autocomplete="off">
|
||||
|
@ -20,15 +20,15 @@
|
|||
<input type="hidden" name="template-file" value="{{.TemplateFile}}">
|
||||
{{range .Fields}}
|
||||
{{if eq .Type "input"}}
|
||||
{{template "repo/issue/fields/input" Dict "Context" $.Context "item" .}}
|
||||
{{template "repo/issue/fields/input" dict "Context" $.Context "item" .}}
|
||||
{{else if eq .Type "markdown"}}
|
||||
{{template "repo/issue/fields/markdown" Dict "Context" $.Context "item" .}}
|
||||
{{template "repo/issue/fields/markdown" dict "Context" $.Context "item" .}}
|
||||
{{else if eq .Type "textarea"}}
|
||||
{{template "repo/issue/fields/textarea" Dict "Context" $.Context "item" .}}
|
||||
{{template "repo/issue/fields/textarea" dict "Context" $.Context "item" .}}
|
||||
{{else if eq .Type "dropdown"}}
|
||||
{{template "repo/issue/fields/dropdown" Dict "Context" $.Context "item" .}}
|
||||
{{template "repo/issue/fields/dropdown" dict "Context" $.Context "item" .}}
|
||||
{{else if eq .Type "checkboxes"}}
|
||||
{{template "repo/issue/fields/checkboxes" Dict "Context" $.Context "item" .}}
|
||||
{{template "repo/issue/fields/checkboxes" dict "Context" $.Context "item" .}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .IsAttachmentEnabled}}
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
{{end}}
|
||||
{{end}}
|
||||
{{if not $.Repository.IsArchived}}
|
||||
{{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
|
||||
{{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}}
|
||||
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
|
||||
{{template "repo/issue/view_content/context_menu" dict "ctxData" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -80,13 +80,13 @@
|
|||
<div id="issue-{{.Issue.ID}}-raw" class="raw-content gt-hidden">{{.Issue.Content}}</div>
|
||||
<div class="edit-content-zone gt-hidden" data-write="issue-{{.Issue.ID}}-write" data-preview="issue-{{.Issue.ID}}-preview" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/content" data-context="{{.RepoLink}}" data-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/attachments" data-view-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/view-attachments"></div>
|
||||
{{if .Issue.Attachments}}
|
||||
{{template "repo/issue/view_content/attachments" Dict "ctxData" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}}
|
||||
{{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{$reactions := .Issue.Reactions.GroupByType}}
|
||||
{{if $reactions}}
|
||||
<div class="ui attached segment reactions" role="note">
|
||||
{{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions}}
|
||||
{{template "repo/issue/view_content/reactions" dict "ctxData" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{if not $.Repository.IsArchived}}
|
||||
{{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
|
||||
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" dict "ctxData" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -80,13 +80,13 @@
|
|||
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
|
||||
<div class="edit-content-zone gt-hidden" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
|
||||
{{if .Attachments}}
|
||||
{{template "repo/issue/view_content/attachments" Dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
|
||||
{{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{$reactions := .Reactions.GroupByType}}
|
||||
{{if $reactions}}
|
||||
<div class="ui attached segment reactions" role="note">
|
||||
{{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
|
||||
{{template "repo/issue/view_content/reactions" dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@ -94,7 +94,7 @@
|
|||
{{else if eq .Type 1}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge gt-bg-green gt-text-white">{{svg "octicon-dot-fill"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if .Issue.IsPull}}
|
||||
|
@ -107,7 +107,7 @@
|
|||
{{else if eq .Type 2}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge gt-bg-red gt-text-white">{{svg "octicon-circle-slash"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if .Issue.IsPull}}
|
||||
|
@ -120,7 +120,7 @@
|
|||
{{else if eq .Type 28}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge gt-bg-purple gt-text-white">{{svg "octicon-git-merge"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$link := printf "%s/commit/%s" $.Repository.Link ($.Issue.PullRequest.MergedCommitID|PathEscape)}}
|
||||
|
@ -147,7 +147,7 @@
|
|||
{{$createdStr:= TimeSinceUnix .CreatedUnix $.locale}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-bookmark"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
{{if eq .RefAction 3}}<del>{{end}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
|
@ -162,7 +162,7 @@
|
|||
{{else if eq .Type 4}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-bookmark"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.commit_ref_at" .EventTag $createdStr | Safe}}
|
||||
|
@ -176,7 +176,7 @@
|
|||
{{if or .AddedLabels .RemovedLabels}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-tag"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if and .AddedLabels (not .RemovedLabels)}}
|
||||
|
@ -192,7 +192,7 @@
|
|||
{{else if eq .Type 8}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-milestone"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if gt .OldMilestoneID 0}}{{if gt .MilestoneID 0}}{{$.locale.Tr "repo.issues.change_milestone_at" (.OldMilestone.Name|Escape) (.Milestone.Name|Escape) $createdStr | Safe}}{{else}}{{$.locale.Tr "repo.issues.remove_milestone_at" (.OldMilestone.Name|Escape) $createdStr | Safe}}{{end}}{{else if gt .MilestoneID 0}}{{$.locale.Tr "repo.issues.add_milestone_at" (.Milestone.Name|Escape) $createdStr | Safe}}{{end}}
|
||||
|
@ -203,7 +203,7 @@
|
|||
<span class="badge">{{svg "octicon-person"}}</span>
|
||||
{{if gt .AssigneeID 0}}
|
||||
{{if .RemovedAssignee}}
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Assignee}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Assignee}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Assignee}}
|
||||
{{if eq .Poster.ID .Assignee.ID}}
|
||||
|
@ -213,7 +213,7 @@
|
|||
{{end}}
|
||||
</span>
|
||||
{{else}}
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Assignee}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Assignee}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Assignee}}
|
||||
{{if eq .Poster.ID .AssigneeID}}
|
||||
|
@ -228,7 +228,7 @@
|
|||
{{else if eq .Type 10}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-pencil"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.change_title_at" (.OldTitle|RenderEmoji $.Context) (.NewTitle|RenderEmoji $.Context) $createdStr | Safe}}
|
||||
|
@ -237,7 +237,7 @@
|
|||
{{else if eq .Type 11}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-git-branch"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.delete_branch_at" (.OldRef|Escape) $createdStr | Safe}}
|
||||
|
@ -246,7 +246,7 @@
|
|||
{{else if eq .Type 12}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.start_tracking_history" $createdStr | Safe}}
|
||||
|
@ -255,12 +255,12 @@
|
|||
{{else if eq .Type 13}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.stop_tracking_history" $createdStr | Safe}}
|
||||
</span>
|
||||
{{template "repo/issue/view_content/comments_delete_time" Dict "ctxData" $ "comment" .}}
|
||||
{{template "repo/issue/view_content/comments_delete_time" dict "ctxData" $ "comment" .}}
|
||||
<div class="detail">
|
||||
{{svg "octicon-clock"}}
|
||||
<span class="text grey muted-links">{{.Content}}</span>
|
||||
|
@ -269,12 +269,12 @@
|
|||
{{else if eq .Type 14}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.add_time_history" $createdStr | Safe}}
|
||||
</span>
|
||||
{{template "repo/issue/view_content/comments_delete_time" Dict "ctxData" $ "comment" .}}
|
||||
{{template "repo/issue/view_content/comments_delete_time" dict "ctxData" $ "comment" .}}
|
||||
<div class="detail">
|
||||
{{svg "octicon-clock"}}
|
||||
<span class="text grey muted-links">{{.Content}}</span>
|
||||
|
@ -283,7 +283,7 @@
|
|||
{{else if eq .Type 15}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.cancel_tracking_history" $createdStr | Safe}}
|
||||
|
@ -292,7 +292,7 @@
|
|||
{{else if eq .Type 16}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.due_date_added" .Content $createdStr | Safe}}
|
||||
|
@ -301,7 +301,7 @@
|
|||
{{else if eq .Type 17}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$parsedDeadline := .Content | ParseDeadline}}
|
||||
|
@ -311,7 +311,7 @@
|
|||
{{else if eq .Type 18}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.due_date_remove" .Content $createdStr | Safe}}
|
||||
|
@ -320,7 +320,7 @@
|
|||
{{else if eq .Type 19}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-package-dependents"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.dependency.added_dependency" $createdStr | Safe}}
|
||||
|
@ -343,7 +343,7 @@
|
|||
{{else if eq .Type 20}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-package-dependents"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.dependency.removed_dependency" $createdStr | Safe}}
|
||||
|
@ -436,8 +436,8 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{if not $.Repository.IsArchived}}
|
||||
{{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" . "delete" false "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
|
||||
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" dict "ctxData" $ "item" . "delete" false "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -452,13 +452,13 @@
|
|||
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
|
||||
<div class="edit-content-zone gt-hidden" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
|
||||
{{if .Attachments}}
|
||||
{{template "repo/issue/view_content/attachments" Dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
|
||||
{{template "repo/issue/view_content/attachments" dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{$reactions := .Reactions.GroupByType}}
|
||||
{{if $reactions}}
|
||||
<div class="ui attached segment reactions">
|
||||
{{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
|
||||
{{template "repo/issue/view_content/reactions" dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@ -563,8 +563,8 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{if not $.Repository.IsArchived}}
|
||||
{{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
|
||||
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
|
||||
{{template "repo/issue/view_content/context_menu" dict "ctxData" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -582,7 +582,7 @@
|
|||
{{$reactions := .Reactions.GroupByType}}
|
||||
{{if $reactions}}
|
||||
<div class="ui attached segment reactions">
|
||||
{{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
|
||||
{{template "repo/issue/view_content/reactions" dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@ -626,7 +626,7 @@
|
|||
{{else if eq .Type 23}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-lock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
{{if .Content}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
|
@ -642,7 +642,7 @@
|
|||
{{else if eq .Type 24}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-key"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{$.locale.Tr "repo.issues.unlock_comment" $createdStr | Safe}}
|
||||
|
@ -651,7 +651,7 @@
|
|||
{{else if eq .Type 25}}
|
||||
<div class="timeline-item event">
|
||||
<span class="badge">{{svg "octicon-git-branch"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
<a{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>{{.Poster.Name}}</a>
|
||||
{{$.locale.Tr "repo.pulls.change_target_branch_at" (.OldRef|Escape) (.NewRef|Escape) $createdStr | Safe}}
|
||||
|
@ -660,7 +660,7 @@
|
|||
{{else if eq .Type 26}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-clock"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
|
||||
|
@ -674,7 +674,7 @@
|
|||
{{else if eq .Type 27}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-eye"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if (gt .AssigneeID 0)}}
|
||||
|
@ -724,7 +724,7 @@
|
|||
{{if not $.UnitProjectsGlobalDisabled}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-project"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if gt .OldProjectID 0}}
|
||||
|
@ -781,7 +781,7 @@
|
|||
{{else if eq .Type 33}}
|
||||
<div class="timeline-item event" id="{{.HashTag}}">
|
||||
<span class="badge">{{svg "octicon-git-branch"}}</span>
|
||||
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
|
||||
{{template "shared/user/avatarlink" dict "Context" $.Context "user" .Poster}}
|
||||
<span class="text grey muted-links">
|
||||
{{template "shared/user/authorlink" .Poster}}
|
||||
{{if and .OldRef .NewRef}}
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
</a>
|
||||
{{end}}
|
||||
{{if AllowedReactions}}
|
||||
{{template "repo/issue/view_content/add_reaction" Dict "ctxData" $.ctxData "ActionURL" .ActionURL}}
|
||||
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $.ctxData "ActionURL" .ActionURL}}
|
||||
{{end}}
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "shared/issuelist" mergeinto . "listType" "dashboard"}}
|
||||
{{template "shared/issuelist" dict "." . "listType" "dashboard"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
<div class="ui divider"></div>
|
||||
{{.locale.Tr "notification.no_subscriptions"}}
|
||||
{{else}}
|
||||
{{template "shared/issuelist" mergeinto . "listType" "dashboard"}}
|
||||
{{template "shared/issuelist" dict "." . "listType" "dashboard"}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{template "explore/repo_search" .}}
|
||||
|
|
Loading…
Reference in a new issue