sponsorship: Add extra input fields to get more org info.

Fixes #27600
This commit is contained in:
Aman Agrawal 2023-11-11 15:15:33 +00:00 committed by Tim Abbott
parent bf53c70dd9
commit 395cafcf46
7 changed files with 103 additions and 10 deletions

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2.6 on 2023-11-11 14:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0018_customer_cloud_xor_self_hosted"),
]
operations = [
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="expected_total_users",
field=models.TextField(default=""),
),
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="paid_users_count",
field=models.TextField(default=""),
),
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="paid_users_description",
field=models.TextField(default=""),
),
]

View File

@ -360,3 +360,6 @@ class ZulipSponsorshipRequest(models.Model):
org_website = models.URLField(max_length=MAX_ORG_URL_LENGTH, blank=True, null=True) org_website = models.URLField(max_length=MAX_ORG_URL_LENGTH, blank=True, null=True)
org_description = models.TextField(default="") org_description = models.TextField(default="")
expected_total_users = models.TextField(default="")
paid_users_count = models.TextField(default="")
paid_users_description = models.TextField(default="")

View File

@ -2159,6 +2159,9 @@ class StripeTest(StripeTestCase):
"organization-type": Realm.ORG_TYPES["opensource"]["id"], "organization-type": Realm.ORG_TYPES["opensource"]["id"],
"website": "invalid-url", "website": "invalid-url",
"description": "Infinispan is a distributed in-memory key/value data store with optional schema.", "description": "Infinispan is a distributed in-memory key/value data store with optional schema.",
"expected_total_users": "10 users",
"paid_users_count": "1 user",
"paid_users_description": "We have 1 paid user.",
} }
response = self.client_post("/json/billing/sponsorship", data) response = self.client_post("/json/billing/sponsorship", data)
@ -2172,6 +2175,9 @@ class StripeTest(StripeTestCase):
"organization-type": Realm.ORG_TYPES["opensource"]["id"], "organization-type": Realm.ORG_TYPES["opensource"]["id"],
"website": "", "website": "",
"description": "Infinispan is a distributed in-memory key/value data store with optional schema.", "description": "Infinispan is a distributed in-memory key/value data store with optional schema.",
"expected_total_users": "10 users",
"paid_users_count": "1 user",
"paid_users_description": "We have 1 paid user.",
} }
response = self.client_post("/json/billing/sponsorship", data) response = self.client_post("/json/billing/sponsorship", data)
@ -2223,6 +2229,9 @@ class StripeTest(StripeTestCase):
"organization-type": Realm.ORG_TYPES["opensource"]["id"], "organization-type": Realm.ORG_TYPES["opensource"]["id"],
"website": "https://infinispan.org/", "website": "https://infinispan.org/",
"description": "Infinispan is a distributed in-memory key/value data store with optional schema.", "description": "Infinispan is a distributed in-memory key/value data store with optional schema.",
"expected_total_users": "10 users",
"paid_users_count": "1 user",
"paid_users_description": "We have 1 paid user.",
} }
response = self.client_post("/json/billing/sponsorship", data) response = self.client_post("/json/billing/sponsorship", data)
self.assert_json_success(response) self.assert_json_success(response)

View File

