mirror of https://github.com/zulip/zulip.git
corporate: Add contact support page.
This commit is contained in:
parent
c750d0e404
commit
763b3c27d6
|
@ -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
|
|
@ -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))
|
||||||
|
|
|
@ -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 = [
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Support request for {{ realm_string_id }}
|
|
@ -0,0 +1,8 @@
|
||||||
|
Support URL: {{ support_url }}
|
||||||
|
|
||||||
|
Subject: {{ request_subject }}
|
||||||
|
|
||||||
|
Message:
|
||||||
|
{{ request_message }}
|
||||||
|
|
||||||
|
Requested by: {{ requested_by }} ({{ user_role }})
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue