Skip to content

Commit 00e1960

Browse files
Allow to add and remove all repositories to team.
1 parent f05cd3e commit 00e1960

File tree

5 files changed

+150
-30
lines changed

5 files changed

+150
-30
lines changed

models/org_team.go

Lines changed: 79 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,21 @@ func (t *Team) addAllRepositories(e Engine) error {
243243
return nil
244244
}
245245

246+
// AddAllRepositories adds all repositories to the team
247+
func (t *Team) AddAllRepositories() (err error) {
248+
sess := x.NewSession()
249+
defer sess.Close()
250+
if err = sess.Begin(); err != nil {
251+
return err
252+
}
253+
254+
if err = t.addAllRepositories(sess); err != nil {
255+
return err
256+
}
257+
258+
return sess.Commit()
259+
}
260+
246261
// AddRepository adds new repository to team of organization.
247262
func (t *Team) AddRepository(repo *Repository) (err error) {
248263
if repo.OwnerID != t.OrgID {
@@ -264,6 +279,69 @@ func (t *Team) AddRepository(repo *Repository) (err error) {
264279
return sess.Commit()
265280
}
266281

282+
// RemoveAllRepositories removes all repositories from team and recalculates access
283+
func (t *Team) RemoveAllRepositories() (err error) {
284+
if t.IncludesAllRepositories {
285+
return nil
286+
}
287+
288+
sess := x.NewSession()
289+
defer sess.Close()
290+
if err = sess.Begin(); err != nil {
291+
return err
292+
}
293+
294+
if err = t.removeAllRepositories(sess); err != nil {
295+
return err
296+
}
297+
298+
t.NumRepos = 0
299+
if _, err = sess.ID(t.ID).Cols("num_repos").Update(t); err != nil {
300+
return err
301+
}
302+
303+
return sess.Commit()
304+
}
305+
306+
// removeAllRepositories removes all repositories from team and recalculates access
307+
// Note: Shall not be called if team includes all repositories
308+
func (t *Team) removeAllRepositories(e Engine) (err error) {
309+
// Delete all accesses.
310+
for _, repo := range t.Repos {
311+
if err := repo.recalculateTeamAccesses(e, t.ID); err != nil {
312+
return err
313+
}
314+
315+
// Remove watches from all users and now unaccessible repos
316+
for _, user := range t.Members {
317+
has, err := hasAccess(e, user.ID, repo)
318+
if err != nil {
319+
return err
320+
} else if has {
321+
continue
322+
}
323+
324+
if err = watchRepo(e, user.ID, repo.ID, false); err != nil {
325+
return err
326+
}
327+
328+
// Remove all IssueWatches a user has subscribed to in the repositories
329+
if err = removeIssueWatchersByRepoID(e, user.ID, repo.ID); err != nil {
330+
return err
331+
}
332+
}
333+
}
334+
335+
// Delete team-repo
336+
if _, err := e.
337+
Where("team_id=?", t.ID).
338+
Delete(new(TeamRepo)); err != nil {
339+
return err
340+
}
341+
342+
return nil
343+
}
344+
267345
// removeRepository removes a repository from a team and recalculates access
268346
// Note: Repository shall not be removed from team if it includes all repositories (unless the repository is deleted)
269347
func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (err error) {
@@ -577,36 +655,7 @@ func DeleteTeam(t *Team) error {
577655
return err
578656
}
579657

580-
// Delete all accesses.
581-
for _, repo := range t.Repos {
582-
if err := repo.recalculateTeamAccesses(sess, t.ID); err != nil {
583-
return err
584-
}
585-
586-
// Remove watches from all users and now unaccessible repos
587-
for _, user := range t.Members {
588-
has, err := hasAccess(sess, user.ID, repo)
589-
if err != nil {
590-
return err
591-
} else if has {
592-
continue
593-
}
594-
595-
if err = watchRepo(sess, user.ID, repo.ID, false); err != nil {
596-
return err
597-
}
598-
599-
// Remove all IssueWatches a user has subscribed to in the repositories
600-
if err = removeIssueWatchersByRepoID(sess, user.ID, repo.ID); err != nil {
601-
return err
602-
}
603-
}
604-
}
605-
606-
// Delete team-repo
607-
if _, err := sess.
608-
Where("team_id=?", t.ID).
609-
Delete(new(TeamRepo)); err != nil {
658+
if err := t.removeAllRepositories(sess); err != nil {
610659
return err
611660
}
612661

options/locale/locale_en-US.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,10 @@ teams.repositories = Team Repositories
15851585
teams.search_repo_placeholder = Search repository…
15861586
teams.add_team_repository = Add Team Repository
15871587
teams.remove_repo = Remove
1588+
teams.remove_all_repos_title = Remove all team repositories
1589+
teams.remove_all_repos_desc = This will remove all of the repositories from the team.
1590+
teams.add_all_repos_title = Add all repositories
1591+
teams.add_all_repos_desc = This will add all of the organizations repositories to the team.
15881592
teams.add_nonexistent_repo = "The repository you're trying to add does not exist; please create it first."
15891593
teams.add_duplicate_users = User is already a team member.
15901594
teams.repos.none = No repositories could be accessed by this team.

public/js/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,7 @@ $(document).ready(function () {
22632263

22642264
// Helpers.
22652265
$('.delete-button').click(showDeletePopup);
2266+
$('.add-all-button').click(showAddAllPopup);
22662267

22672268
$('.delete-branch-button').click(showDeletePopup);
22682269

@@ -2501,6 +2502,35 @@ function showDeletePopup() {
25012502
return false;
25022503
}
25032504

2505+
function showAddAllPopup() {
2506+
const $this = $(this);
2507+
let filter = "";
2508+
if ($this.attr("id")) {
2509+
filter += "#" + $this.attr("id")
2510+
}
2511+
2512+
const dialog = $('.addall.modal' + filter);
2513+
dialog.find('.name').text($this.data('name'));
2514+
2515+
dialog.modal({
2516+
closable: false,
2517+
onApprove: function() {
2518+
if ($this.data('type') == "form") {
2519+
$($this.data('form')).submit();
2520+
return;
2521+
}
2522+
2523+
$.post($this.data('url'), {
2524+
"_csrf": csrf,
2525+
"id": $this.data("id")
2526+
}).done(function(data) {
2527+
window.location.href = data.redirect;
2528+
});
2529+
}
2530+
}).modal('show');
2531+
return false;
2532+
}
2533+
25042534
function initVueComponents(){
25052535
const vueDelimeters = ['${', '}'];
25062536

routers/org/teams.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,21 @@ func TeamsRepoAction(ctx *context.Context) {
155155
err = ctx.Org.Team.AddRepository(repo)
156156
case "remove":
157157
err = ctx.Org.Team.RemoveRepository(com.StrTo(ctx.Query("repoid")).MustInt64())
158+
case "addall":
159+
err = ctx.Org.Team.AddAllRepositories()
160+
case "removeall":
161+
err = ctx.Org.Team.RemoveAllRepositories()
158162
}
159163

160164
if err != nil {
161165
log.Error("Action(%s): '%s' %v", ctx.Params(":action"), ctx.Org.Team.Name, err)
162166
ctx.ServerError("TeamsRepoAction", err)
163167
return
164168
}
169+
170+
ctx.JSON(200, map[string]interface{}{
171+
"redirect": ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories",
172+
})
165173
ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories")
166174
}
167175

templates/org/team/repositories.tmpl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
</div>
2222
<button class="ui green button">{{.i18n.Tr "org.teams.add_team_repository"}}</button>
2323
</form>
24+
<div class="ui divider"></div>
25+
<form class="ui form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/repositories" method="post">
26+
{{.CsrfTokenHtml}}
27+
<button class="ui green small button add-all-button" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/addall">Add all organization repositories</button>
28+
<button class="ui red small button delete-button" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/removeall">Remove all team repositories</button>
29+
</form>
2430
</div>
2531
{{end}}
2632
<div class="ui bottom attached table segment repositories">
@@ -44,4 +50,27 @@
4450
</div>
4551
</div>
4652
</div>
53+
54+
<div class="ui small basic delete modal">
55+
<div class="ui icon header">
56+
<i class="trash icon"></i>
57+
{{.i18n.Tr "org.teams.remove_all_repos_title"}}
58+
</div>
59+
<div class="content">
60+
<p>{{.i18n.Tr "org.teams.remove_all_repos_desc"}}</p>
61+
</div>
62+
{{template "base/delete_modal_actions" .}}
63+
</div>
64+
65+
<div class="ui small basic addall modal">
66+
<div class="ui icon header">
67+
<i class="globe icon"></i>
68+
{{.i18n.Tr "org.teams.add_all_repos_title"}}
69+
</div>
70+
<div class="content">
71+
<p>{{.i18n.Tr "org.teams.add_all_repos_desc"}}</p>
72+
</div>
73+
{{template "base/delete_modal_actions" .}}
74+
</div>
75+
4776
{{template "base/footer" .}}

0 commit comments

Comments
 (0)