Browse Source

[Feature] Custom Reactions (#8886)

* add [ui] Reactions

* move contend check from form to go functions

* use else if

* check if reaction is allowed only on react
(so previous custom reaction can be still removed)

* use $.AllowedReactions in templates

* use ctx.Flash.Error

* use it there too

* add redirection

* back to server error
because a wrong reaction is a template issue ...

* add emoji list link

* add docs entry

* small wording nit
suggestions from @jolheiser - thx

* same reactions as github

* fix PR reactions

* handle error so template JS could check

* Add Integrations Test

* add REACTIONS setting to cheat-sheet doc page
tags/v1.11.0-rc1
6543 4 years ago
parent
commit
668eaf95d5

+ 3
- 0
custom/conf/app.ini.sample View File

DEFAULT_THEME = gitea DEFAULT_THEME = gitea
; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`. ; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`.
THEMES = gitea,arc-green THEMES = gitea,arc-green
; All available reactions. Allow users react with different emoji's
: For the whole list look at https://gitea.com/gitea/gitea.com/issues/8
REACTIONS = +1, -1, laugh, hooray, confused, heart, rocket, eyes
; Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used. ; Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
DEFAULT_SHOW_FULL_NAME = false DEFAULT_SHOW_FULL_NAME = false
; Whether to search within description at repository search on explore page. ; Whether to search within description at repository search on explore page.

+ 1
- 0
docs/content/doc/advanced/config-cheat-sheet.en-us.md View File

- `DEFAULT_THEME`: **gitea**: \[gitea, arc-green\]: Set the default theme for the Gitea install. - `DEFAULT_THEME`: **gitea**: \[gitea, arc-green\]: Set the default theme for the Gitea install.
- `THEMES`: **gitea,arc-green**: All available themes. Allow users select personalized themes - `THEMES`: **gitea,arc-green**: All available themes. Allow users select personalized themes
regardless of the value of `DEFAULT_THEME`. regardless of the value of `DEFAULT_THEME`.
- `REACTIONS`: All available reactions. Allow users react with different emoji's.
- `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used. - `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
- `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page. - `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page.
- `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets. - `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets.

+ 9
- 0
docs/content/doc/advanced/customizing-gitea.en-us.md View File



To add a custom Readme, add a markdown formatted file (without an `.md` extension) to `custom/options/readme` To add a custom Readme, add a markdown formatted file (without an `.md` extension) to `custom/options/readme`


### Reactions

To change reaction emoji's you can set allowed reactions at app.ini
```
[ui]
REACTIONS = +1, -1, laugh, confused, heart, hooray, eyes
```
A full list of supported emoji's is at [emoji list](https://gitea.com/gitea/gitea.com/issues/8)

## Customizing the look of Gitea ## Customizing the look of Gitea


As of version 1.6.0 Gitea has built-in themes. The two built-in themes are, the default theme `gitea`, and a dark theme `arc-green`. To change the look of your Gitea install change the value of `DEFAULT_THEME` in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini` to another one of the available options. As of version 1.6.0 Gitea has built-in themes. The two built-in themes are, the default theme `gitea`, and a dark theme `arc-green`. To change the look of your Gitea install change the value of `DEFAULT_THEME` in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini` to another one of the available options.

+ 26
- 0
integrations/issue_test.go View File

assert.Equal(t, "Description", val) assert.Equal(t, "Description", val)
} }


func TestIssueReaction(t *testing.T) {
defer prepareTestEnv(t)()
session := loginUser(t, "user2")
issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")

req := NewRequest(t, "GET", issueURL)
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)

req = NewRequestWithValues(t, "POST", path.Join(issueURL, "/reactions/react"), map[string]string{
"_csrf": htmlDoc.GetCSRF(),
"content": "8ball",
})
session.MakeRequest(t, req, http.StatusInternalServerError)
req = NewRequestWithValues(t, "POST", path.Join(issueURL, "/reactions/react"), map[string]string{
"_csrf": htmlDoc.GetCSRF(),
"content": "eyes",
})
session.MakeRequest(t, req, http.StatusOK)
req = NewRequestWithValues(t, "POST", path.Join(issueURL, "/reactions/unreact"), map[string]string{
"_csrf": htmlDoc.GetCSRF(),
"content": "eyes",
})
session.MakeRequest(t, req, http.StatusOK)
}

