corporate: Add contact support page.

This commit is contained in:
Eeshan Garg 2021-09-29 13:51:55 -04:00 committed by Tim Abbott
parent c750d0e404
commit 763b3c27d6
13 changed files with 228 additions and 9 deletions

15
corporate/lib/support.py Normal file
View File

@ -0,0 +1,15 @@
from urllib.parse import urlencode, urljoin, urlunsplit
from django.conf import settings
from django.urls import reverse
from zerver.models import Realm, get_realm
def get_support_url(realm: Realm) -> str:
support_realm_uri = get_realm(settings.STAFF_SUBDOMAIN).uri
support_url = urljoin(
support_realm_uri,
urlunsplit(("", "", reverse("support"), urlencode({"q": realm.string_id}), "")),
)
return support_url

View File

@ -1487,6 +1487,41 @@ class StripeTest(StripeTestCase):
self.assert_json_success(response) self.assert_json_success(response)
def test_support_request(self) -> None:
user = self.example_user("hamlet")
self.assertIsNone(get_customer_by_realm(user.realm))
self.login_user(user)
result = self.client_get("/support/")
self.assertEqual(result.status_code, 200)
self.assert_in_success_response(["Contact support"], result)
data = {
"request_subject": "Not getting messages.",
"request_message": "Running into this weird issue.",
}
result = self.client_post("/support/", data)
self.assert_in_success_response(["Thanks for getting in touch with us!"], result)
from django.core.mail import outbox
self.assert_length(outbox, 1)
for message in outbox:
self.assert_length(message.to, 1)
self.assertEqual(message.to[0], "desdemona+admin@zulip.com")
self.assertEqual(message.subject, "Support request for zulip")
self.assertEqual(message.reply_to, ["hamlet@zulip.com"])
self.assertEqual(self.email_envelope_from(message), settings.NOREPLY_EMAIL_ADDRESS)
self.assertIn("Zulip Support <noreply-", self.email_display_from(message))
self.assertIn("Requested by: King Hamlet (Member)", message.body)
self.assertIn(
"Support URL: http://zulip.testserver/activity/support?q=zulip", message.body
)
self.assertIn("Subject: Not getting messages.", message.body)
self.assertIn("Message:\nRunning into this weird issue", message.body)
def test_request_sponsorship(self) -> None: def test_request_sponsorship(self) -> None:
user = self.example_user("hamlet") user = self.example_user("hamlet")
self.assertIsNone(get_customer_by_realm(user.realm)) self.assertIsNone(get_customer_by_realm(user.realm))

View File

@ -5,6 +5,7 @@ from django.urls import path
from django.views.generic import TemplateView from django.views.generic import TemplateView
from corporate.views.billing_page import billing_home, replace_payment_source, update_plan from corporate.views.billing_page import billing_home, replace_payment_source, update_plan
from corporate.views.support import support_request
from corporate.views.upgrade import initial_upgrade, sponsorship, upgrade from corporate.views.upgrade import initial_upgrade, sponsorship, upgrade
from zerver.lib.rest import rest_path from zerver.lib.rest import rest_path
@ -16,6 +17,7 @@ i18n_urlpatterns: Any = [
# Billing # Billing
path("billing/", billing_home), path("billing/", billing_home),
path("upgrade/", initial_upgrade, name="initial_upgrade"), path("upgrade/", initial_upgrade, name="initial_upgrade"),
path("support/", support_request),
] ]
v1_api_and_json_patterns = [ v1_api_and_json_patterns = [

View File

@ -0,0 +1,58 @@
from django import forms
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from corporate.lib.support import get_support_url
from zerver.decorator import zulip_login_required
from zerver.lib.request import has_request_variables
from zerver.lib.send_email import FromAddress, send_email
class SupportRequestForm(forms.Form):
# We use the same subject length requirement as GitHub's
# contact support form.
MAX_SUBJECT_LENGTH = 50
request_subject = forms.CharField(max_length=MAX_SUBJECT_LENGTH)
request_message = forms.CharField(widget=forms.Textarea)
@zulip_login_required
@has_request_variables
def support_request(request: HttpRequest) -> HttpResponse:
user = request.user
assert user.is_authenticated
context = {
"email": user.delivery_email,
"realm_name": user.realm.name,
"MAX_SUBJECT_LENGTH": SupportRequestForm.MAX_SUBJECT_LENGTH,
}
if request.POST:
post_data = request.POST.copy()
form = SupportRequestForm(post_data)
if form.is_valid():
email_context = {
"requested_by": user.full_name,
"realm_string_id": user.realm.string_id,
"request_subject": form.cleaned_data["request_subject"],
"request_message": form.cleaned_data["request_message"],
"support_url": get_support_url(user.realm),
"user_role": user.get_role_name(),
}
send_email(
"zerver/emails/support_request",
to_emails=[FromAddress.SUPPORT],
from_name="Zulip Support",
from_address=FromAddress.tokenized_no_reply_address(),
reply_to_email=user.delivery_email,
context=email_context,
)
response = render(request, "corporate/support_request_thanks.html", context=context)
return response
response = render(request, "corporate/support_request.html", context=context)
return response

View File

@ -1,7 +1,6 @@
import logging import logging
from decimal import Decimal from decimal import Decimal
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from urllib.parse import urlencode, urljoin, urlunsplit
from django import forms from django import forms
from django.conf import settings from django.conf import settings
@ -24,6 +23,7 @@ from corporate.lib.stripe import (
update_sponsorship_status, update_sponsorship_status,
validate_licenses, validate_licenses,
) )
from corporate.lib.support import get_support_url
from corporate.models import ( from corporate.models import (
CustomerPlan, CustomerPlan,
ZulipSponsorshipRequest, ZulipSponsorshipRequest,
@ -37,7 +37,7 @@ from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success from zerver.lib.response import json_success
from zerver.lib.send_email import FromAddress, send_email from zerver.lib.send_email import FromAddress, send_email
from zerver.lib.validator import check_bool, check_int, check_string_in from zerver.lib.validator import check_bool, check_int, check_string_in
from zerver.models import Realm, UserProfile, get_org_type_display_name, get_realm from zerver.models import Realm, UserProfile, get_org_type_display_name
billing_logger = logging.getLogger("corporate.stripe") billing_logger = logging.getLogger("corporate.stripe")
@ -221,12 +221,7 @@ def sponsorship(
requested_by = user.full_name requested_by = user.full_name
user_role = user.get_role_name() user_role = user.get_role_name()
support_url = get_support_url(realm)
support_realm_uri = get_realm(settings.STAFF_SUBDOMAIN).uri
support_url = urljoin(
support_realm_uri,
urlunsplit(("", "", reverse("support"), urlencode({"q": realm.string_id}), "")),
)
post_data = request.POST.copy() post_data = request.POST.copy()
# We need to do this because the field name in the template # We need to do this because the field name in the template

View File

@ -286,6 +286,10 @@ html {
text-align: center; text-align: center;
} }
.thanks-page div {
text-align: center;
}
.lead { .lead {
font-weight: bold; font-weight: bold;
} }

View File

@ -417,6 +417,7 @@ html {
input[type="text"], input[type="text"],
input[type="email"], input[type="email"],
input[type="password"], input[type="password"],
textarea,
select { select {
padding: 10px 32px 10px 12px; padding: 10px 32px 10px 12px;
margin: 25px 0 5px; margin: 25px 0 5px;
@ -815,6 +816,16 @@ button#register_auth_button_gitlab {
margin-left: 2px; margin-left: 2px;
} }
} }
&.support-form-field {
width: 450px;
input,
textarea {
width: 400px;
font-size: 1rem;
}
}
} }
& [for="realm_in_root_domain"] { & [for="realm_in_root_domain"] {
@ -831,6 +842,12 @@ button#register_auth_button_gitlab {
border-radius: 4px; border-radius: 4px;
} }
.support-submit-button {
margin-top: 20px;
margin-bottom: 5px;
width: 450px;
}
.register-button .loader { .register-button .loader {
display: none; display: none;
vertical-align: top; vertical-align: top;
@ -868,7 +885,9 @@ button#register_auth_button_gitlab {
} }
} }
#id_email { #id_email,
#support_from,
#support_realm {
font-weight: normal; font-weight: normal;
margin: 2px; margin: 2px;
padding-top: 25px; padding-top: 25px;

