Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2629,6 +2629,10 @@ members.remove = Remove
members.remove.detail = Remove %[1]s from %[2]s?
members.leave = Leave
members.leave.detail = Leave %s?
members.invite = Invite
members.invite_member = Invite Member
members.to = To
members.team = Team
members.invite_desc = Add a new member to %s:
members.invite_now = Invite Now

Expand Down
17 changes: 16 additions & 1 deletion routers/web/org/members.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import (

const (
// tplMembers template for organization members page
tplMembers base.TplName = "org/member/members"
tplMembers base.TplName = "org/member/members"
tplMembersInvite base.TplName = "org/member/invite"
)

// Members render organization users page
Expand Down Expand Up @@ -76,6 +77,20 @@ func Members(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplMembers)
}

// MembersInvite render organization members invite page
func MembersInvite(ctx *context.Context) {
org := ctx.Org.Organization
ctx.Data["Title"] = org.FullName
ctx.Data["PageIsOrgMembers"] = true
ctx.Data["Teams"] = ctx.Org.Teams
ctx.Data["IsEmailInviteEnabled"] = setting.MailService != nil
if err := shared_user.LoadHeaderCount(ctx); err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
ctx.HTML(http.StatusOK, tplMembersInvite)
}

// MembersAction response for operation to a member of organization
func MembersAction(ctx *context.Context) {
uid := ctx.FormInt64("uid")
Expand Down
1 change: 1 addition & 0 deletions routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ func registerRoutes(m *web.Route) {
m.Group("/org", func() {
m.Group("/{org}", func() {
m.Get("/members", org.Members)
m.Get("/members/invite", org.MembersInvite)
}, context.OrgAssignment())
}, ignSignIn)

Expand Down
28 changes: 28 additions & 0 deletions templates/org/member/invite.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content organization invitemember">
{{template "org/header" .}}
<div class="ui container">
{{template "base/alert" .}}

<div class="center">
<h1 class="ui header">{{ctx.Locale.Tr "org.members.invite_member"}}</h1>
<form class="ui action input member-invite" data-org-link="{{.OrgLink}}" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="uid" value="{{.SignedUser.ID}}">
<div class="ui label">{{ctx.Locale.Tr "org.members.invite"}}</div>
<div id="search-user-box" class="ui search input"{{if .IsEmailInviteEnabled}} data-allow-email="true" data-allow-email-description="{{ctx.Locale.Tr "org.teams.invite_team_member" $.Team.Name}}"{{end}}>
<input class="prompt" name="uname" placeholder="{{ctx.Locale.Tr "repo.settings.search_user_placeholder"}}" autocomplete="off" autofocus required>
</div>
<div class="ui label">{{ctx.Locale.Tr "org.members.to"}}</div>
<select class="ui selection dropdown" name="team">
{{range .Teams}}
<option value="{{.LowerName | PathEscape}}">{{.Name}}</option>
{{end}}
</select>
<div class="ui label">{{ctx.Locale.Tr "org.members.team"}}</div>
<button class="ui primary button">{{ctx.Locale.Tr "org.members.invite_now"}}</button>
</form>
</div>
</div>
</div>
{{template "base/footer" .}}
8 changes: 7 additions & 1 deletion templates/org/member/members.tmpl
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content organization">
<div role="main" aria-label="{{.Title}}" class="page-content organization members">
{{template "org/header" .}}
<div class="ui container">
{{template "base/alert" .}}
{{if .IsOrganizationOwner}}
<div class="text right">
<a class="ui primary button" href="{{.OrgLink}}/members/invite">{{svg "octicon-plus"}} {{ctx.Locale.Tr "org.members.invite_member"}}</a>
</div>
<div class="divider"></div>
{{end}}

<div class="flex-list">
{{range .Members}}
Expand Down
18 changes: 18 additions & 0 deletions web_src/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ a.label,
text-decoration: none !important;
}

.ui.search > .prompt {
color: var(--color-text);
background: var(--color-box-body);
border-color: var(--color-secondary);
}

.ui.search .prompt {
border-radius: var(--border-radius);
}

.ui.search > .prompt:focus {
border-color: var(--color-primary);
background: var(--color-box-body);
color: var(--color-text);
}

.ui.search > .results {
background: var(--color-body);
border-color: var(--color-secondary);
Expand Down Expand Up @@ -257,6 +273,8 @@ ol.ui.list li,
.ui.input.focus > input,
.ui.input > input:focus {
border-color: var(--color-primary);
background: var(--color-box-body);
color: var(--color-text);
}

.ui.action.input .ui.ui.button {
Expand Down
31 changes: 31 additions & 0 deletions web_src/js/features/org-member.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export function initOrgMemberInvite() {
if (document.querySelector('.page-content.organization.invitemember') === null) {
return;
}

/**
* @type {HTMLFormElement | null}
*/
const memberInvite = document.querySelector('form.member-invite');
if (memberInvite === null) {
return;
}

const orgLink = memberInvite.getAttribute('data-org-link');
if (orgLink === null) {
return;
}

/**
* @type {HTMLSelectElement | null}
*/
const teamSelect = memberInvite.querySelector('select[name=team]');
if (teamSelect === null) {
return;
}

memberInvite.action = `${orgLink}/teams/${teamSelect.value}/action/add`;
teamSelect.addEventListener('change', () => {
memberInvite.action = `${orgLink}/teams/${teamSelect.value}/action/add`;
});
}
3 changes: 3 additions & 0 deletions web_src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
initRepoSettingSearchTeamBox,
} from './features/repo-settings.js';
import {initRepoDiffView} from './features/repo-diff.js';
import {initOrgMemberInvite} from './features/org-member.js';
import {initOrgTeamSearchRepoBox, initOrgTeamSettings} from './features/org-team.js';
import {initUserAuthWebAuthn, initUserAuthWebAuthnRegister} from './features/user-auth-webauthn.js';
import {initRepoRelease, initRepoReleaseNew} from './features/repo-release.js';
Expand Down Expand Up @@ -135,6 +136,8 @@ onDomReady(() => {
initNotificationCount();
initNotificationsTable();

initOrgMemberInvite();

initOrgTeamSearchRepoBox();
initOrgTeamSettings();

Expand Down