mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	demo_request: Add form for user to request a demo.
This sends an email to us after user fills out and sends the form.
This commit is contained in:
		@@ -2344,6 +2344,37 @@ class StripeTest(StripeTestCase):
 | 
			
		||||
            response,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_demo_request(self) -> None:
 | 
			
		||||
        result = self.client_get("/request-demo/")
 | 
			
		||||
        self.assertEqual(result.status_code, 200)
 | 
			
		||||
        self.assert_in_success_response(["Request a demo"], result)
 | 
			
		||||
 | 
			
		||||
        data = {
 | 
			
		||||
            "full_name": "King Hamlet",
 | 
			
		||||
            "email": "test@zulip.com",
 | 
			
		||||
            "role": "Manager",
 | 
			
		||||
            "organization_name": "Zulip",
 | 
			
		||||
            "organization_type": "Business",
 | 
			
		||||
            "organization_website": "https://example.com",
 | 
			
		||||
            "expected_user_count": "10 (2 unpaid members)",
 | 
			
		||||
            "message": "Need help!",
 | 
			
		||||
        }
 | 
			
		||||
        result = self.client_post("/request-demo/", data)
 | 
			
		||||
        self.assert_in_success_response(["Thanks for contacting 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, "Demo request for Zulip")
 | 
			
		||||
            self.assertEqual(message.reply_to, ["test@zulip.com"])
 | 
			
		||||
            self.assertEqual(self.email_envelope_from(message), settings.NOREPLY_EMAIL_ADDRESS)
 | 
			
		||||
            self.assertIn("Zulip demo request <noreply-", self.email_display_from(message))
 | 
			
		||||
            self.assertIn("Full name: King Hamlet", message.body)
 | 
			
		||||
 | 
			
		||||
    def test_support_request(self) -> None:
 | 
			
		||||
        user = self.example_user("hamlet")
 | 
			
		||||
        self.assertIsNone(get_customer_by_realm(user.realm))
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ from corporate.views.sponsorship import (
 | 
			
		||||
    sponsorship,
 | 
			
		||||
    sponsorship_page,
 | 
			
		||||
)
 | 
			
		||||
from corporate.views.support import remote_servers_support, support, support_request
 | 
			
		||||
from corporate.views.support import demo_request, remote_servers_support, support, support_request
 | 
			
		||||
from corporate.views.upgrade import (
 | 
			
		||||
    remote_realm_upgrade,
 | 
			
		||||
    remote_realm_upgrade_page,
 | 
			
		||||
@@ -94,6 +94,7 @@ i18n_urlpatterns: Any = [
 | 
			
		||||
    path("sponsorship/", sponsorship_page, name="sponsorship_request"),
 | 
			
		||||
    path("upgrade/", upgrade_page, name="upgrade_page"),
 | 
			
		||||
    path("support/", support_request),
 | 
			
		||||
    path("request-demo/", demo_request),
 | 
			
		||||
    path("billing/event_status/", event_status_page, name="event_status_page"),
 | 
			
		||||
    path("stripe/webhook/", stripe_webhook, name="stripe_webhook"),
 | 
			
		||||
    # Server admin (user_profile.is_staff) visible stats pages
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,21 @@ class SupportRequestForm(forms.Form):
 | 
			
		||||
    request_message = forms.CharField(widget=forms.Textarea)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DemoRequestForm(forms.Form):
 | 
			
		||||
    MAX_INPUT_LENGTH = 50
 | 
			
		||||
    SORTED_ORG_TYPE_NAMES = sorted(
 | 
			
		||||
        ([org_type["name"] for org_type in Realm.ORG_TYPES.values() if not org_type["hidden"]]),
 | 
			
		||||
    )
 | 
			
		||||
    full_name = forms.CharField(max_length=MAX_INPUT_LENGTH)
 | 
			
		||||
    email = forms.EmailField()
 | 
			
		||||
    role = forms.CharField(max_length=MAX_INPUT_LENGTH)
 | 
			
		||||
    organization_name = forms.CharField(max_length=MAX_INPUT_LENGTH)
 | 
			
		||||
    organization_type = forms.CharField()
 | 
			
		||||
    organization_website = forms.URLField(required=True)
 | 
			
		||||
    expected_user_count = forms.CharField(max_length=MAX_INPUT_LENGTH)
 | 
			
		||||
    message = forms.CharField(widget=forms.Textarea)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@zulip_login_required
 | 
			
		||||
@has_request_variables
 | 
			
		||||
def support_request(request: HttpRequest) -> HttpResponse:
 | 
			
		||||
@@ -139,6 +154,47 @@ def support_request(request: HttpRequest) -> HttpResponse:
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@has_request_variables
 | 
			
		||||
def demo_request(request: HttpRequest) -> HttpResponse:
 | 
			
		||||
    context = {
 | 
			
		||||
        "MAX_INPUT_LENGTH": DemoRequestForm.MAX_INPUT_LENGTH,
 | 
			
		||||
        "SORTED_ORG_TYPE_NAMES": DemoRequestForm.SORTED_ORG_TYPE_NAMES,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if request.POST:
 | 
			
		||||
        post_data = request.POST.copy()
 | 
			
		||||
        form = DemoRequestForm(post_data)
 | 
			
		||||
 | 
			
		||||
        if form.is_valid():
 | 
			
		||||
            email_context = {
 | 
			
		||||
                "full_name": form.cleaned_data["full_name"],
 | 
			
		||||
                "email": form.cleaned_data["email"],
 | 
			
		||||
                "role": form.cleaned_data["role"],
 | 
			
		||||
                "organization_name": form.cleaned_data["organization_name"],
 | 
			
		||||
                "organization_type": form.cleaned_data["organization_type"],
 | 
			
		||||
                "organization_website": form.cleaned_data["organization_website"],
 | 
			
		||||
                "expected_user_count": form.cleaned_data["expected_user_count"],
 | 
			
		||||
                "message": form.cleaned_data["message"],
 | 
			
		||||
            }
 | 
			
		||||
            # Sent to the server's support team, so this email is not user-facing.
 | 
			
		||||
            send_email(
 | 
			
		||||
                "zerver/emails/demo_request",
 | 
			
		||||
                to_emails=[FromAddress.SUPPORT],
 | 
			
		||||
                from_name="Zulip demo request",
 | 
			
		||||
                from_address=FromAddress.tokenized_no_reply_address(),
 | 
			
		||||
                reply_to_email=email_context["email"],
 | 
			
		||||
                context=email_context,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            response = render(
 | 
			
		||||
                request, "corporate/support/support_request_thanks.html", context=context
 | 
			
		||||
            )
 | 
			
		||||
            return response
 | 
			
		||||
 | 
			
		||||
    response = render(request, "corporate/support/demo_request.html", context=context)
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_plan_type_string(plan_type: int) -> str:
 | 
			
		||||
    return {
 | 
			
		||||
        Realm.PLAN_TYPE_SELF_HOSTED: "Self-hosted",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								templates/corporate/support/demo_request.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								templates/corporate/support/demo_request.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
{% 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>Request a demo</h1>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <form method="post" class="white-box" id="registration">
 | 
			
		||||
            {{ csrf_input }}
 | 
			
		||||
 | 
			
		||||
            <fieldset class="support-request">
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="full_name" class="inline-block label-title">Full name</label>
 | 
			
		||||
                    <input class="required" type="text" name="full_name" maxlength="{{ MAX_INPUT_LENGTH }}" required />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="email" class="inline-block label-title">Email</label>
 | 
			
		||||
                    <input class="required" type="email" name="email" required />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="role" class="inline-block label-title">Your role</label>
 | 
			
		||||
                    <input class="required" type="text" name="role" maxlength="{{ MAX_INPUT_LENGTH }}" required />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="organization_name" class="inline-block label-title">Organization name</label>
 | 
			
		||||
                    <input class="required" type="text" name="organization_name" maxlength="{{ MAX_INPUT_LENGTH }}" required />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="organization_type" class="inline-block label-title">Organization type</label>
 | 
			
		||||
                    <select name="organization_type" class="required">
 | 
			
		||||
                        {% for org_type in SORTED_ORG_TYPE_NAMES %}
 | 
			
		||||
                            <option
 | 
			
		||||
                              value="{{ org_type }}">
 | 
			
		||||
                                {{ org_type }}
 | 
			
		||||
                            </option>
 | 
			
		||||
                        {% endfor %}
 | 
			
		||||
                    </select>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="organization_website" class="inline-block label-title">Organization website</label>
 | 
			
		||||
                    <input class="required" type="url" name="organization_website" required />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="expected_user_count" class="inline-block label-title">Expected number of users (approximate range)</label>
 | 
			
		||||
                    <input class="required" type="text" name="expected_user_count" maxlength="{{ MAX_INPUT_LENGTH }}" required />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="input-box support-form-field">
 | 
			
		||||
                    <label for="message" class="inline-block label-title">How can we help?</label>
 | 
			
		||||
                    <textarea name="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/loading/loader-white.svg') }}"></object>
 | 
			
		||||
                    </button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </fieldset>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
{% block portico_content %}
 | 
			
		||||
<div class="flex full-page thanks-page">
 | 
			
		||||
    <div class="center-block new-style">
 | 
			
		||||
    <div class="center-block new-style white-box">
 | 
			
		||||
        <h1>{{ _("Thanks for contacting us!") }}</h1>
 | 
			
		||||
        <p>{{ _("We will be in touch with you soon.") }}</p>
 | 
			
		||||
        <p>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								templates/zerver/emails/demo_request.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								templates/zerver/emails/demo_request.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
{% extends "zerver/emails/email_base_messages.html" %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<b>Subject</b>: Demo request for {{ organization_name }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Full name</b>: {{ full_name }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Email</b>: {{ email }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Role</b>: {{ role }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Organization type</b>: {{ organization_type }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Organization website</b>: {{ organization_website }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Expected user count</b>: {{ expected_user_count }}
 | 
			
		||||
<br />
 | 
			
		||||
<b>Message</b>: {{ message }}
 | 
			
		||||
<br />
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
							
								
								
									
										1
									
								
								templates/zerver/emails/demo_request.subject.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								templates/zerver/emails/demo_request.subject.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
Demo request for {{organization_name}}
 | 
			
		||||
							
								
								
									
										15
									
								
								templates/zerver/emails/demo_request.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								templates/zerver/emails/demo_request.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
Subject: Demo request for {{ organization_name }}
 | 
			
		||||
 | 
			
		||||
Full name: {{ full_name }}
 | 
			
		||||
 | 
			
		||||
Email: {{ email }}
 | 
			
		||||
 | 
			
		||||
Role: {{ role }}
 | 
			
		||||
 | 
			
		||||
Organization type: {{ organization_type }}
 | 
			
		||||
 | 
			
		||||
Organization website: {{ organization_website }}
 | 
			
		||||
 | 
			
		||||
Expected user count: {{ expected_user_count }}
 | 
			
		||||
 | 
			
		||||
Message: {{ message }}
 | 
			
		||||
@@ -527,6 +527,7 @@ html {
 | 
			
		||||
        input[type="email"],
 | 
			
		||||
        input[type="password"],
 | 
			
		||||
        input[type="number"],
 | 
			
		||||
        input[type="url"],
 | 
			
		||||
        textarea,
 | 
			
		||||
        select {
 | 
			
		||||
            padding: 10px 32px 10px 12px;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user