@ -233,6 +233,9 @@ class SponsorshipRequestForm(forms.Form):
website = forms.URLField(max_length=ZulipSponsorshipRequest.MAX_ORG_URL_LENGTH, required=False) website = forms.URLField(max_length=ZulipSponsorshipRequest.MAX_ORG_URL_LENGTH, required=False)
organization_type = forms.IntegerField() organization_type = forms.IntegerField()
description = forms.CharField(widget=forms.Textarea) description = forms.CharField(widget=forms.Textarea)
expected_total_users = forms.CharField(widget=forms.Textarea)
paid_users_count = forms.CharField(widget=forms.Textarea)
paid_users_description = forms.CharField(widget=forms.Textarea, required=False)
@require_organization_member @require_organization_member
@ -243,6 +246,9 @@ def sponsorship(
organization_type: str = REQ("organization-type"), organization_type: str = REQ("organization-type"),
website: str = REQ(), website: str = REQ(),
description: str = REQ(), description: str = REQ(),
expected_total_users: str = REQ(),
paid_users_count: str = REQ(),
paid_users_description: str = REQ(),
) -> HttpResponse: ) -> HttpResponse:
realm = user.realm realm = user.realm
billing_session = RealmBillingSession(user) billing_session = RealmBillingSession(user)
@ -266,6 +272,9 @@ def sponsorship(
org_website=form.cleaned_data["website"], org_website=form.cleaned_data["website"],
org_description=form.cleaned_data["description"], org_description=form.cleaned_data["description"],
org_type=form.cleaned_data["organization_type"], org_type=form.cleaned_data["organization_type"],
expected_total_users=form.cleaned_data["expected_total_users"],
paid_users_count=form.cleaned_data["paid_users_count"],
paid_users_description=form.cleaned_data["paid_users_description"],
) )
sponsorship_request.save() sponsorship_request.save()
@ -287,6 +296,9 @@ def sponsorship(
"organization_type": org_type_display_name, "organization_type": org_type_display_name,
"website": website, "website": website,
"description": description, "description": description,
"expected_total_users": expected_total_users,
"paid_users_count": paid_users_count,
"paid_users_description": paid_users_description,
} }
send_email( send_email(
"zerver/emails/sponsorship_request", "zerver/emails/sponsorship_request",

View File

@ -66,17 +66,35 @@
</div> </div>
<label for="organization-type" class="inline-block label-title">Organization type</label> <label for="organization-type" class="inline-block label-title">Organization type</label>
</div> </div>
<p id="sponsorship-discount-details"></p>
<div class="input-box sponsorship-form-field no-validation"> <div class="input-box sponsorship-form-field no-validation">
<label for="org-website" class="inline-block label-title">Organization website</label> <label for="org-website" class="inline-block
<input id="org-website" name="website" type="text" placeholder="Leave blank if this organization does not have a website."/> label-title">Organization website (if any)</label>
<input id="org-website" name="website" type="text"/>
<div id="sponsorship-org-website-error" class="alert alert-danger sponsorship-field-error"></div> <div id="sponsorship-org-website-error" class="alert alert-danger sponsorship-field-error"></div>
</div> </div>
<div class="input-box sponsorship-form-field"> <div class="input-box sponsorship-form-field">
<label for="description" class="inline-block label-title">Describe this organization</label> <label for="description" class="inline-block
label-title">Description of your organization</label>
<textarea id="description" name="description" cols="100" rows="5"></textarea> <textarea id="description" name="description" cols="100" rows="5"></textarea>
<div id="sponsorship-description-error" class="alert alert-danger sponsorship-field-error"></div> <div id="sponsorship-description-error" class="alert alert-danger sponsorship-field-error"></div>
</div> </div>
<p id="sponsorship-discount-details"></p> <div class="input-box sponsorship-form-field">
<label for="expected-total-users" class="inline-block label-title">Expected number of users (approximate range)</label>
<input id="expected-total-users" name="expected_total_users" type="text" />
<div id="sponsorship-expected-total-users-error" class="alert alert-danger sponsorship-field-error"></div>
</div>
<div class="input-box sponsorship-form-field no-validation">
<label for="paid-users-count" class="inline-block label-title">How many paid staff does your organization have?</label>
<input id="paid-users-count" name="paid_users_count" type="text"/>
<div id="sponsorship-paid-users-count-error" class="alert alert-danger sponsorship-field-error"></div>
</div>
<div class="input-box sponsorship-form-field">
<label for="paid-users-description" class="inline-block
label-title">Description of paid staff (if any)</label>
<textarea id="paid-users-description" name="paid_users_description" cols="100" rows="2"></textarea>
<div id="sponsorship-paid-users-description-error" class="alert alert-danger sponsorship-field-error"></div>
</div>
<!-- Disabled buttons do not fire any events, so we need a container div that isn't disabled for tippyjs to work --> <!-- Disabled buttons do not fire any events, so we need a container div that isn't disabled for tippyjs to work -->
<div class="upgrade-button-container" {% if is_demo_organization %}data-tippy-content="Convert demo organization before upgrading."{% endif %}> <div class="upgrade-button-container" {% if is_demo_organization %}data-tippy-content="Convert demo organization before upgrading."{% endif %}>
<button type="submit" id="sponsorship-button" class="stripe-button-el invoice-button" {% if is_demo_organization %}disabled{% endif %}> <button type="submit" id="sponsorship-button" class="stripe-button-el invoice-button" {% if is_demo_organization %}disabled{% endif %}>

View File

@ -14,6 +14,30 @@ function hide_submit_loading_indicator(): void {
$("#sponsorship-button .sponsorship-button-text").show(); $("#sponsorship-button .sponsorship-button-text").show();
} }
function validate_data(data: helpers.FormDataObject): boolean {
let found_error = false;
if (data.description.trim() === "") {
$("#sponsorship-description-error").text("Organization description cannot be blank.");
hide_submit_loading_indicator();
found_error = true;
}
if (data.paid_users_count.trim() === "") {
$("#sponsorship-paid-users-count-error").text("Number of paid staff cannot be blank.");
hide_submit_loading_indicator();
found_error = true;
}
if (data.expected_total_users.trim() === "") {
$("#sponsorship-expected-total-users-error").text(
"Expected number of users cannot be blank.",
);
hide_submit_loading_indicator();
found_error = true;
}
return !found_error;
}
function create_ajax_request(): void { function create_ajax_request(): void {
show_submit_loading_indicator(); show_submit_loading_indicator();
const $form = $("#sponsorship-form"); const $form = $("#sponsorship-form");
@ -25,10 +49,7 @@ function create_ajax_request(): void {
// Clear any previous error messages. // Clear any previous error messages.
$(".sponsorship-field-error").text(""); $(".sponsorship-field-error").text("");
if (!validate_data(data)) {
if (data.description.trim() === "") {
$("#sponsorship-description-error").text("Organization description cannot be blank.");
hide_submit_loading_indicator();
return; return;
} }
@ -62,7 +83,10 @@ export function initialize(): void {
}); });
function update_discount_details(): void { function update_discount_details(): void {
const selected_org_type = $<HTMLSelectElement>("#organization-type").find(":selected").attr("data-string-value") ?? ""; const selected_org_type =
$<HTMLSelectElement>("#organization-type")
.find(":selected")
.attr("data-string-value") ?? "";
helpers.update_discount_details(selected_org_type); helpers.update_discount_details(selected_org_type);
} }

View File

@ -372,7 +372,7 @@ input[name="licenses"] {
#sponsorship-discount-details { #sponsorship-discount-details {
font-weight: normal; font-weight: normal;
margin: 2px; margin: 2px;
padding-top: 25px; padding-top: 0;
text-align: left; text-align: left;
overflow-wrap: break-word; overflow-wrap: break-word;
width: 450px; width: 450px;