View File

@ -0,0 +1,43 @@
{% extends "zerver/portico_signup.html" %}
{% block portico_content %}
<div class="register-account flex full-page">
<div class="center-block new-style">
<div class="pitch">
<h1>{{ _('Contact support') }}</h1>
</div>
<form method="post" class="form-horizontal white-box" id="registration">
{{ csrf_input }}
<fieldset class="support-request">
<div class="input-box no-validation support-form-field">
<label for="support_from" class="inline-block label-title">{{ _('From') }}</label>
<div id="support_from">{{ email }}</div>
</div>
<div class="input-box no-validation support-form-field">
<label for="support_realm" class="inline-block label-title">{{ _('Organization') }}</label>
<div id="support_realm">{{ realm_name }}</div>
</div>
<div class="input-box support-form-field">
<label for="request_subject" class="inline-block label-title">{{ _('Subject') }}</label>
<input id="request_subject" class="required" type="text" name="request_subject" maxlength="{{ MAX_SUBJECT_LENGTH }}" required />
</div>
<div class="input-box support-form-field">
<label for="request_message" class="inline-block label-title">{{ _('Message') }}</label>
<textarea id="request_message" name="request_message" cols="100" rows="5" required></textarea>
</div>
<div class="register-button-box">
<button class="register-button support-submit-button" type="submit">
<span>{{ _('Submit') }}</span>
<object class="loader" type="image/svg+xml" data="/static/images/loader-white.svg"></object>
</button>
</div>
</fieldset>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends "zerver/portico.html" %}
{% block portico_content %}
<div class="flex full-page thanks-page">
<div class="center-block new-style">
<h1>Thanks for contacting us!</h1>
<p>We will be in touch with you soon.</p>
<p>
You can find answers to frequently asked questions in the
<a href="/help/">Zulip help center</a>.
</p>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends "zerver/emails/email_base_messages.html" %}
{% block content %}
<b>Support URL</b>: <a href="{{ support_url }}">{{ support_url }}</a>
<br /><br />
<b>Subject</b>: {{ request_subject }}
<br /><br />
<b>Message</b>:
<br />
{{ request_message }}
<br /><br />
<b>Requested by</b>: {{ requested_by }} ({{ user_role }})
{% endblock %}

View File

@ -0,0 +1 @@
Support request for {{ realm_string_id }}

View File

@ -0,0 +1,8 @@
Support URL: {{ support_url }}
Subject: {{ request_subject }}
Message:
{{ request_message }}
Requested by: {{ requested_by }} ({{ user_role }})

View File

@ -547,6 +547,9 @@ html_rules: List["Rule"] = [
"templates/zerver/email.html", "templates/zerver/email.html",
"zerver/tests/fixtures/email", "zerver/tests/fixtures/email",
"templates/zerver/for-companies.html", "templates/zerver/for-companies.html",
"templates/corporate/support_request.html",
"templates/corporate/support_request_thanks.html",
"templates/zerver/emails/support_request.html",
}, },
"exclude_pattern": "email subject", "exclude_pattern": "email subject",
"description": "avoid subject in templates", "description": "avoid subject in templates",