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:
commit
d8e516d2d3
@ -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)
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
1
web_src/js/globals.d.ts
vendored
1
web_src/js/globals.d.ts
vendored
@ -53,6 +53,7 @@ interface Window {
|
||||
enableTimeTracking: boolean,
|
||||
mermaidMaxSourceCharacters: number,
|
||||
i18n: Record<string, string>,
|
||||
frontendInited: boolean,
|
||||
},
|
||||
$: JQueryStatic,
|
||||
jQuery: JQueryStatic,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -12,6 +12,7 @@ window.config = {
|
||||
enableTimeTracking: true,
|
||||
mermaidMaxSourceCharacters: 5000,
|
||||
i18n: {},
|
||||
frontendInited: false,
|
||||
};
|
||||
|
||||
window.testModules = {};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user