func TestIssueCrossReference(t *testing.T) { func TestIssueCrossReference(t *testing.T) {
defer prepareTestEnv(t)() defer prepareTestEnv(t)()



+ 1
- 1
modules/auth/repo_form.go View File



// ReactionForm form for adding and removing reaction // ReactionForm form for adding and removing reaction
type ReactionForm struct { type ReactionForm struct {
Content string `binding:"Required;In(+1,-1,laugh,confused,heart,hooray)"`
Content string `binding:"Required"`
} }


// Validate validates the fields // Validate validates the fields

+ 2
- 0
modules/setting/setting.go View File

DefaultShowFullName bool DefaultShowFullName bool
DefaultTheme string DefaultTheme string
Themes []string Themes []string
Reactions []string
SearchRepoDescription bool SearchRepoDescription bool
UseServiceWorker bool UseServiceWorker bool


MaxDisplayFileSize: 8388608, MaxDisplayFileSize: 8388608,
DefaultTheme: `gitea`, DefaultTheme: `gitea`,
Themes: []string{`gitea`, `arc-green`}, Themes: []string{`gitea`, `arc-green`},
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
Admin: struct { Admin: struct {
UserPagingNum int UserPagingNum int
RepoPagingNum int RepoPagingNum int

+ 13
- 0
routers/repo/issue.go View File

} }
} }
ctx.Data["IssueWatch"] = iw ctx.Data["IssueWatch"] = iw
ctx.Data["AllowedReactions"] = setting.UI.Reactions


issue.RenderedContent = string(markdown.Render([]byte(issue.Content), ctx.Repo.RepoLink, issue.RenderedContent = string(markdown.Render([]byte(issue.Content), ctx.Repo.RepoLink,
ctx.Repo.Repository.ComposeMetas())) ctx.Repo.Repository.ComposeMetas()))


switch ctx.Params(":action") { switch ctx.Params(":action") {
case "react": case "react":
if !util.IsStringInSlice(form.Content, setting.UI.Reactions) {
err := fmt.Errorf("ChangeIssueReaction: '%s' is not an allowed reaction", form.Content)
ctx.ServerError(err.Error(), err)
return
}

reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Content) reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Content)
if err != nil { if err != nil {
log.Info("CreateIssueReaction: %s", err) log.Info("CreateIssueReaction: %s", err)


switch ctx.Params(":action") { switch ctx.Params(":action") {
case "react": case "react":
if !util.IsStringInSlice(form.Content, setting.UI.Reactions) {
err := fmt.Errorf("ChangeIssueReaction: '%s' is not an allowed reaction", form.Content)
ctx.ServerError(err.Error(), err)
return
}

reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Content) reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Content)
if err != nil { if err != nil {
log.Info("CreateCommentReaction: %s", err) log.Info("CreateCommentReaction: %s", err)

+ 1
- 0
routers/repo/pull.go View File



ctx.Data["NumCommits"] = compareInfo.Commits.Len() ctx.Data["NumCommits"] = compareInfo.Commits.Len()
ctx.Data["NumFiles"] = compareInfo.NumFiles ctx.Data["NumFiles"] = compareInfo.NumFiles
ctx.Data["AllowedReactions"] = setting.UI.Reactions
return compareInfo return compareInfo
} }



+ 1
- 1
templates/repo/diff/comments.tmpl View File

{{$reactions := .Reactions.GroupByType}} {{$reactions := .Reactions.GroupByType}}
{{if $reactions}} {{if $reactions}}
<div class="ui attached segment reactions"> <div class="ui attached segment reactions">
{{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions }}
{{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions "AllowedReactions" $.AllowedReactions }}
</div> </div>
{{end}} {{end}}
</div> </div>

+ 2
- 2
templates/repo/issue/view_content.tmpl View File

{{end}} {{end}}
{{if not $.Repository.IsArchived}} {{if not $.Repository.IsArchived}}
<div class="ui right actions"> <div class="ui right actions">
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) }}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "AllowedReactions" $.AllowedReactions}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "diff" false }} {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "diff" false }}
</div> </div>
{{end}} {{end}}
{{$reactions := .Issue.Reactions.GroupByType}} {{$reactions := .Issue.Reactions.GroupByType}}
{{if $reactions}} {{if $reactions}}
<div class="ui attached segment reactions"> <div class="ui attached segment reactions">
{{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions }}
{{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions "AllowedReactions" $.AllowedReactions}}
</div> </div>
{{end}} {{end}}
{{if .Issue.Attachments}} {{if .Issue.Attachments}}

+ 9
- 6
templates/repo/issue/view_content/add_reaction.tmpl View File

<div class="menu has-emoji"> <div class="menu has-emoji">
<div class="header">{{ .ctx.i18n.Tr "repo.pick_reaction"}}</div> <div class="header">{{ .ctx.i18n.Tr "repo.pick_reaction"}}</div>
<div class="divider"></div> <div class="divider"></div>
<div class="item" data-content="+1">:+1:</div>
<div class="item" data-content="-1">:-1:</div>
<div class="item" data-content="laugh">:laughing:</div>
<div class="item" data-content="confused">:confused:</div>
<div class="item" data-content="heart">:heart:</div>
<div class="item" data-content="hooray">:tada:</div>
{{range $value := .AllowedReactions}}
{{if eq $value "hooray"}}
<div class="item" data-content="hooray">:tada:</div>
{{else if eq $value "laugh"}}
<div class="item" data-content="laugh">:laughing:</div>
{{else}}
<div class="item" data-content="{{$value}}">:{{$value}}:</div>
{{end}}
{{end}}
</div> </div>
</div> </div>
{{end}} {{end}}

+ 2
- 2
templates/repo/issue/view_content/comments.tmpl View File

{{end}} {{end}}
</div> </div>
{{end}} {{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) }}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "AllowedReactions" $.AllowedReactions}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "diff" false }} {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "diff" false }}
</div> </div>
{{end}} {{end}}
{{$reactions := .Reactions.GroupByType}} {{$reactions := .Reactions.GroupByType}}
{{if $reactions}} {{if $reactions}}
<div class="ui attached segment reactions"> <div class="ui attached segment reactions">
{{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions }}
{{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions "AllowedReactions" $.AllowedReactions}}
</div> </div>
{{end}} {{end}}
{{if .Attachments}} {{if .Attachments}}

+ 6
- 6
templates/repo/issue/view_content/reactions.tmpl View File

<a class="ui label basic{{if $value.HasUser $.ctx.SignedUserID}} blue{{end}}{{if not $.ctx.IsSigned}} disabled{{end}} has-emoji" data-title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ $.ctx.i18n.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}" data-content="{{ $key }}" data-action-url="{{ $.ActionURL }}"> <a class="ui label basic{{if $value.HasUser $.ctx.SignedUserID}} blue{{end}}{{if not $.ctx.IsSigned}} disabled{{end}} has-emoji" data-title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ $.ctx.i18n.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}" data-content="{{ $key }}" data-action-url="{{ $.ActionURL }}">
{{if eq $key "hooray"}} {{if eq $key "hooray"}}
:tada: :tada:
{{else if eq $key "laugh"}}
:laughing:
{{else}} {{else}}
{{if eq $key "laugh"}}
:laughing:
{{else}}
:{{$key}}:
{{end}}
:{{$key}}:
{{end}} {{end}}
{{len $value}} {{len $value}}
</a> </a>
{{end}} {{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $.ctx "ActionURL" .ActionURL }}
{{if $.AllowedReactions}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $.ctx "ActionURL" .ActionURL "AllowedReactions" $.AllowedReactions}}
{{end}}

Loading…
Cancel
Save