From b1e73387eaab11c5127906adf778bd4a3c849313 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 14 Mar 2024 12:28:35 -0500 Subject: [PATCH] Website: update signup forms and license dispenser (#17572) Closes: #16697 Changes: - Updated the managed cloud feature in `pricing-features-table.yml` to note that is only available for >700 hosts - Updated `signup.js` to accept one new input `primaryBuyingSituation` and to throw an error if someone signs up with a personal email address. - Updated the /customers/register page to ask users signing up what they will be using Fleet for, and to display an error if a user signs up with a personal email address. - Updated the /try-fleet/register page to show an error if a user signs up with a personal email address - Updated the /customers/new-license page to: - only show the quoted price for users creating a quote for >700 hosts - Add a checkbox to the billing form for users to confirm that they understand they are buying a license for self-hosted Fleet Premium --- handbook/company/pricing-features-table.yml | 2 +- website/api/controllers/entrance/signup.js | 40 +++++++- .../images/icon-checkmark-white-10x9@2x.png | Bin 0 -> 290 bytes website/assets/images/icon-copy-14x14@2x.png | Bin 0 -> 681 bytes .../assets/images/icon-pencil-12x12@2x.png | Bin 0 -> 415 bytes .../js/pages/customers/new-license.page.js | 9 +- .../assets/js/pages/entrance/signup.page.js | 1 + .../styles/pages/customers/dashboard.less | 88 +++++++++++------- .../styles/pages/customers/new-license.less | 46 +++++++++ .../assets/styles/pages/entrance/signup.less | 18 ++++ website/views/pages/customers/dashboard.ejs | 22 ++--- website/views/pages/customers/new-license.ejs | 22 +++-- website/views/pages/entrance/login.ejs | 2 +- website/views/pages/entrance/signup.ejs | 28 ++++-- 14 files changed, 214 insertions(+), 64 deletions(-) create mode 100644 website/assets/images/icon-checkmark-white-10x9@2x.png create mode 100644 website/assets/images/icon-copy-14x14@2x.png create mode 100644 website/assets/images/icon-pencil-12x12@2x.png diff --git a/handbook/company/pricing-features-table.yml b/handbook/company/pricing-features-table.yml index 829e13807d..bacf972b78 100644 --- a/handbook/company/pricing-features-table.yml +++ b/handbook/company/pricing-features-table.yml @@ -529,7 +529,7 @@ tier: Free productCategories: [Endpoint operations] pricingTableCategories: [Deployment] -- industryName: Managed Cloud +- industryName: Managed Cloud (700+ hosts) description: Have Fleet host it for you (currently only available for customers with 700+ hosts. PS. Wish we could host for you? We're working on it! Please let us know if you know of a good partner. In the meantime, join fleetdm.com/support and we're happy to help you deploy Fleet yourself.) pricingTableCategories: [Deployment] productCategories: [Endpoint operations,Device management,Vulnerability management] diff --git a/website/api/controllers/entrance/signup.js b/website/api/controllers/entrance/signup.js index dd62d799a5..df3b8853aa 100644 --- a/website/api/controllers/entrance/signup.js +++ b/website/api/controllers/entrance/signup.js @@ -61,6 +61,18 @@ the account verification message.)`, type: 'string', isIn: ['Buy a license', 'Try Fleet'], defaultsTo: 'Buy a license', + }, + + primaryBuyingSituation: { + type: 'string', + description: 'What the user will be using Fleet for.', + required: true, + isIn: [ + 'endpoint-ops-security', + 'endpoint-ops-it', + 'device-management', + 'vulnerability-management' + ], } }, @@ -84,18 +96,41 @@ the account verification message.)`, description: 'The provided email address is already in use.', }, + invalidEmailDomain: { + description: 'This email address is on a denylist of domains and cannot be used to signup for a fleetdm.com account.', + responseType: 'badRequest' + }, + }, - fn: async function ({emailAddress, password, firstName, lastName, organization, signupReason}) { + fn: async function ({emailAddress, password, firstName, lastName, organization, signupReason, primaryBuyingSituation}) { // Note: in Oct. 2023, the Fleet Sandbox related code was removed from this action. For more details, see https://github.com/fleetdm/fleet/pull/14638/files var newEmailAddress = emailAddress.toLowerCase(); - // Checking if a user with this email address exists in our database before we send a request to the cloud provisioner. if(await User.findOne({emailAddress: newEmailAddress})) { throw 'emailAlreadyInUse'; } + // Check the user's email address and return an 'invalidEmailDomain' response if the domain is in the bannedEmailDomainsForSignup array. + let emailDomain = newEmailAddress.split('@')[1]; + let bannedEmailDomainsForSignup = [ + 'gmail.com', + 'yahoo.com', + 'yahoo.co.uk', + 'hotmail.com', + 'hotmail.co.uk', + 'outlook.com', + 'icloud.com', + 'proton.me', + 'live.com', + 'yandex.ru', + 'ymail.com', + ]; + if(_.includes(bannedEmailDomainsForSignup, emailDomain)){ + throw 'invalidEmailDomain'; + } + if (!sails.config.custom.enableBillingFeatures) { throw new Error('The Stripe configuration variables (sails.config.custom.stripePublishableKey and sails.config.custom.stripeSecret) are missing!'); @@ -137,6 +172,7 @@ the account verification message.)`, lastName, organization, signupReason, + primaryBuyingSituation, webhookSecret: sails.config.custom.zapierSandboxWebhookSecret, } }) diff --git a/website/assets/images/icon-checkmark-white-10x9@2x.png b/website/assets/images/icon-checkmark-white-10x9@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb3f6ca9d9f5cf35e2bf7483b9764921f44dac8 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy}!3HFwFZ>e#Qk(@Ik;M!QVyYm_=ozH)0Vv2= z9OUlAuO?P6UzmyR@uwdh$4qhirv`{zw5|^rDT2= z_~EF3=x|%kl3Ok>%Wpq@-m*zAb*5Z&!3pi&z{t-xoKwxa#UF4i@&Dwnbb9^)-|d%E hoM!n=D#JKOl|ANeYuM2(B|puEB9h zXP6Ay?8+c61_=Zjx$!G*?pAwu?{0Usdk6`jb))zKr*1-e7%R$EN9J<4k${|>8Ml`b901Y{0*)a8 z*aUC6X;>nYr^Dk|0xxx4Bhv415yB2%T^n}9e7$S#Y8fM9N5xH0Ip48{W}nRkVt29s zVoXG*u>^orNPyY)AO#d)Vn>0qVuDw1>h5et9)ECl^mu~^1K$tKW!5Piy{^%s|KAOW zxAW#=BX^H*(-JXa>ykccY*G#h993#(DTkUS#BN!?cjA-|q$%rq(;`8>``g&5$*@bo51SSro0Ji%Fi@`8TPt6rREp@5;C{`0ActyeT z`R30kl0ZbL3dg6GkE+hcVo3T@frJumDOUAc+a93 zIJZB?FK>nX+0#_n_nfiW3UUxpo8V!U{EtPNK@@nP88lWyJ1d9^U-UedL0b4$0~zp* z2D0Fx1~TDm2D0Hx23f#`lsR0iT>0=n1K#IXyDlby3!zw09_A)lz=f2ls@1ZB2L>~r znpwexR3Nxm595G`K4f?YQc6YfI53cx`aAj9*FdvuyYGS|{Q@3K*i;811N8s^002ov JPDHLkV1haRvNZqz literal 0 HcmV?d00001 diff --git a/website/assets/js/pages/customers/new-license.page.js b/website/assets/js/pages/customers/new-license.page.js index f2c7a720ce..f49312ffff 100644 --- a/website/assets/js/pages/customers/new-license.page.js +++ b/website/assets/js/pages/customers/new-license.page.js @@ -16,6 +16,7 @@ parasails.registerPage('new-license', { billingFormRules: { paymentSource: {required: true}, + selfHostedAcknowledgment: {required: true, is: true}, }, // Syncing / loading state @@ -73,13 +74,19 @@ parasails.registerPage('new-license', { this.showQuotedPrice = true; this.quotedPrice = quote.quotedPrice; this.numberOfHostsQuoted = quote.numberOfHosts; - if(quote.numberOfHosts <= 700) { + if(quote.numberOfHosts < 700) { this.formData.quoteId = quote.id; this.showBillingForm = true; } await this.forceRender(); }, + clickClearOneFormError: async function(field) { + if(this.formErrors[field]){ + this.formErrors = _.omit(this.formErrors, field); + } + }, + clickScheduleDemo: async function() { this.syncing = true; // Note: we keep loading spinner present indefinitely so that it is apparent that a new page is loading diff --git a/website/assets/js/pages/entrance/signup.page.js b/website/assets/js/pages/entrance/signup.page.js index 301f0014bc..d527b084a1 100644 --- a/website/assets/js/pages/entrance/signup.page.js +++ b/website/assets/js/pages/entrance/signup.page.js @@ -17,6 +17,7 @@ parasails.registerPage('signup', { organization: {required: true}, emailAddress: {required: true, isEmail: true}, password: {required: true, minLength: 8}, + primaryBuyingSituation: {required: true}, }, // Syncing / loading state syncing: false, diff --git a/website/assets/styles/pages/customers/dashboard.less b/website/assets/styles/pages/customers/dashboard.less index cd46a5b186..6dd2f43dff 100644 --- a/website/assets/styles/pages/customers/dashboard.less +++ b/website/assets/styles/pages/customers/dashboard.less @@ -1,5 +1,5 @@ #dashboard { - padding-top: 40px; + padding-top: 80px; h1 { font-size: 28px; @@ -7,7 +7,8 @@ } h3 { padding-bottom: 16px; - font-size: 24px; + font-size: 16px; + line-height: 120%; margin-bottom: 0px; } a { @@ -93,42 +94,60 @@ cursor: pointer; } - [purpose='slack-button'] { - font-size: 16px; + [purpose='animated-arrow-button-red'] { + display: flex; + flex-direction: row; + align-items: center; + line-height: 24px; + padding-right: 24px; + cursor: pointer; + position: relative; + width: fit-content; + font-weight: bold; + user-select: none; + transition: 0.2s ease-in-out; + -o-transition: 0.2s ease-in-out; + -ms-transition: 0.2s ease-in-out; + -moz-transition: 0.2s ease-in-out; + -webkit-transition: 0.2s ease-in-out; color: @core-fleet-black; - background-color: #fff; - border: 1px solid #C5C7D1; - border-radius: 4px; - padding: 8px 40px; - line-height: 20px; - &:hover { - background: #fff; - color: @core-fleet-black; - } - &:focus { - box-shadow: none; - } - img { - display: inline; - height: 20px; - width: auto; - padding-right: 4px; - margin-bottom: 1px; - } - a { - color: @core-fleet-black; - } text-decoration: none; + &:hover { + color: #000; + } + &:after { + content: url('/images/arrow-right-red-16x16@2x.png'); + transform: scale(0.5); + position: absolute; + top: -5px; + left: 75%; // <--- here + transition: 0.2s ease-in-out; + -o-transition: 0.2s ease-in-out; + -ms-transition: 0.2s ease-in-out; + -moz-transition: 0.2s ease-in-out; + -webkit-transition: 0.2s ease-in-out; + } + &:hover:after { + left: 82%; // <--- here + transition: 0.2s ease-in-out; + -o-transition: 0.2s ease-in-out; + -ms-transition: 0.2s ease-in-out; + -moz-transition: 0.2s ease-in-out; + -webkit-transition: 0.2s ease-in-out; + } } [purpose='deploy-button'] { - font-size: 16px; - line-height: 20px; - padding: 8px 40px; - border-radius: 4px; - color: white; + height: 48px; + padding: 16px 32px; + border-radius: 8px; + color: #FFF; text-decoration: none; + font-size: 16px; + font-weight: 700; + line-height: 16px; + margin-right: 32px; &:hover { - color: white; + color: #FFF; } } @@ -243,7 +262,7 @@ } @media (max-width: 768px) { - padding-top: 60px; + padding-top: 64px; [purpose='modal-content'] { margin-top: 50px; @@ -262,6 +281,9 @@ [purpose='billing-card'] { padding: 40px 20px; } + [purpose='deploy-button'] { + margin-right: unset; + } } diff --git a/website/assets/styles/pages/customers/new-license.less b/website/assets/styles/pages/customers/new-license.less index 484bc00789..1942c73ff6 100644 --- a/website/assets/styles/pages/customers/new-license.less +++ b/website/assets/styles/pages/customers/new-license.less @@ -25,6 +25,52 @@ input[type='number'] { -moz-appearance: textfield; } + + [purpose='self-hosted-checkbox'] { + [purpose='self-hosted-note'] { + font-size: 14px; + line-height: 150%; + margin-bottom: 0px; + margin-botom: 24px; + } + input { + display: none; + } + input + label { + position: relative; + padding-left: 24px; + cursor: pointer; + } + input + label::before { + content: ''; + position: absolute; + left: 0; + top: 2px; + width: 16px; + height: 16px; + background-color: #fff; + border: 2px solid #192147; + border-radius: 4px; + } + input:checked + label::before { + background-color: #192147; + } + input:checked + label::after { + content: url('/images/icon-checkmark-white-10x9@2x.png'); + position: absolute; + left: -1px; + top: 2px; + transform: scale(0.5); + width: 16px; + height: 16px; + } + label.is-invalid::before { + border: 2px solid #FF5C83; + } + label.is-invalid + .invalid-feedback { + display: block; + } + } [purpose='quote-input'] { max-width: 200px; } diff --git a/website/assets/styles/pages/entrance/signup.less b/website/assets/styles/pages/entrance/signup.less index 21b4acff8f..6288210bb1 100644 --- a/website/assets/styles/pages/entrance/signup.less +++ b/website/assets/styles/pages/entrance/signup.less @@ -28,6 +28,24 @@ .card-body { padding: 2em; } + .selectbox { + + position: relative; + } + .selectbox::after { + content: url('/images/chevron-12x8@2x.png'); + right: 14px; + transform: scale(0.5); + top: 14px; + position: absolute; + pointer-events: none; + } + .selectbox select { + border-radius: 6px; + height: 48px; + appearance: none; + -webkit-appearance: none; + } } [purpose='submit-button'] { diff --git a/website/views/pages/customers/dashboard.ejs b/website/views/pages/customers/dashboard.ejs index 26631ccbec..abac99d72d 100644 --- a/website/views/pages/customers/dashboard.ejs +++ b/website/views/pages/customers/dashboard.ejs @@ -42,7 +42,7 @@

- License keyclick here to copy your license keyLicense key copied! + License keyclick here to copy your license keyLicense key copied!

{{thisSubscription.fleetLicenseKey}}

@@ -56,28 +56,28 @@
Organization:
- {{me.organization}}A pencil icon indicating that this information can be editted + {{me.organization}}A pencil icon indicating that this information can be editted

Name:
- {{me.firstName}} {{me.lastName}}A pencil icon indicating that this information can be editted + {{me.firstName}} {{me.lastName}}A pencil icon indicating that this information can be editted

Email:
- {{me.emailChangeCandidate ? me.emailChangeCandidate : me.emailAddress}}A pencil icon indicating that this information can be editted + {{me.emailChangeCandidate ? me.emailChangeCandidate : me.emailAddress}}A pencil icon indicating that this information can be editted

Password:
- ••••••••A pencil icon indicating that this information can be editted + ••••••••A pencil icon indicating that this information can be editted
@@ -89,7 +89,7 @@
A credit card Icon
-

{{me.billingCardBrand}} ending in {{me.billingCardLast4}}A pencil icon indicating that this information can be editted

+

{{me.billingCardBrand}} ending in {{me.billingCardLast4}}A pencil icon indicating that this information can be editted

@@ -106,7 +106,7 @@ An icon indicating that this section has important information
-

Contact us to change your number of devices, or to cancel your subscription.

+

Contact us to change your number of devices, or to cancel your subscription.

@@ -114,13 +114,11 @@ -
- + diff --git a/website/views/pages/customers/new-license.ejs b/website/views/pages/customers/new-license.ejs index c4a4027b5a..5064a71649 100644 --- a/website/views/pages/customers/new-license.ejs +++ b/website/views/pages/customers/new-license.ejs @@ -3,7 +3,7 @@

Welcome to Fleet Premium

-

We just need a few details in order to get you a self-hosted Fleet Premium license key.

+

We just need a few details in order to get started.

@@ -17,27 +17,27 @@

- $7.00/month/device
(Billed annually at $84/device) + $7.00/ host / month
(Billed annually)

-
+
- Order total + Order summary
-

Fleet Premium

(self-hosted or managed cloud)

-
+

Fleet Premium (self-hosted or managed cloud)

+
${{(!showQuotedPrice || _.isNaN(formData.numberOfHosts * 7.00 * 12)) ? quotedPrice : formData.numberOfHosts * 7.00 * 12}}.00
/year
Continue - Talk to us - Continue + Talk to us + Continue
@@ -72,6 +72,12 @@
+
+ + +

Please confirm that you will be hosting Fleet yourself.

+ +

The billing card provided could not be used. Please use another card or contact support.

diff --git a/website/views/pages/entrance/login.ejs b/website/views/pages/entrance/login.ejs index ba85473b8f..489e87bbab 100644 --- a/website/views/pages/entrance/login.ejs +++ b/website/views/pages/entrance/login.ejs @@ -2,7 +2,7 @@

Welcome to Premium

-

Sign in to manage your Fleet Premium subscription.

+

We just need a few details in order to get started.

Welcome to Fleet

diff --git a/website/views/pages/entrance/signup.ejs b/website/views/pages/entrance/signup.ejs index e185da8181..e3bbb974ee 100644 --- a/website/views/pages/entrance/signup.ejs +++ b/website/views/pages/entrance/signup.ejs @@ -7,44 +7,60 @@
- - I have an account + + I have an account
This doesn’t appear to be a valid email address
- +
Password too short.
Please enter a password.

Minimum length is 8 characters

- +
Please enter the name of your organization.
- +
Please enter your first name.
- +
Please enter your last name.
+
+ +
+ +
+
Please select an option.
+

This email is already linked to a Fleet account.
Please sign in with your email and password.

+ +

Please enter a valid work email address

+

By signing up you agree to our privacy policy and terms of service.

Agree and continue