From 82874e6e6b7a1755ad742c0bbcafe2eb6b0d75a4 Mon Sep 17 00:00:00 2001 From: Jacob Wegner Date: Tue, 1 Mar 2016 09:52:55 -0600 Subject: [PATCH 1/2] add TeamManageView and TeamInviteView CBVs --- pinax/teams/views.py | 132 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 2 deletions(-) diff --git a/pinax/teams/views.py b/pinax/teams/views.py index f94df8f..dc4a118 100644 --- a/pinax/teams/views.py +++ b/pinax/teams/views.py @@ -1,12 +1,13 @@ import json -from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden +from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse from django.shortcuts import render, redirect, get_object_or_404 from django.template import RequestContext from django.template.loader import render_to_string +from django.utils.decorators import method_decorator from django.views.decorators.http import require_POST from django.views.generic.edit import CreateView -from django.views.generic import ListView +from django.views.generic import ListView, FormView, TemplateView from django.contrib import messages from django.contrib.auth import get_user_model @@ -95,6 +96,32 @@ def team_detail(request): }) +class TeamManageView(TemplateView): + + template_name = "teams/team_manage.html" + + @method_decorator(manager_required) + def dispatch(self, *args, **kwargs): + self.team = self.request.team + self.role = self.team.role_for(self.request.user) + return super(TeamManageView, self).dispatch(*args, **kwargs) + + def get_context_data(self, **kwargs): + ctx = super(TeamManageView, self).get_context_data(**kwargs) + ctx.update({ + "team": self.team, + "role": self.role, + "invite_form": self.get_team_invite_form(), + "can_join": self.team.can_join(self.request.user), + "can_leave": self.team.can_leave(self.request.user), + "can_apply": self.team.can_apply(self.request.user), + }) + return ctx + + def get_team_invite_form(self): + return TeamInviteUserForm(team=self.team) + + @team_required @login_required def team_manage(request): @@ -188,6 +215,107 @@ def team_reject(request, pk): return redirect("team_detail", slug=membership.team.slug) +class TeamInviteView(FormView): + http_method_names = ["post"] + form_class = TeamInviteUserForm + + @method_decorator(manager_required) + def dispatch(self, *args, **kwargs): + self.team = self.request.team + return super(TeamInviteView, self).dispatch(*args, **kwargs) + + def get_form_kwargs(self): + form_kwargs = super(TeamInviteView, self).get_form_kwargs() + form_kwargs.update({"team": self.team}) + return form_kwargs + + def get_unbound_form(self): + """ + Overrides behavior of FormView.get_form_kwargs + when method is POST or PUT + """ + form_kwargs = self.get_form_kwargs() + # @@@ remove fields that would cause the form to be bound + # when instantiated + bound_fields = ["data", "files"] + for field in bound_fields: + form_kwargs.pop(field, None) + return self.get_form_class()(**form_kwargs) + + def after_membership_added(self, form): + """ + Allows the developer to customize actions that happen after a membership + was added in form_valid + """ + pass + + def get_form_success_data(self, form): + """ + Allows customization of the JSON data returned when a valid form submission occurs. + """ + data = { + "html": render_to_string( + "teams/_invite_form.html", + { + "invite_form": self.get_unbound_form(), + "team": self.team + }, + context_instance=RequestContext(self.request) + ) + } + + membership = self.membership + if membership is not None: + if membership.state == Membership.STATE_APPLIED: + fragment_class = ".applicants" + elif membership.state == Membership.STATE_INVITED: + fragment_class = ".invitees" + elif membership.state in (Membership.STATE_AUTO_JOINED, Membership.STATE_ACCEPTED): + fragment_class = { + Membership.ROLE_OWNER: ".owners", + Membership.ROLE_MANAGER: ".managers", + Membership.ROLE_MEMBER: ".members" + }[membership.role] + data.update({ + "append-fragments": { + fragment_class: render_to_string( + "teams/_membership.html", + { + "membership": membership, + "team": self.team + }, + context_instance=RequestContext(self.request) + ) + } + }) + return data + + def form_valid(self, form): + user_or_email = form.cleaned_data["invitee"] + role = form.cleaned_data["role"] + if isinstance(user_or_email, string_types): + self.membership = self.team.invite_user(self.request.user, user_or_email, role) + else: + self.membership = self.team.add_user(user_or_email, role, by=self.request.user) + + self.after_membership_added(form) + + data = self.get_form_success_data(form) + return self.render_to_response(data) + + def form_invalid(self, form): + data = { + "html": render_to_string("teams/_invite_form.html", { + "invite_form": form, + "team": self.team + }, context_instance=RequestContext(self.request)) + } + return self.render_to_response(data) + + def render_to_response(self, context, **response_kwargs): + return JsonResponse(context) + + @team_required @login_required @require_POST From 2b9b017d2434abd0ece48b38dca554d40529cfce Mon Sep 17 00:00:00 2001 From: Jacob Wegner Date: Thu, 10 Mar 2016 09:14:37 -0600 Subject: [PATCH 2/2] swap out team_manage and team_invite FBVs for equivalent CBVs --- pinax/teams/urls.py | 4 +-- pinax/teams/views.py | 79 -------------------------------------------- 2 files changed, 2 insertions(+), 81 deletions(-) diff --git a/pinax/teams/urls.py b/pinax/teams/urls.py index 4e80848..2b6b724 100644 --- a/pinax/teams/urls.py +++ b/pinax/teams/urls.py @@ -14,11 +14,11 @@ url(r"^(?P[\w\-]+)/leave/$", views.team_leave, name="team_leave"), url(r"^(?P[\w\-]+)/apply/$", views.team_apply, name="team_apply"), url(r"^(?P[\w\-]+)/edit/$", views.team_update, name="team_edit"), - url(r"^(?P[\w\-]+)/manage/$", views.team_manage, name="team_manage"), + url(r"^(?P[\w\-]+)/manage/$", views.TeamManageView.as_view(), name="team_manage"), # membership specific url(r"^(?P[\w\-]+)/ac/users-to-invite/$", views.autocomplete_users, name="team_autocomplete_users"), # noqa - url(r"^(?P[\w\-]+)/invite-user/$", views.team_invite, name="team_invite"), + url(r"^(?P[\w\-]+)/invite-user/$", views.TeamInviteView.as_view(), name="team_invite"), url(r"^(?P[\w\-]+)/members/(?P\d+)/revoke-invite/$", views.team_member_revoke_invite, name="team_member_revoke_invite"), # noqa url(r"^(?P[\w\-]+)/members/(?P\d+)/resend-invite/$", views.team_member_resend_invite, name="team_member_resend_invite"), # noqa url(r"^(?P[\w\-]+)/members/(?P\d+)/promote/$", views.team_member_promote, name="team_member_promote"), # noqa diff --git a/pinax/teams/views.py b/pinax/teams/views.py index dc4a118..141c6de 100644 --- a/pinax/teams/views.py +++ b/pinax/teams/views.py @@ -122,27 +122,6 @@ def get_team_invite_form(self): return TeamInviteUserForm(team=self.team) -@team_required -@login_required -def team_manage(request): - team = request.team - state = team.state_for(request.user) - role = team.role_for(request.user) - if team.manager_access == Team.MEMBER_ACCESS_INVITATION and \ - state is None and not request.user.is_staff: - raise Http404() - - return render(request, "teams/team_manage.html", { - "team": team, - "state": state, - "role": role, - "invite_form": TeamInviteUserForm(team=team), - "can_join": team.can_join(request.user), - "can_leave": team.can_leave(request.user), - "can_apply": team.can_apply(request.user), - }) - - @team_required @login_required def team_join(request): @@ -316,64 +295,6 @@ def render_to_response(self, context, **response_kwargs): return JsonResponse(context) -@team_required -@login_required -@require_POST -def team_invite(request): - team = request.team - role = team.role_for(request.user) - if role not in [Membership.ROLE_MANAGER, Membership.ROLE_OWNER]: - raise Http404() - form = TeamInviteUserForm(request.POST, team=team) - if form.is_valid(): - user_or_email = form.cleaned_data["invitee"] - role = form.cleaned_data["role"] - if isinstance(user_or_email, string_types): - membership = team.invite_user(request.user, user_or_email, role) - else: - membership = team.add_user(user_or_email, role) - data = { - "html": render_to_string( - "teams/_invite_form.html", - { - "invite_form": TeamInviteUserForm(team=team), - "team": team - }, - context_instance=RequestContext(request) - ) - } - if membership is not None: - if membership.state == Membership.STATE_APPLIED: - fragment_class = ".applicants" - elif membership.state == Membership.STATE_INVITED: - fragment_class = ".invitees" - elif membership.state in (Membership.STATE_AUTO_JOINED, Membership.STATE_ACCEPTED): - fragment_class = { - Membership.ROLE_OWNER: ".owners", - Membership.ROLE_MANAGER: ".managers", - Membership.ROLE_MEMBER: ".members" - }[membership.role] - data.update({ - "append-fragments": { - fragment_class: render_to_string( - "teams/_membership.html", - { - "membership": membership - }, - context_instance=RequestContext(request) - ) - } - }) - else: - data = { - "html": render_to_string("teams/_invite_form.html", { - "invite_form": form, - "team": team - }, context_instance=RequestContext(request)) - } - return HttpResponse(json.dumps(data), content_type="application/json") - - @manager_required @require_POST def team_member_revoke_invite(request, pk):