Allow team owners to add members.
parent
1daf8c2975
commit
3a28eacda5
File diff suppressed because one or more lines are too long
|
@ -3092,8 +3092,32 @@ div.team-controller {
|
|||
width: 50%;
|
||||
}
|
||||
ul {
|
||||
margin-bottom: 0;
|
||||
margin-top: 10px;
|
||||
margin: 12px 0 0 0;
|
||||
|
||||
li {
|
||||
box-sizing: border-box;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
width: 42%;
|
||||
@include border-radius(3px);
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
}
|
||||
a.btn {
|
||||
float: right;
|
||||
}
|
||||
img {
|
||||
margin-right: 10px;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
&:hover {
|
||||
background: #ebebeb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ if (typeof angular !== 'undefined') {
|
|||
// Services.
|
||||
app.factory('TeamStorage', function($http, $q) {
|
||||
return {
|
||||
searchMembers: function(query) {
|
||||
searchUsers: function(query) {
|
||||
var promise = $http({
|
||||
method: 'GET',
|
||||
url: '/api/public/user/?format=json&username__contains=' + query
|
||||
url: '/api/public/user/?format=json&limit=100&username__contains=' + query
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
@ -22,17 +22,17 @@ if (typeof angular !== 'undefined') {
|
|||
|
||||
// Controllers.
|
||||
controllers.TeamController = function($scope, $timeout, TeamStorage) {
|
||||
$scope.members = [];
|
||||
$scope.users = [];
|
||||
$scope.$watch('search', function(val) {
|
||||
$timeout.cancel($scope.timeout);
|
||||
|
||||
if (!val) return $scope.members = [];
|
||||
if (!val) return $scope.users = [];
|
||||
|
||||
$scope.timeout = $timeout(function() {
|
||||
TeamStorage.searchMembers(val).then(function(response) {
|
||||
$scope.members = response.data.objects;
|
||||
TeamStorage.searchUsers(val).then(function(response) {
|
||||
$scope.users = response.data.objects;
|
||||
});
|
||||
}, 250);
|
||||
}, 350);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -38,14 +38,20 @@
|
|||
type="search"
|
||||
value=""
|
||||
/>
|
||||
<ul ng-cloak ng-if="members.length">
|
||||
<li ng-repeat="member in members">{[{ member.username }]}</li>
|
||||
<ul ng-cloak ng-if="users.length">
|
||||
<li ng-repeat="user in users">
|
||||
<img src="https://secure.gravatar.com/avatar/{[{ user.email_md5 }]}?s=26" />
|
||||
<span>{[{ user.username }]}</span>
|
||||
<a class="btn btn-small" href="/{{ team.slug }}/members/add/{[{ user.username }]}/">Add »</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="def" data-title="Members ({{ team.members.all|length }} of {{ team.member_limit }})">
|
||||
<ul style="margin-bottom: 0">
|
||||
{% for member in team.members.all %}
|
||||
<li>{{ member }}</li>
|
||||
<li>
|
||||
{{ member }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,9 @@ urlpatterns = \
|
|||
patterns('',
|
||||
url(r'^for-teams/$', views.for_teams),
|
||||
url(r'^for-teams/complete/$', views.for_teams_complete),
|
||||
url(r'^(?P<username>[^/]+)/members/add/(?P<member>[^/]+)/$',
|
||||
views.add_team_member,
|
||||
name='add-team-member'),
|
||||
url(r'^(?P<username>[^/]+)/members/$',
|
||||
views.team_members,
|
||||
name='team-members'),
|
||||
|
|
|
@ -37,6 +37,19 @@ def team_members(request, username):
|
|||
}
|
||||
|
||||
|
||||
def add_team_member(request, username, member):
|
||||
team = get_object_or_404(Team, slug=username)
|
||||
user = get_object_or_404(User, username=member)
|
||||
|
||||
if (team.owner != request.user):
|
||||
raise Http404
|
||||
|
||||
team.members.add(user)
|
||||
team.save()
|
||||
|
||||
return HttpResponseRedirect('/' + team.slug + '/members/')
|
||||
|
||||
|
||||
@render_to('teams/for-teams-complete.html')
|
||||
def for_teams_complete(request):
|
||||
if request.method == 'POST' and request.user.is_authenticated():
|
||||
|
|
Loading…
Reference in New Issue