loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add slogan config (#3752)

This is a PR for #3616

Currently added a new optional config `SLOGAN` in ini file. When this config is set title page is modified in APP_NAME [ - SLOGAN]

Example in image below

![Selezione_075.png](/attachments/7a72171e-e730-4e57-8c97-ffc94258e00f)

Add the new config value in the admin settings page (readonly)

![Screenshot 2024-05-13 at 18-04-13 My Forgejo.png](/attachments/dad00fc2-29fa-4371-a7b9-5233eadeac13)

## TODO

* [x] Add the possibility to add the `SLOGAN` config from the installation form
* [ ] Update https://forgejo.org/docs/next/admin/config-cheat-sheet

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3752
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: mirko <mirko.perillo@gmail.com>
Co-committed-by: mirko <mirko.perillo@gmail.com>

authored by

mirko
mirko
and committed by
Earl Warren
f015846c dedcd6c6

+138 -13
+10 -3
custom/conf/app.example.ini
··· 1 - ; This file lists the default values used by Gitea 1 + ; This file lists the default values used by Forgejo 2 2 ;; Copy required sections to your own app.ini (default is custom/conf/app.ini) 3 3 ;; and modify as needed. 4 4 ;; Do not copy the whole file as-is, as it contains some invalid sections for illustrative purposes. 5 5 ;; If you don't know what a setting is you should not set it. 6 6 ;; 7 - ;; see https://docs.gitea.com/administration/config-cheat-sheet for additional documentation. 7 + ;; see https://forgejo.org/docs/next/admin/config-cheat-sheet for additional documentation. 8 8 9 9 10 10 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ··· 41 41 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 42 42 ;; 43 43 ;; App name that shows in every page title 44 - APP_NAME = ; Gitea: Git with a cup of tea 44 + APP_NAME = ; Forgejo: Beyond coding. We Forge. 45 + ;; 46 + ;; APP_SLOGAN shows a slogan near the App name in every page title. 47 + ;APP_SLOGAN = 48 + ;; 49 + ;; APP_DISPLAY_NAME_FORMAT defines how the AppDisplayName should be presented 50 + ;; It is used only if APP_SLOGAN is set. 51 + ;APP_DISPLAY_NAME_FORMAT = {APP_NAME}: {APP_SLOGAN} 45 52 ;; 46 53 ;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally 47 54 RUN_USER = ; git
+20 -1
modules/setting/server.go
··· 45 45 // AppName is the Application name, used in the page title. 46 46 // It maps to ini:"APP_NAME" 47 47 AppName string 48 + // AppSlogan is the Application slogan. 49 + // It maps to ini:"APP_SLOGAN" 50 + AppSlogan string 51 + // AppDisplayNameFormat defines how the AppDisplayName should be presented 52 + // It maps to ini:"APP_DISPLAY_NAME_FORMAT" 53 + AppDisplayNameFormat string 54 + // AppDisplayName is the display name for the application, defined following AppDisplayNameFormat 55 + AppDisplayName string 48 56 // AppURL is the Application ROOT_URL. It always has a '/' suffix 49 57 // It maps to ini:"ROOT_URL" 50 58 AppURL string ··· 164 172 return strings.TrimSuffix(staticURLPrefix, "/") 165 173 } 166 174 175 + func generateDisplayName() string { 176 + appDisplayName := AppName 177 + if AppSlogan != "" { 178 + appDisplayName = strings.Replace(AppDisplayNameFormat, "{APP_NAME}", AppName, 1) 179 + appDisplayName = strings.Replace(appDisplayName, "{APP_SLOGAN}", AppSlogan, 1) 180 + } 181 + return appDisplayName 182 + } 183 + 167 184 func loadServerFrom(rootCfg ConfigProvider) { 168 185 sec := rootCfg.Section("server") 169 186 AppName = rootCfg.Section("").Key("APP_NAME").MustString("Forgejo: Beyond coding. We Forge.") 170 - 187 + AppSlogan = rootCfg.Section("").Key("APP_SLOGAN").MustString("") 188 + AppDisplayNameFormat = rootCfg.Section("").Key("APP_DISPLAY_NAME_FORMAT").MustString("{APP_NAME}: {APP_SLOGAN}") 189 + AppDisplayName = generateDisplayName() 171 190 Domain = sec.Key("DOMAIN").MustString("localhost") 172 191 HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0") 173 192 HTTPPort = sec.Key("HTTP_PORT").MustString("3000")
+36
modules/setting/server_test.go
··· 1 + // Copyright 2024 The Forgejo Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package setting 5 + 6 + import ( 7 + "testing" 8 + 9 + "code.gitea.io/gitea/modules/test" 10 + 11 + "github.com/stretchr/testify/assert" 12 + ) 13 + 14 + func TestDisplayNameDefault(t *testing.T) { 15 + defer test.MockVariableValue(&AppName, "Forgejo")() 16 + defer test.MockVariableValue(&AppSlogan, "Beyond coding. We Forge.")() 17 + defer test.MockVariableValue(&AppDisplayNameFormat, "{APP_NAME}: {APP_SLOGAN}")() 18 + displayName := generateDisplayName() 19 + assert.Equal(t, "Forgejo: Beyond coding. We Forge.", displayName) 20 + } 21 + 22 + func TestDisplayNameEmptySlogan(t *testing.T) { 23 + defer test.MockVariableValue(&AppName, "Forgejo")() 24 + defer test.MockVariableValue(&AppSlogan, "")() 25 + defer test.MockVariableValue(&AppDisplayNameFormat, "{APP_NAME}: {APP_SLOGAN}")() 26 + displayName := generateDisplayName() 27 + assert.Equal(t, "Forgejo", displayName) 28 + } 29 + 30 + func TestDisplayNameCustomFormat(t *testing.T) { 31 + defer test.MockVariableValue(&AppName, "Forgejo")() 32 + defer test.MockVariableValue(&AppSlogan, "Beyond coding. We Forge.")() 33 + defer test.MockVariableValue(&AppDisplayNameFormat, "{APP_NAME} - {APP_SLOGAN}")() 34 + displayName := generateDisplayName() 35 + assert.Equal(t, "Forgejo - Beyond coding. We Forge.", displayName) 36 + }
+6
modules/templates/helper.go
··· 79 79 "AppName": func() string { 80 80 return setting.AppName 81 81 }, 82 + "AppSlogan": func() string { 83 + return setting.AppSlogan 84 + }, 85 + "AppDisplayName": func() string { 86 + return setting.AppDisplayName 87 + }, 82 88 "AppSubUrl": func() string { 83 89 return setting.AppSubURL 84 90 },
+6
modules/templates/mailer.go
··· 28 28 "AppName": func() string { 29 29 return setting.AppName 30 30 }, 31 + "AppSlogan": func() string { 32 + return setting.AppSlogan 33 + }, 34 + "AppDisplayName": func() string { 35 + return setting.AppDisplayName 36 + }, 31 37 "AppDomain": func() string { // documented in mail-templates.md 32 38 return setting.Domain 33 39 },
+3
options/locale/locale_en-US.ini
··· 267 267 general_title = General settings 268 268 app_name = Instance title 269 269 app_name_helper = You can enter your company name here. 270 + app_slogan = Instance slogan 271 + app_slogan_helper = Enter your instance slogan here. Leave empty to disable. 270 272 repo_path = Repository root path 271 273 repo_path_helper = Remote Git repositories will be saved to this directory. 272 274 lfs_path = Git LFS root path ··· 3207 3209 3208 3210 config.server_config = Server configuration 3209 3211 config.app_name = Instance title 3212 + config.app_slogan = Instance slogan 3210 3213 config.app_ver = Forgejo version 3211 3214 config.app_url = Base URL 3212 3215 config.custom_conf = Configuration file path
+10
release-notes/8.0.0/3616.md
··· 1 + There are a couple of new configs to define the name of the instance. 2 + The more important is `APP_SLOGAN`. It permits to configure a slogan for the site and it is optional. 3 + The other is `APP_DISPLAY_NAME_FORMAT` and permits to customize the aspect of the full display name for the instance used in some parts of the UI as: 4 + 5 + - Title page. 6 + - Homepage head title. 7 + - Open Graph site and title meta tags. 8 + 9 + Its default value is `APP_NAME: APP_SLOGAN`. 10 + The config `APP_DISPLAY_NAME_FORMAT` is used only if `APP_SLOGAN` is set otherwise the full display name shows only `APP_NAME` value.
+3 -1
routers/install/install.go
··· 115 115 ctx.Data["CurDbType"] = curDBType 116 116 117 117 // Application general settings 118 - form.AppName = setting.AppName 118 + form.AppName = "Forgejo" 119 + form.AppSlogan = "Beyond coding. We Forge." 119 120 form.RepoRootPath = setting.RepoRootPath 120 121 form.LFSRootPath = setting.LFS.Storage.Path 121 122 ··· 383 384 } 384 385 385 386 cfg.Section("").Key("APP_NAME").SetValue(form.AppName) 387 + cfg.Section("").Key("APP_SLOGAN").SetValue(form.AppSlogan) 386 388 cfg.Section("").Key("RUN_USER").SetValue(form.RunUser) 387 389 cfg.Section("").Key("WORK_PATH").SetValue(setting.AppWorkPath) 388 390 cfg.Section("").Key("RUN_MODE").SetValue("prod")
+1
services/forms/user_form.go
··· 31 31 DbSchema string 32 32 33 33 AppName string `binding:"Required" locale:"install.app_name"` 34 + AppSlogan string 34 35 RepoRootPath string `binding:"Required"` 35 36 LFSRootPath string 36 37 RunUser string `binding:"Required"`
+2
templates/admin/config.tmpl
··· 7 7 <dl class="admin-dl-horizontal"> 8 8 <dt>{{ctx.Locale.Tr "admin.config.app_name"}}</dt> 9 9 <dd>{{AppName}}</dd> 10 + <dt>{{ctx.Locale.Tr "admin.config.app_slogan"}}</dt> 11 + <dd>{{AppSlogan}}</dd> 10 12 <dt>{{ctx.Locale.Tr "admin.config.app_ver"}}</dt> 11 13 <dd>{{AppVer}}{{.AppBuiltWith}}</dd> 12 14 <dt>{{ctx.Locale.Tr "admin.config.custom_conf"}}</dt>
+1 -1
templates/base/head.tmpl
··· 3 3 <head> 4 4 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 5 {{/* Display `- .Repository.FullName` only if `.Title` does not already start with that. */}} 6 - <title>{{if .Title}}{{.Title}} - {{end}}{{if and (.Repository.Name) (not (StringUtils.HasPrefix .Title .Repository.FullName))}}{{.Repository.FullName}} - {{end}}{{AppName}}</title> 6 + <title>{{if .Title}}{{.Title}} - {{end}}{{if and (.Repository.Name) (not (StringUtils.HasPrefix .Title .Repository.FullName))}}{{.Repository.FullName}} - {{end}}{{AppDisplayName}}</title> 7 7 {{if .ManifestData}}<link rel="manifest" href="data:{{.ManifestData}}">{{end}} 8 8 <meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}"> 9 9 <meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}">
+2 -2
templates/base/head_opengraph.tmpl
··· 38 38 <meta property="og:image" content="{{.Repository.Owner.AvatarLink ctx}}"> 39 39 {{end}} 40 40 {{else}} 41 - <meta property="og:title" content="{{AppName}}"> 41 + <meta property="og:title" content="{{AppDisplayName}}"> 42 42 <meta property="og:type" content="website"> 43 43 <meta property="og:image" content="{{AssetUrlPrefix}}/img/logo.png"> 44 44 <meta property="og:url" content="{{AppUrl}}"> 45 45 <meta property="og:description" content="{{MetaDescription}}"> 46 46 {{end}} 47 - <meta property="og:site_name" content="{{AppName}}"> 47 + <meta property="og:site_name" content="{{AppDisplayName}}">
+1 -1
templates/home.tmpl
··· 5 5 <img class="logo" width="220" height="220" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}"> 6 6 <div class="hero"> 7 7 <h1 class="ui icon header title"> 8 - {{AppName}} 8 + {{AppDisplayName}} 9 9 </h1> 10 10 <h2>{{ctx.Locale.Tr "startpage.app_desc"}}</h2> 11 11 </div>
+5
templates/install.tmpl
··· 107 107 <input id="app_name" name="app_name" value="{{.app_name}}" required> 108 108 <span class="help">{{ctx.Locale.Tr "install.app_name_helper"}}</span> 109 109 </div> 110 + <div class="inline field"> 111 + <label for="app_slogan">{{ctx.Locale.Tr "install.app_slogan"}}</label> 112 + <input id="app_slogan" name="app_slogan" value="{{.app_slogan}}"> 113 + <span class="help">{{ctx.Locale.Tr "install.app_slogan_helper"}}</span> 114 + </div> 110 115 <div class="inline required field {{if .Err_RepoRootPath}}error{{end}}"> 111 116 <label for="repo_root_path">{{ctx.Locale.Tr "install.repo_path"}}</label> 112 117 <input id="repo_root_path" name="repo_root_path" value="{{.repo_root_path}}" required>
+1 -1
templates/status/500.tmpl
··· 9 9 <html lang="{{ctx.Locale.Lang}}" data-theme="{{ThemeName .SignedUser}}"> 10 10 <head> 11 11 <meta name="viewport" content="width=device-width, initial-scale=1"> 12 - <title>{{ctx.Locale.Tr "error.server_internal"}} - {{AppName}}</title> 12 + <title>{{ctx.Locale.Tr "error.server_internal"}} - {{AppDisplayName}}</title> 13 13 <link rel="icon" href="{{AssetUrlPrefix}}/img/favicon.svg" type="image/svg+xml"> 14 14 <link rel="alternate icon" href="{{AssetUrlPrefix}}/img/favicon.png" type="image/png"> 15 15 {{template "base/head_style" .}}
+25
tests/integration/view_test.go
··· 185 185 }) 186 186 }) 187 187 } 188 + 189 + func TestTitleDisplayName(t *testing.T) { 190 + session := emptyTestSession(t) 191 + title := GetHTMLTitle(t, session, "/") 192 + assert.Equal(t, "Gitea: Git with a cup of tea", title) 193 + } 194 + 195 + func TestHomeDisplayName(t *testing.T) { 196 + session := emptyTestSession(t) 197 + req := NewRequest(t, "GET", "/") 198 + resp := session.MakeRequest(t, req, http.StatusOK) 199 + htmlDoc := NewHTMLParser(t, resp.Body) 200 + assert.Equal(t, "Gitea: Git with a cup of tea", strings.TrimSpace(htmlDoc.Find("h1.title").Text())) 201 + } 202 + 203 + func TestOpenGraphDisplayName(t *testing.T) { 204 + session := emptyTestSession(t) 205 + req := NewRequest(t, "GET", "/") 206 + resp := session.MakeRequest(t, req, http.StatusOK) 207 + htmlDoc := NewHTMLParser(t, resp.Body) 208 + ogTitle, _ := htmlDoc.Find("meta[property='og:title']").Attr("content") 209 + assert.Equal(t, "Gitea: Git with a cup of tea", ogTitle) 210 + ogSiteName, _ := htmlDoc.Find("meta[property='og:site_name']").Attr("content") 211 + assert.Equal(t, "Gitea: Git with a cup of tea", ogSiteName) 212 + }
+2 -1
tests/mysql.ini.tmpl
··· 1 - APP_NAME = Gitea: Git with a cup of tea 1 + APP_NAME = Gitea 2 + APP_SLOGAN = Git with a cup of tea 2 3 RUN_MODE = prod 3 4 4 5 [database]
+2 -1
tests/pgsql.ini.tmpl
··· 1 - APP_NAME = Gitea: Git with a cup of tea 1 + APP_NAME = Gitea 2 + APP_SLOGAN = Git with a cup of tea 2 3 RUN_MODE = prod 3 4 4 5 [database]
+2 -1
tests/sqlite.ini.tmpl
··· 1 - APP_NAME = Gitea: Git with a cup of tea 1 + APP_NAME = Gitea 2 + APP_SLOGAN = Git with a cup of tea 2 3 RUN_MODE = prod 3 4 4 5 [database]