mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-04 10:05:18 +02:00
add templates for pages to add and manage teams with access to a group
This commit is contained in:
parent
902cf739b8
commit
8d82d52c30
@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
group_model "code.gitea.io/gitea/models/group"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@ -451,6 +452,7 @@ type GetFeedsOptions struct {
|
||||
RequestedUser *user_model.User // the user we want activity for
|
||||
RequestedTeam *organization.Team // the team we want activity for
|
||||
RequestedRepo *repo_model.Repository // the repo we want activity for
|
||||
RequestedGroup *group_model.Group // the repo group we want activity for
|
||||
Actor *user_model.User // the user viewing the activity
|
||||
IncludePrivate bool // include private actions
|
||||
OnlyPerformedBy bool // only actions performed by requested user
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
group_model "code.gitea.io/gitea/models/group"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@ -21,15 +22,15 @@ type UserHeatmapData struct {
|
||||
|
||||
// GetUserHeatmapDataByUser returns an array of UserHeatmapData, it checks whether doer can access user's activity
|
||||
func GetUserHeatmapDataByUser(ctx context.Context, user, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||
return getUserHeatmapData(ctx, user, nil, doer)
|
||||
return getUserHeatmapData(ctx, user, nil, nil, doer)
|
||||
}
|
||||
|
||||
// GetUserHeatmapDataByOrgTeam returns an array of UserHeatmapData, it checks whether doer can access org's activity
|
||||
func GetUserHeatmapDataByOrgTeam(ctx context.Context, org *organization.Organization, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||
return getUserHeatmapData(ctx, org.AsUser(), team, doer)
|
||||
func GetUserHeatmapDataByOrgTeam(ctx context.Context, org *organization.Organization, team *organization.Team, group *group_model.Group, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||
return getUserHeatmapData(ctx, org.AsUser(), team, group, doer)
|
||||
}
|
||||
|
||||
func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||
func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organization.Team, group *group_model.Group, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||
hdata := make([]*UserHeatmapData, 0)
|
||||
|
||||
if !ActivityReadable(user, doer) {
|
||||
@ -53,6 +54,7 @@ func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organi
|
||||
Actor: doer,
|
||||
IncludePrivate: true, // don't filter by private, as we already filter by repo access
|
||||
IncludeDeleted: true,
|
||||
RequestedGroup: group,
|
||||
// * Heatmaps for individual users only include actions that the user themself did.
|
||||
// * For organizations actions by all users that were made in owned
|
||||
// repositories are counted.
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package group
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
@ -102,7 +103,7 @@ func GetTopLevelGroupItemList(ctx context.Context, orgID int64, doer *user_model
|
||||
ActorID: doer.ID,
|
||||
OwnerID: orgID,
|
||||
}, group_model.
|
||||
AccessibleGroupCondition(doer, unit.TypeInvalid))
|
||||
AccessibleGroupCondition(doer, unit.TypeInvalid, perm.AccessModeRead))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
144
templates/group/team/new.tmpl
Normal file
144
templates/group/team/new.tmpl
Normal file
@ -0,0 +1,144 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content repo-group new team">
|
||||
{{template "group/header" .}}
|
||||
<div class="ui container">
|
||||
<div class="ui grid">
|
||||
<div class="column">
|
||||
<form class="ui form" action="{{.OrgGroupLink}}/teams/{{.Team.LowerName | PathEscape}}/edit" data-delete-url="{{.OrgGroupLink}}/teams/{{.Team.LowerName | PathEscape}}/delete" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<h3 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "org.teams.settings"}}
|
||||
</h3>
|
||||
<div class="ui attached segment">
|
||||
{{template "base/alert" .}}
|
||||
{{if not (eq .Team.LowerName "owners")}}
|
||||
<div class="grouped field">
|
||||
<label>{{ctx.Locale.Tr "org.team_access_desc"}}</label>
|
||||
<br>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="repo_access" value="specific" {{if not .Team.IncludesAllRepositories}}checked{{end}}>
|
||||
<label>{{ctx.Locale.Tr "org.teams.specific_repositories"}}</label>
|
||||
<span class="help">{{ctx.Locale.Tr "org.teams.specific_repositories_helper"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="repo_access" value="all" {{if .Team.IncludesAllRepositories}}checked{{end}}>
|
||||
<label>{{ctx.Locale.Tr "org.teams.all_repositories"}}</label>
|
||||
<span class="help">{{ctx.Locale.Tr "org.teams.all_repositories_helper"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<label for="can_create_org_repo">{{ctx.Locale.Tr "org.teams.can_create_org_repo"}}</label>
|
||||
<input id="can_create_org_repo" name="can_create_org_repo" type="checkbox" {{if .Team.CanCreateOrgRepo}}checked{{end}}>
|
||||
<span class="help">{{ctx.Locale.Tr "org.teams.can_create_org_repo_helper"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grouped field">
|
||||
<label>{{ctx.Locale.Tr "org.team_permission_desc"}}</label>
|
||||
<br>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="permission" value="read" {{if or .PageIsOrgTeamsNew (eq .Team.AccessMode 1) (eq .Team.AccessMode 2)}}checked{{end}}>
|
||||
<label>{{ctx.Locale.Tr "org.teams.general_access"}}</label>
|
||||
<span class="help">{{ctx.Locale.Tr "org.teams.general_access_helper"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="permission" value="admin" {{if eq .Team.AccessMode 3}}checked{{end}}>
|
||||
<label>{{ctx.Locale.Tr "org.teams.admin_access"}}</label>
|
||||
<span class="help">{{ctx.Locale.Tr "org.teams.admin_access_helper"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="team-units required grouped field {{if eq .Team.AccessMode 3}}tw-hidden{{end}}">
|
||||
<label>{{ctx.Locale.Tr "org.team_unit_desc"}}</label>
|
||||
<table class="ui celled table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ctx.Locale.Tr "units.unit"}}</th>
|
||||
<th class="center aligned">{{ctx.Locale.Tr "org.teams.none_access"}}
|
||||
<span class="tw-align-middle" data-tooltip-content="{{ctx.Locale.Tr "org.teams.none_access_helper"}}">{{svg "octicon-question" 16 "tw-ml-1"}}</span></th>
|
||||
<th class="center aligned">{{ctx.Locale.Tr "org.teams.read_access"}}
|
||||
<span class="tw-align-middle" data-tooltip-content="{{ctx.Locale.Tr "org.teams.read_access_helper"}}">{{svg "octicon-question" 16 "tw-ml-1"}}</span></th>
|
||||
<th class="center aligned">{{ctx.Locale.Tr "org.teams.write_access"}}
|
||||
<span class="tw-align-middle" data-tooltip-content="{{ctx.Locale.Tr "org.teams.write_access_helper"}}">{{svg "octicon-question" 16 "tw-ml-1"}}</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $t, $unit := $.Units}}
|
||||
{{if ge $unit.MaxPerm 2}}
|
||||
<tr>
|
||||
<td>
|
||||
<div {{if $unit.Type.UnitGlobalDisabled}}class="field" data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{- else -}}class="field"{{end}}>
|
||||
<div>
|
||||
<label>{{ctx.Locale.Tr $unit.NameKey}}{{if $unit.Type.UnitGlobalDisabled}} {{ctx.Locale.Tr "org.team_unit_disabled"}}{{end}}</label>
|
||||
<span class="help">{{ctx.Locale.Tr $unit.DescKey}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="center aligned">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="unit_{{$unit.Type.Value}}" value="0"{{if or ($unit.Type.UnitGlobalDisabled) (eq ($.Team.UnitAccessMode ctx $unit.Type) 0)}} checked{{end}} title="{{ctx.Locale.Tr "org.teams.none_access"}}">
|
||||
</div>
|
||||
</td>
|
||||
<td class="center aligned">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode ctx $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}} title="{{ctx.Locale.Tr "org.teams.read_access"}}">
|
||||
</div>
|
||||
</td>
|
||||
<td class="center aligned">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="unit_{{$unit.Type.Value}}" value="2"{{if (ge ($.Team.UnitAccessMode ctx $unit.Type) 2)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}} title="{{ctx.Locale.Tr "org.teams.write_access"}}">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{range $t, $unit := $.Units}}
|
||||
{{if lt $unit.MaxPerm 2}}
|
||||
<div {{if $unit.Type.UnitGlobalDisabled}}class="field" data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{else}}class="field"{{end}}>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode ctx $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
|
||||
<label>{{ctx.Locale.Tr $unit.NameKey}}{{if $unit.Type.UnitGlobalDisabled}} {{ctx.Locale.Tr "org.team_unit_disabled"}}{{end}}</label>
|
||||
<span class="help">{{ctx.Locale.Tr $unit.DescKey}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="field">
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "org.teams.update_settings"}}</button>
|
||||
{{if not (eq .Team.LowerName "owners")}}
|
||||
<button class="ui red button delete-button" data-url="{{.OrgGroupLink}}/teams/{{.Team.Name | PathEscape}}/delete">{{ctx.Locale.Tr "org.teams.delete_team"}}</button>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui g-modal-confirm delete modal">
|
||||
<div class="header">
|
||||
{{svg "octicon-trash"}}
|
||||
{{ctx.Locale.Tr "group.teams.delete_team_title"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{ctx.Locale.Tr "group.teams.delete_team_desc"}}</p>
|
||||
</div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
104
templates/group/team/teams.tmpl
Normal file
104
templates/group/team/teams.tmpl
Normal file
@ -0,0 +1,104 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content repo-group teams">
|
||||
{{template "group/header" .}}
|
||||
<div class="ui container">
|
||||
{{ template "base/alert" .}}
|
||||
|
||||
<div class="ui mobile reversed stackable grid">
|
||||
<div class="eleven wide column">
|
||||
<div class="ui two column stackable grid">
|
||||
{{if or .IsGroupAdmin .IsGroupOwner}}
|
||||
|
||||
<div class="one column row">
|
||||
<div class="column">
|
||||
<form class="ui form ignore-dirty tw-flex tw-flex-wrap tw-gap-2" action="{{$.OrgGroupLink}}/teams/add"
|
||||
method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<input type="hidden" name="uid" value="{{.SignedUser.ID}}">
|
||||
<div id="search-team-box" data-search-url="{{$.OrgLink}}/-/search_team_candidates"
|
||||
class="ui search tw-mr-2 tw-flex-grow">
|
||||
<div class="ui input fluid">
|
||||
<input class="prompt" name="tname" placeholder="{{ctx.Locale.Tr "search.team_kind"}}"
|
||||
autocomplete="off" required>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "group.teams.add"}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{range .Teams}}
|
||||
<div class="column">
|
||||
<div class="ui top attached header">
|
||||
<a class="text black"
|
||||
href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong>{{.Name}}</strong></a>
|
||||
<div class="ui right">
|
||||
<a class="ui primary tiny button"
|
||||
href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}">{{ctx.Locale.Tr "view"}}</a>
|
||||
|
||||
{{if .IsMember ctx $.SignedUser.ID}}
|
||||
<form>
|
||||
<button class="ui red tiny button delete-button" data-modal-id="leave-team"
|
||||
data-url="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/action/leave"
|
||||
data-datauid="{{$.SignedUser.ID}}"
|
||||
data-name="{{.Name}}">{{ctx.Locale.Tr "org.teams.leave"}}</button>
|
||||
</form>
|
||||
{{else if $.IsOrganizationOwner}}
|
||||
<form method="post" action="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/action/join">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui primary tiny button" name="uid"
|
||||
value="{{$.SignedUser.ID}}">{{ctx.Locale.Tr "org.teams.join"}}</button>
|
||||
</form>
|
||||
{{end}}
|
||||
|
||||
{{if and (or $.IsGroupAdmin $.IsGroupOwner) (not .IsOwnerTeam)}}
|
||||
<form>
|
||||
<button class="ui red tiny button delete-button" data-modal-id="remove-team"
|
||||
data-url="{{$.OrgGroupLink}}/teams/{{.LowerName | PathEscape}}/remove"
|
||||
data-datauid="{{$.SignedUser.ID}}"
|
||||
data-name="{{.Name}}">{{ctx.Locale.Tr "group.teams.remove"}}</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached segment members">
|
||||
{{range .Members}}
|
||||
{{template "shared/user/avatarlink" dict "user" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui bottom attached header">
|
||||
<p class="team-meta"><a class="muted"
|
||||
href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}">{{.NumMembers}} {{ctx.Locale.Tr "org.lower_members"}}</a>
|
||||
· <a class="muted"
|
||||
href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/repositories">{{.NumRepos}} {{ctx.Locale.Tr "org.lower_repositories"}}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="five wide column">
|
||||
{{template "group/sidebar/menu" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui g-modal-confirm delete modal" id="leave-team">
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "org.teams.leave"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{ctx.Locale.Tr "org.teams.leave.detail" (`<span class="name"></span>`|SafeHTML)}}</p>
|
||||
</div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
<div class="ui g-modal-confirm delete modal" id="remove-team">
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "group.teams.remove"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{ctx.Locale.Tr "group.teams.remove.detail" (`<span class="name"></span>`|SafeHTML)}}</p>
|
||||
</div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
@ -1,6 +1,10 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content organization teams">
|
||||
{{if .PageIsOrgTeams}}
|
||||
{{template "org/header" .}}
|
||||
{{else if .PageIsGroupTeams}}
|
||||
{{template "group/header" .}}
|
||||
{{end}}
|
||||
<div class="ui container">
|
||||
{{template "base/alert" .}}
|
||||
{{if .IsOrganizationOwner}}
|
||||
@ -18,6 +22,7 @@
|
||||
<a class="tw-text-text" href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong>{{.Name}}</strong></a>
|
||||
<div class="ui right">
|
||||
<a class="ui primary tiny button" href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}">{{ctx.Locale.Tr "view"}}</a>
|
||||
|
||||
{{if .IsMember ctx $.SignedUser.ID}}
|
||||
<form>
|
||||
<button class="ui red tiny button delete-button" data-modal-id="leave-team"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user