mirror of https://github.com/zulip/zulip.git
sponsorsihp: Make submitting the form work.
Includes various changes to make submitting the sponsorship form work.
This commit is contained in:
parent
a75c8ee6f0
commit
ff5e1c3aee
|
@ -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>
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
$(() => {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue