* 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 pagetags/v1.11.0-rc1
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. |
- `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. |
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. |
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)() | ||||
// 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 |
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 |
} | } | ||||
} | } | ||||
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) |
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 | ||||
} | } | ||||
{{$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> |
{{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}} |
<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}} |
{{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}} |
<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}} |