0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-12 13:22:55 +02:00

Merge branch 'main' into feature/artifact-viewer

This commit is contained in:
silverwind 2026-04-28 01:52:34 +02:00 committed by GitHub
commit d8e516d2d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 61 additions and 122 deletions

View File

@ -609,6 +609,8 @@ func DeleteTeam(ctx *context.Context) {
// TeamInvite renders the team invite page
func TeamInvite(ctx *context.Context) {
invite, org, team, inviter, err := getTeamInviteFromContext(ctx)
// TODO: to quickly debug the UI, can uncomment this (don't worry, it won't pass CI lint)
// invite, org, team, inviter, err = &org_model.TeamInvite{}, &org_model.Organization{}, &org_model.Team{}, ctx.Doer, nil
if err != nil {
if org_model.IsErrTeamInviteNotFound(err) {
ctx.NotFound(err)

View File

@ -5,13 +5,11 @@ package context
import (
"context"
"fmt"
"html"
"html/template"
"net/http"
"strconv"
"strings"
"sync"
"time"
"code.gitea.io/gitea/modules/httplib"
@ -91,31 +89,14 @@ func (c TemplateContext) AppFullLink(link ...string) template.URL {
return template.URL(s + "/" + strings.TrimPrefix(link[0], "/"))
}
var globalVars = sync.OnceValue(func() (ret struct {
scriptImportRemainingPart string
},
) {
// add onerror handler to alert users when the script fails to load:
// * for end users: there were many users reporting that "UI doesn't work", actually they made mistakes in their config
// * for developers: help them to remember to run "make watch-frontend" to build frontend assets
// the message will be directly put in the onerror JS code's string
onScriptErrorPrompt := `Please make sure the asset files can be accessed.`
if !setting.IsProd {
onScriptErrorPrompt += `\n\nFor development, run: make watch-frontend.`
}
onScriptErrorJS := fmt.Sprintf(`alert('Failed to load asset file from ' + this.src + '. %s')`, onScriptErrorPrompt)
ret.scriptImportRemainingPart = `onerror="` + html.EscapeString(onScriptErrorJS) + `"></script>`
return ret
})
func (c TemplateContext) ScriptImport(path string, typ ...string) template.HTML {
if len(typ) > 0 {
if typ[0] == "module" {
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" type="module" src="` + html.EscapeString(public.AssetURI(path)) + `" ` + globalVars().scriptImportRemainingPart)
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" type="module" src="` + html.EscapeString(public.AssetURI(path)) + `"></script>`)
}
panic("unsupported script type: " + typ[0])
}
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" src="` + html.EscapeString(public.AssetURI(path)) + `" ` + globalVars().scriptImportRemainingPart)
return template.HTML(`<script nonce="` + c.CspScriptNonce() + `" src="` + html.EscapeString(public.AssetURI(path)) + `"></script>`)
}
func (c TemplateContext) CspScriptNonce() (ret string) {

View File

@ -11,5 +11,8 @@
{{template "base/footer_content" .}}
{{ctx.ScriptImport "js/index.js" "module"}}
{{template "custom/footer" .}}
<script nonce="{{ctx.CspScriptNonce}}" type="module">
if (!window.config?.frontendInited) alert("Frontend is not initialized, check console errors or asset files.")
</script>
</body>
</html>

View File

@ -1,13 +1,13 @@
<div class="ui container tw-flex">
{{ctx.AvatarUtils.Avatar .Org 100 "org-avatar"}}
<div id="org-info" class="tw-flex tw-flex-col tw-flex-1 tw-break-anywhere">
<div class="ui header">
{{.Org.DisplayName}}
<span class="org-visibility">
<div class="ui container tw-flex tw-gap-4">
<div>{{ctx.AvatarUtils.Avatar .Org 100}}</div>
<div class="flex-relaxed-list">
<div class="ui header flex-left-right tw-m-0">
<div class="flex-text-block">
<span class="tw-text-2xl">{{.Org.DisplayName}}</span>
{{if .Org.Visibility.IsLimited}}<span class="ui large basic horizontal label">{{ctx.Locale.Tr "org.settings.visibility.limited_shortname"}}</span>{{end}}
{{if .Org.Visibility.IsPrivate}}<span class="ui large basic horizontal label">{{ctx.Locale.Tr "org.settings.visibility.private_shortname"}}</span>{{end}}
</span>
<span class="flex-text-block tw-ml-auto tw-text-16 tw-whitespace-nowrap">
</div>
<div class="flex-text-block">
{{if .EnableFeed}}
<a class="ui basic label button" href="{{.Org.HomeLink}}.rss" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">
{{svg "octicon-rss" 24}}
@ -16,14 +16,20 @@
{{if .IsSigned}}
{{template "org/follow_unfollow" .}}
{{end}}
</span>
</div>
</div>
{{if .RenderedDescription}}<div class="render-content markup">{{.RenderedDescription}}</div>{{end}}
<div class="tw-text-text-light meta tw-mt-1">
{{if .Org.Location}}<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="flex-text-block">{{svg "octicon-link"}} <a class="muted" target="_blank" rel="me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
{{if .IsSigned}}
{{if .Org.Email}}<div class="flex-text-block">{{svg "octicon-mail"}} <a class="muted" href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></div>{{end}}
{{if .RenderedDescription}}
<div class="render-content markup">{{.RenderedDescription}}</div>
{{end}}
<div>
{{if .Org.Location}}
<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>
{{end}}
{{if .Org.Website}}
<div class="flex-text-block">{{svg "octicon-link"}} <a class="muted" target="_blank" rel="me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>
{{end}}
{{if and .IsSigned .Org.Email}}
<div class="flex-text-block">{{svg "octicon-mail"}} <a class="muted" href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></div>
{{end}}
</div>
</div>

View File

@ -55,11 +55,12 @@
{{end}}
{{if .NumMembers}}
<h4 class="ui top attached header tw-flex">
<strong class="tw-flex-1">{{ctx.Locale.Tr "org.members"}}</strong>
<h4 class="ui top attached header flex-left-right">
<strong>{{ctx.Locale.Tr "org.members"}}</strong>
<a class="tw-text-text-light flex-text-inline" href="{{.OrgLink}}/members"><span>{{.NumMembers}}</span> {{svg "octicon-chevron-right"}}</a>
</h4>
<div class="ui attached segment members">
{{/* gap 8px below is specifically chosen to make sure a full line of avatars can exactly fit the segment width */}}
<div class="ui attached segment flex-text-block tw-flex-wrap tw-gap-[8px]">
{{range $memberUser := .OrgOverviewMembers}}
{{if or $.IsOrganizationMember (call $.IsPublicMember $memberUser.ID)}}
{{template "shared/user/avatarlink" dict "user" $memberUser "size" 32 "tooltip" true}}
@ -68,20 +69,22 @@
</div>
{{end}}
{{if .IsOrganizationMember}}
<div class="ui top attached header tw-flex">
<strong class="tw-flex-1">{{ctx.Locale.Tr "org.teams"}}</strong>
<div class="ui top attached header flex-left-right">
<strong>{{ctx.Locale.Tr "org.teams"}}</strong>
<a class="tw-text-text-light flex-text-inline" href="{{.OrgLink}}/teams"><span>{{.Org.NumTeams}}</span> {{svg "octicon-chevron-right"}}</a>
</div>
<div class="ui attached table segment teams">
<div class="ui attached segment">
<div class="flex-relaxed-list">
{{range .OrgOverviewTeams}}
<div class="item">
<a href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong class="team-name">{{.Name}}</strong></a>
<div>
<a href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong>{{.Name}}</strong></a>
<p class="tw-text-text-light">
<a class="muted" href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong>{{.NumMembers}}</strong> {{ctx.Locale.Tr "org.lower_members"}}</a> ·
<a class="muted" href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/repositories"><strong>{{.NumRepos}}</strong> {{ctx.Locale.Tr "org.lower_repositories"}}</a>
</p>
</div>
{{end}}
</div>
</div>
{{if .IsOrganizationOwner}}
<div class="ui bottom attached segment">

View File

@ -1,18 +1,14 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content organization invite">
<div role="main" aria-label="{{.Title}}" class="page-content">
<div class="ui container">
{{template "base/alert" .}}
<div class="ui centered card">
<div class="image">
{{ctx.AvatarUtils.Avatar .Organization 140}}
</div>
<div class="content">
<div class="header">{{ctx.Locale.Tr "org.teams.invite.title" .Team.Name .Organization.Name}}</div>
<div class="meta">{{ctx.Locale.Tr "org.teams.invite.by" .Inviter.Name}}</div>
<div class="description">{{ctx.Locale.Tr "org.teams.invite.description"}}</div>
</div>
<div class="extra content">
<form class="ui form" action="" method="post">
<div class="tw-flex tw-justify-center">
<div class="flex-relaxed-list">
<div class="tw-flex tw-justify-center">{{ctx.AvatarUtils.Avatar .Organization 140}}</div>
<div>{{ctx.Locale.Tr "org.teams.invite.title" .Team.Name .Organization.Name}}</div>
<div>{{ctx.Locale.Tr "org.teams.invite.by" .Inviter.Name}}</div>
<div>{{ctx.Locale.Tr "org.teams.invite.description"}}</div>
<form class="ui form tw-mt-4" action="" method="post">
<button class="fluid ui primary button">{{ctx.Locale.Tr "org.teams.join"}}</button>
</form>
</div>

View File

@ -15,21 +15,21 @@
{{end}}
</div>
</h4>
<div class="ui attached table segment detail">
<div class="item">
<div class="ui attached segment">
{{if .Team.Description}}
{{.Team.Description}}
{{else}}
<span class="tw-text-text-light tw-italic">{{ctx.Locale.Tr "org.teams.no_desc"}}</span>
{{end}}
</div>
{{if eq .Team.LowerName "owners"}}
<div class="item">
<div class="ui attached segment">
{{/* TODO: old indent is kept to make diff changes minimal, can be reformatted in the future */}}
{{if eq .Team.LowerName "owners"}}
<p>{{ctx.Locale.Tr "org.teams.owners_permission_desc"}}</p>
<p>{{ctx.Locale.Tr "org.teams.owners_permission_suggestion"}}</p>
</div>
{{else}}
<div class="item">
{{else}}
<h3>{{ctx.Locale.Tr "org.team_access_desc"}}</h3>
<ul>
{{if .Team.IncludesAllRepositories}}
@ -75,9 +75,9 @@
</tbody>
</table>
{{end}}
</div>
{{end}}
</div>
{{end}}
</div>
{{if .IsOrganizationOwner}}
<div class="ui bottom attached segment">
<a class="ui small button" href="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/edit">{{svg "octicon-gear"}} {{ctx.Locale.Tr "org.teams.settings"}}</a>

View File

@ -37,7 +37,6 @@
@import "./shared/flex-list.css";
@import "./shared/milestone.css";
@import "./shared/repoorg.css";
@import "./shared/settings.css";
@import "./features/dropzone.css";

View File

@ -1,23 +1,3 @@
.organization .head .ui.header .ui.right {
margin-top: 5px;
}
.page-content.organization .org-avatar {
margin-right: 15px;
}
.page-content.organization #org-info .ui.header {
display: flex;
align-items: center;
font-size: 36px;
margin-bottom: 0;
}
.page-content.organization #org-info .desc {
font-size: 16px;
margin-bottom: 10px;
}
.page-content.organization .team-item-box > .team-item-header {
min-height: 50px; /* the header sometimes contains a mini button, sometimes not, so we set a min-height to make sure the layout is consistent */
}
@ -30,20 +10,3 @@
white-space: nowrap;
color: var(--color-text-light-3);
}
.organization.invite .ui.avatar {
width: 100%;
height: 100%;
}
.organization.teams .detail .item {
padding: 10px 15px;
}
.organization.teams .detail .item:not(:last-child) {
border-bottom: 1px solid var(--color-secondary);
}
.org-team-navbar .active.item {
background: var(--color-box-body) !important;
}

View File

@ -1,18 +0,0 @@
.repository .head .ui.header .text,
.organization .head .ui.header .text {
vertical-align: middle;
font-size: 1.6rem;
margin-left: 15px;
}
.repository .ui.tabs.container,
.organization .ui.tabs.container {
margin-top: 14px;
margin-bottom: 0;
}
.repository .head .ui.header .org-visibility .label,
.organization .head .ui.header .org-visibility .label {
margin-left: 5px;
margin-top: 5px;
}

View File

@ -53,6 +53,7 @@ interface Window {
enableTimeTracking: boolean,
mermaidMaxSourceCharacters: number,
i18n: Record<string, string>,
frontendInited: boolean,
},
$: JQueryStatic,
jQuery: JQueryStatic,

View File

@ -171,3 +171,5 @@ const initDur = performance.now() - initStartTime;
if (initDur > 500) {
console.error(`slow init functions took ${initDur.toFixed(3)}ms`);
}
window.config.frontendInited = true;

View File

@ -12,6 +12,7 @@ window.config = {
enableTimeTracking: true,
mermaidMaxSourceCharacters: 5000,
i18n: {},
frontendInited: false,
};
window.testModules = {};