forked from NYANDEV/forgejo
Add modals to Organization and Team remove/leave (#16471)
* Add modals to Organization and Team remove/leave Add confirmation modals to Organization and Team remove and leave. Fix #16215 Signed-off-by: Andrew Thornton <art27@cantab.net> * avoid for-in Signed-off-by: Andrew Thornton <art27@cantab.net> * Revert "avoid for-in" This reverts commit 2af9a6f9d46ed31b6fc6e3a29e695577dcf09f75. * Apply suggestions from code review Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
3289aceec2
commit
e37342db0c
19 changed files with 157 additions and 40 deletions
|
@ -2176,12 +2176,15 @@ members.member_role = Member Role:
|
|||
members.owner = Owner
|
||||
members.member = Member
|
||||
members.remove = Remove
|
||||
members.remove.detail = Remove %[1]s from %[2]s?
|
||||
members.leave = Leave
|
||||
members.leave.detail = Leave %s?
|
||||
members.invite_desc = Add a new member to %s:
|
||||
members.invite_now = Invite Now
|
||||
|
||||
teams.join = Join
|
||||
teams.leave = Leave
|
||||
teams.leave.detail = Leave %s?
|
||||
teams.can_create_org_repo = Create repositories
|
||||
teams.can_create_org_repo_helper = Members can create new repositories in organization. Creator will get administrator access to the new repository.
|
||||
teams.read_access = Read Access
|
||||
|
|
|
@ -99,14 +99,18 @@ func MembersAction(ctx *context.Context) {
|
|||
err = org.RemoveMember(uid)
|
||||
if models.IsErrLastOrgOwner(err) {
|
||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/members")
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"redirect": ctx.Org.OrgLink + "/members",
|
||||
})
|
||||
return
|
||||
}
|
||||
case "leave":
|
||||
err = org.RemoveMember(ctx.User.ID)
|
||||
if models.IsErrLastOrgOwner(err) {
|
||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/members")
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"redirect": ctx.Org.OrgLink + "/members",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -120,9 +124,12 @@ func MembersAction(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if ctx.Params(":action") != "leave" {
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/members")
|
||||
} else {
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
redirect := ctx.Org.OrgLink + "/members"
|
||||
if ctx.Params(":action") == "leave" {
|
||||
redirect = setting.AppSubURL + "/"
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"redirect": redirect,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -66,6 +66,23 @@ func TeamsAction(ctx *context.Context) {
|
|||
err = ctx.Org.Team.AddMember(ctx.User.ID)
|
||||
case "leave":
|
||||
err = ctx.Org.Team.RemoveMember(ctx.User.ID)
|
||||
if err != nil {
|
||||
if models.IsErrLastOrgOwner(err) {
|
||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||
} else {
|
||||
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"ok": false,
|
||||
"err": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.JSON(http.StatusOK,
|
||||
map[string]interface{}{
|
||||
"redirect": ctx.Org.OrgLink + "/teams/",
|
||||
})
|
||||
return
|
||||
case "remove":
|
||||
if !ctx.Org.IsOwner {
|
||||
ctx.Error(http.StatusNotFound)
|
||||
|
@ -73,6 +90,23 @@ func TeamsAction(ctx *context.Context) {
|
|||
}
|
||||
err = ctx.Org.Team.RemoveMember(uid)
|
||||
page = "team"
|
||||
if err != nil {
|
||||
if models.IsErrLastOrgOwner(err) {
|
||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||
} else {
|
||||
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"ok": false,
|
||||
"err": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.JSON(http.StatusOK,
|
||||
map[string]interface{}{
|
||||
"redirect": ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName,
|
||||
})
|
||||
return
|
||||
case "add":
|
||||
if !ctx.Org.IsOwner {
|
||||
ctx.Error(http.StatusNotFound)
|
||||
|
|
|
@ -54,14 +54,18 @@
|
|||
<div class="ui four wide column">
|
||||
<div class="text right">
|
||||
{{if eq $.SignedUser.ID .ID}}
|
||||
<form method="post" action="{{$.OrgLink}}/members/action/leave">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui red small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.leave"}}</button>
|
||||
<form>
|
||||
<button class="ui red small button delete-button" data-modal-id="leave-organization"
|
||||
data-url="{{$.OrgLink}}/members/action/leave" data-datauid="{{.ID}}"
|
||||
data-name="{{.DisplayName}}"
|
||||
data-data-organization-name="{{$.Org.DisplayName}}">{{$.i18n.Tr "org.members.leave"}}</button>
|
||||
</form>
|
||||
{{else if $.IsOrganizationOwner}}
|
||||
<form method="post" action="{{$.OrgLink}}/members/action/remove">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui red small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.remove"}}</button>
|
||||
<form>
|
||||
<button class="ui red small button delete-button" data-modal-id="remove-organization-member"
|
||||
data-url="{{$.OrgLink}}/members/action/remove" data-datauid="{{.ID}}"
|
||||
data-name="{{.DisplayName}}"
|
||||
data-data-organization-name="{{$.Org.DisplayName}}">{{$.i18n.Tr "org.members.remove"}}</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@ -73,4 +77,25 @@
|
|||
{{template "base/paginate" .}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui small basic delete modal" id="leave-organization">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-x" 16 "close inside"}}
|
||||
{{$.i18n.Tr "org.members.leave"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{$.i18n.Tr "org.members.leave.detail" `<span class="dataOrganizationName"></span>` | Safe}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
<div class="ui small basic delete modal" id="remove-organization-member">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-x" 16 "close inside"}}
|
||||
{{$.i18n.Tr "org.members.remove"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{$.i18n.Tr "org.members.remove.detail" `<span class="name"></span>` `<span class="dataOrganizationName"></span>` | Safe}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -26,10 +26,12 @@
|
|||
<div class="ui bottom attached table segment members">
|
||||
{{range .Team.Members}}
|
||||
<div class="item">
|
||||
{{if $.IsOrganizationOwner}}
|
||||
<form method="post" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/remove">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui red small button right" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.remove"}}</button>
|
||||
{{if and $.IsOrganizationOwner (not (eq $.SignedUser.ID .ID))}}
|
||||
<form>
|
||||
<button class="ui red button delete-button right" data-modal-id="remove-team-member"
|
||||
data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/remove" data-datauid="{{.ID}}"
|
||||
data-name="{{.DisplayName}}"
|
||||
data-data-team-name="{{$.Team.Name}}">{{$.i18n.Tr "org.members.remove"}}</button>
|
||||
</form>
|
||||
{{end}}
|
||||
<a href="{{.HomeLink}}">
|
||||
|
@ -47,4 +49,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui small basic delete modal" id="remove-team-member">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-x" 16 "close inside"}}
|
||||
{{$.i18n.Tr "org.members.remove"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{$.i18n.Tr "org.members.remove.detail" `<span class="name"></span>` `<span class="dataTeamName"></span>` | Safe}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<strong>{{.Team.Name}}</strong>
|
||||
<div class="ui right">
|
||||
{{if .Team.IsMember $.SignedUser.ID}}
|
||||
<form method="post" action="{{.OrgLink}}/teams/{{.Team.LowerName}}/action/leave">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<input type="hidden" name="page" value="home"/>
|
||||
<button type="submit" class="ui red tiny button" name="uid" value="{{$.SignedUser.ID}}">{{$.i18n.Tr "org.teams.leave"}}</button>
|
||||
<form>
|
||||
<button class="ui red tiny button delete-button" data-modal-id="leave-team-sidebar"
|
||||
data-url="{{.OrgLink}}/teams/{{.Team.LowerName}}/action/leave" data-datauid="{{$.SignedUser.ID}}"
|
||||
data-name="{{.Team.Name}}">{{$.i18n.Tr "org.teams.leave"}}</button>
|
||||
</form>
|
||||
{{else if .IsOrganizationOwner}}
|
||||
<form method="post" action="{{.OrgLink}}/teams/{{.Team.LowerName}}/action/join">
|
||||
|
@ -59,3 +59,13 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui small basic delete modal" id="leave-team-sidebar">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-x" 16 "close inside"}}
|
||||
{{$.i18n.Tr "org.teams.leave"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{$.i18n.Tr "org.teams.leave.detail" `<span class="name"></span>` | Safe}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
<a class="text black" href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong>{{.Name}}</strong></a>
|
||||
<div class="ui right">
|
||||
{{if .IsMember $.SignedUser.ID}}
|
||||
<form method="post" action="{{$.OrgLink}}/teams/{{.LowerName}}/action/leave">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui red small button" name="uid" value="{{$.SignedUser.ID}}">{{$.i18n.Tr "org.teams.leave"}}</button>
|
||||
<form>
|
||||
<button class="ui red tiny button delete-button" data-modal-id="leave-team"
|
||||
data-url="{{$.OrgLink}}/teams/{{.LowerName}}/action/leave" data-datauid="{{$.SignedUser.ID}}"
|
||||
data-name="{{.Name}}">{{$.i18n.Tr "org.teams.leave"}}</button>
|
||||
</form>
|
||||
{{else if $.IsOrganizationOwner}}
|
||||
<form method="post" action="{{$.OrgLink}}/teams/{{.LowerName}}/action/join">
|
||||
|
@ -44,4 +45,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui small basic delete modal" id="leave-team">
|
||||
<div class="ui icon header">
|
||||
{{svg "octicon-x" 16 "close inside"}}
|
||||
{{$.i18n.Tr "org.teams.leave"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{$.i18n.Tr "org.teams.leave.detail" `<span class="name"></span>` | Safe}}</p>
|
||||
</div>
|
||||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<div class="item">
|
||||
{{if not .IsPrimary}}
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-email" data-url="{{AppSubUrl}}/user/settings/account/email/delete" data-id="{{.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-email" data-url="{{AppSubUrl}}/user/settings/account/email/delete" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "settings.delete_email"}}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -185,7 +185,7 @@
|
|||
<input id="password-confirmation" name="password" type="password" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui red button delete-button" id="delete-account" data-type="form" data-form="#delete-form">
|
||||
<div class="ui red button delete-button" data-modal-id="delete-account" data-type="form" data-form="#delete-form">
|
||||
{{.i18n.Tr "settings.confirm_delete_account"}}
|
||||
</div>
|
||||
<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
{{range .Tokens}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-token" data-url="{{$.Link}}/delete" data-id="{{.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-token" data-url="{{$.Link}}/delete" data-id="{{.ID}}">
|
||||
{{svg "octicon-trash" 16 "mr-2"}}
|
||||
{{$.i18n.Tr "settings.delete_token"}}
|
||||
</button>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{{svg "octicon-pencil" 16 "mr-2"}}
|
||||
{{$.i18n.Tr "settings.oauth2_application_edit"}}
|
||||
</a>
|
||||
<button class="ui red tiny button delete-button" id="remove-gitea-oauth2-application"
|
||||
<button class="ui red tiny button delete-button" data-modal-id="remove-gitea-oauth2-application"
|
||||
data-url="{{AppSubUrl}}/user/settings/applications/oauth2/delete"
|
||||
data-id="{{$app.ID}}">
|
||||
{{svg "octicon-trash" 16 "mr-2"}}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{{range $grant := .Grants}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="revoke-gitea-oauth2-grant"
|
||||
<button class="ui red tiny button delete-button" data-modal-id="revoke-gitea-oauth2-grant"
|
||||
data-url="{{AppSubUrl}}/user/settings/applications/oauth2/revoke"
|
||||
data-id="{{$grant.ID}}">
|
||||
{{$.i18n.Tr "settings.revoke_key"}}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{{range .GPGKeys}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-gpg" data-url="{{$.Link}}/delete?type=gpg" data-id="{{.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-gpg" data-url="{{$.Link}}/delete?type=gpg" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
{{if and (not .Verified) (ne $.VerifyingID .KeyID)}}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{{range .Principals}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-principal" data-url="{{$.Link}}/delete?type=principal" data-id="{{.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-principal" data-url="{{$.Link}}/delete?type=principal" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
{{range $index, $key := .Keys}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button{{if index $.ExternalKeys $index}} disabled{{end}}" id="delete-ssh" data-url="{{$.Link}}/delete?type=ssh" data-id="{{.ID}}"{{if index $.ExternalKeys $index}} title="{{$.i18n.Tr "settings.ssh_externally_managed"}}"{{end}}>
|
||||
<button class="ui red tiny button delete-button{{if index $.ExternalKeys $index}} disabled{{end}}" data-modal-id="delete-ssh" data-url="{{$.Link}}/delete?type=ssh" data-id="{{.ID}}"{{if index $.ExternalKeys $index}} title="{{$.i18n.Tr "settings.ssh_externally_managed"}}"{{end}}>
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{{range $loginSource, $provider := .AccountLinks}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-account-link" data-url="{{AppSubUrl}}/user/settings/security/account_link" data-id="{{$loginSource.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-account-link" data-url="{{AppSubUrl}}/user/settings/security/account_link" data-id="{{$loginSource.ID}}">
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{{range .OpenIDs}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-openid" data-url="{{AppSubUrl}}/user/settings/security/openid/delete" data-id="{{.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-openid" data-url="{{AppSubUrl}}/user/settings/security/openid/delete" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<form class="ui form" action="{{AppSubUrl}}/user/settings/security/two_factor/disable" method="post" enctype="multipart/form-data" id="disable-form">
|
||||
{{.CsrfTokenHtml}}
|
||||
<p>{{.i18n.Tr "settings.twofa_disable_note"}}</p>
|
||||
<div class="ui red button delete-button" id="disable-twofa" data-type="form" data-form="#disable-form">{{$.i18n.Tr "settings.twofa_disable"}}</div>
|
||||
<div class="ui red button delete-button" data-modal-id="disable-twofa" data-type="form" data-form="#disable-form">{{$.i18n.Tr "settings.twofa_disable"}}</div>
|
||||
</form>
|
||||
{{else}}
|
||||
<p>{{.i18n.Tr "settings.twofa_not_enrolled"}}</p>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{{range .U2FRegistrations}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
<button class="ui red tiny button delete-button" id="delete-registration" data-url="{{$.Link}}/u2f/delete" data-id="{{.ID}}">
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-registration" data-url="{{$.Link}}/u2f/delete" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -2956,13 +2956,19 @@ $(() => {
|
|||
|
||||
function showDeletePopup() {
|
||||
const $this = $(this);
|
||||
const dataArray = $this.data();
|
||||
let filter = '';
|
||||
if ($this.attr('id')) {
|
||||
filter += `#${$this.attr('id')}`;
|
||||
if ($this.data('modal-id')) {
|
||||
filter += `#${$this.data('modal-id')}`;
|
||||
}
|
||||
|
||||
const dialog = $(`.delete.modal${filter}`);
|
||||
dialog.find('.name').text($this.data('name'));
|
||||
for (const [key, value] of Object.entries(dataArray)) {
|
||||
if (key && key.startsWith('data')) {
|
||||
dialog.find(`.${key}`).text(value);
|
||||
}
|
||||
}
|
||||
|
||||
dialog.modal({
|
||||
closable: false,
|
||||
|
@ -2972,10 +2978,19 @@ function showDeletePopup() {
|
|||
return;
|
||||
}
|
||||
|
||||
$.post($this.data('url'), {
|
||||
const postData = {
|
||||
_csrf: csrf,
|
||||
id: $this.data('id')
|
||||
}).done((data) => {
|
||||
};
|
||||
for (const [key, value] of Object.entries(dataArray)) {
|
||||
if (key && key.startsWith('data')) {
|
||||
postData[key.substr(4)] = value;
|
||||
}
|
||||
if (key === 'id') {
|
||||
postData['id'] = value;
|
||||
}
|
||||
}
|
||||
|
||||
$.post($this.data('url'), postData).done((data) => {
|
||||
window.location.href = data.redirect;
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue