sponsorsihp: Make submitting the form work.

Includes various changes to make submitting the sponsorship form work.
This commit is contained in:
Aman Agrawal 2023-11-02 15:03:52 +00:00 committed by Tim Abbott
parent a75c8ee6f0
commit ff5e1c3aee
7 changed files with 102 additions and 32 deletions

View File

@ -4,12 +4,12 @@
{% set PAGE_TITLE = "💚 Request sponsorship" %}
{% block portico_content %}
<div class="register-account flex full-page">
<div class="register-account flex full-page sponsorship-page">
<div class="center-block new-style">
<div class="pitch">
<h1>💚 Request sponsorship</h1>
</div>
<div id="registration" class="white-box">
<div class="white-box">
<div id="sponsorship-error" class="alert alert-danger"></div>
<div id="sponsorship-input-section">
<form id="sponsorship-form" method="post">
@ -20,7 +20,7 @@
</div>
<div class="input-box sponsorship-form-field">
<div class="inline-block relative">
<select name="realm_type" id="realm_type" class="sponsorship-form-select">
<select name="organization-type" id="organization-type" class="sponsorship-form-select">
{% for org_type in sorted_org_types %}
{% if not org_type[1].hidden %}
<option data-string-value="{{ org_type[0] }}"
@ -32,11 +32,11 @@
{% endfor %}
</select>
</div>
<label for="realm_type" class="inline-block label-title">{{ _('Organization type') }}</label>
<label for="organization-type" class="inline-block label-title">{{ _('Organization type') }}</label>
</div>
<div class="input-box sponsorship-form-field no-validation">
<label for="org-website" class="inline-block label-title">{{ _('Organization website') }}</label>
<input id="org-website" name="website" type="text" class="input-large" placeholder="{{ _('Leave blank if your organization does not have a website.') }}"/>
<input id="org-website" name="website" type="text" placeholder="{{ _('Leave blank if your organization does not have a website.') }}"/>
</div>
<div class="input-box sponsorship-form-field">
<label for="description" class="inline-block label-title">{{ _('Describe your organization briefly') }}</label>
@ -46,8 +46,8 @@
<!-- 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="{% trans %}Convert demo organization before upgrading.{% endtrans %}"{% endif %}>
<button type="submit" id="sponsorship-button" class="stripe-button-el invoice-button" {% if is_demo_organization %}disabled{% endif %}>
Submit
<object class="loader" type="image/svg+xml" data="{{ static('images/loading/loader-white.svg') }}"></object>
<span class="sponsorship-button-text">Submit</span>
<object class="loader sponsorship-button-loader" type="image/svg+xml" data="{{ static('images/loading/loader-white.svg') }}"></object>
</button>
</div>
</form>

View File

@ -58,7 +58,6 @@ EXEMPT_FILES = make_set(
"web/src/avatar.ts",
"web/src/billing/event_status.ts",
"web/src/billing/helpers.ts",
"web/src/billing/upgrade.ts",
"web/src/blueslip.ts",
"web/src/blueslip_stacktrace.ts",
"web/src/browser_history.ts",

View File

@ -5,7 +5,7 @@ import * as loading from "../loading";
import {page_params} from "./page_params";
type FormDataObject = Record<string, string>;
export type FormDataObject = Record<string, string>;
export const schedule_schema = z.enum(["monthly", "annual"]);
export type Prices = Record<z.infer<typeof schedule_schema>, number>;
@ -108,7 +108,7 @@ export function update_charged_amount(prices: Prices, schedule: keyof Prices): v
$("#charged_amount").text(format_money(page_params.seat_count * prices[schedule]));
}
export function update_discount_details(organization_type: keyof DiscountDetails): void {
export function update_discount_details(organization_type: string): void {
let discount_notice =
"Your organization may be eligible for a discount on Zulip Cloud Standard. Organizations whose members are not employees are generally eligible.";
const discount_details: DiscountDetails = {
@ -120,9 +120,20 @@ export function update_discount_details(organization_type: keyof DiscountDetails
education_nonprofit:
"Zulip Cloud Standard is discounted 90% for education non-profits with online purchase.",
};
if (discount_details[organization_type]) {
discount_notice = discount_details[organization_type];
try {
const parsed_organization_type = organization_type_schema.parse(organization_type);
discount_notice = discount_details[parsed_organization_type];
} catch {
// This will likely fail if organization_type is not in organization_type_schema or
// parsed_organization_type is not preset in discount_details. In either case, we will
// fallback to the default discount_notice.
//
// Why use try / catch?
// Because organization_type_schema.options.includes wants organization_type to be of type
// opensource | research | ... and defining a type like that is not useful.
}
$("#sponsorship-discount-details").text(discount_notice);
}
@ -161,18 +172,6 @@ export function set_tab(page: string): void {
window.addEventListener("hashchange", handle_hashchange);
}
export function set_sponsorship_form(): void {
$("#sponsorship-button").on("click", (e) => {
if (!is_valid_input($("#sponsorship-form"))) {
return;
}
e.preventDefault();
create_ajax_request("/json/billing/sponsorship", "sponsorship", [], "POST", () =>
window.location.replace("/"),
);
});
}
export function is_valid_input(elem: JQuery<HTMLFormElement>): boolean {
return elem[0].checkValidity();
}

View File

@ -2,8 +2,56 @@ import $ from "jquery";
import * as helpers from "./helpers";
function show_submit_loading_indicator(): void {
$("#sponsorship-button .sponsorship-button-loader").css("display", "inline-block");
$("#sponsorship-button").prop("disabled", true);
$("#sponsorship-button .sponsorship-button-text").hide();
}
function hide_submit_loading_indicator(): void {
$("#sponsorship-button .sponsorship-button-loader").css("display", "none");
$("#sponsorship-button").prop("disabled", false);
$("#sponsorship-button .sponsorship-button-text").show();
}
function create_ajax_request(): void {
show_submit_loading_indicator();
const $form = $("#sponsorship-form");
const data: helpers.FormDataObject = {};
for (const item of $form.serializeArray()) {
data[item.name] = item.value;
}
void $.ajax({
type: "post",
url: "/json/billing/sponsorship",
data,
success() {
window.location.reload();
},
error(xhr) {
hide_submit_loading_indicator();
if (xhr.responseJSON?.msg) {
$("#sponsorship-error").show().text(xhr.responseJSON.msg);
}
},
});
}
export function initialize(): void {
helpers.set_sponsorship_form();
$("#sponsorship-button").on("click", (e) => {
if (!helpers.is_valid_input($("#sponsorship-form"))) {
return;
}
e.preventDefault();
create_ajax_request();
});
$<HTMLSelectElement>("#organization-type").on("change", (e) => {
const string_value = $(e.currentTarget.selectedOptions).attr("data-string-value") ?? "";
helpers.update_discount_details(string_value);
});
}
$(() => {

View File

@ -44,11 +44,6 @@ export const initialize = (): void => {
helpers.update_charged_amount(prices, helpers.schedule_schema.parse(this.value));
});
$<HTMLSelectElement>("select[name=organization-type]").on("change", (e) => {
const string_value = $(e.currentTarget.selectedOptions).attr("data-string-value");
helpers.update_discount_details(helpers.organization_type_schema.parse(string_value));
});
$("#autopay_annual_price").text(helpers.format_money(prices.annual));
$("#autopay_annual_price_per_month").text(helpers.format_money(prices.annual / 12));
$("#autopay_monthly_price").text(helpers.format_money(prices.monthly));

View File

@ -371,6 +371,33 @@ input[name="licenses"] {
background-color: hsl(240deg 96% 68%);
}
#sponsorship-form {
.sponsorship-page .white-box {
margin: 30px;
}
.sponsorship-page #sponsorship-form {
margin: 0;
}
#sponsorship-discount-details {
font-weight: normal;
margin: 2px;
padding-top: 25px;
text-align: left;
overflow-wrap: break-word;
width: 450px;
}
@media (width < 600px) {
.sponsorship-page {
transform: scale(0.8);
margin: -50px;
}
}
@media (width < 460px) {
.sponsorship-page {
transform: scale(0.6);
margin: -150px -100px;
}
}

View File

@ -916,6 +916,7 @@ button#register_auth_button_gitlab {
}
}
#sponsorship-form,
#registration,
#new-realm-creation {
width: auto;
@ -1012,7 +1013,8 @@ button#register_auth_button_gitlab {
width: 450px;
}
.register-button .loader {
.register-button .loader,
.sponsorship-button-loader {
display: none;
vertical-align: top;
position: relative;