mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
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
This commit is contained in:
parent
3365fd736f
commit
b1e73387ea
14 changed files with 214 additions and 64 deletions
|
|
@ -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]
|
||||
|
|
|
|||
40
website/api/controllers/entrance/signup.js
vendored
40
website/api/controllers/entrance/signup.js
vendored
|
|
@ -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,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
BIN
website/assets/images/icon-checkmark-white-10x9@2x.png
vendored
Normal file
BIN
website/assets/images/icon-checkmark-white-10x9@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 290 B |
BIN
website/assets/images/icon-copy-14x14@2x.png
vendored
Normal file
BIN
website/assets/images/icon-copy-14x14@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 681 B |
BIN
website/assets/images/icon-pencil-12x12@2x.png
vendored
Normal file
BIN
website/assets/images/icon-pencil-12x12@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 415 B |
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
18
website/assets/styles/pages/entrance/signup.less
vendored
18
website/assets/styles/pages/entrance/signup.less
vendored
|
|
@ -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'] {
|
||||
|
|
|
|||
22
website/views/pages/customers/dashboard.ejs
vendored
22
website/views/pages/customers/dashboard.ejs
vendored
|
|
@ -42,7 +42,7 @@
|
|||
<p><js-timestamp :at="thisSubscription.nextBillingAt" always-show-year format="billing"></js-timestamp></p>
|
||||
</div>
|
||||
<div class="col-12 col-lg-4 pt-3 pt-lg-0">
|
||||
<strong>License key</strong><img class="d-inline-block ml-2" style="width: 15px; height: 16px; cursor: pointer;" src="/images/icon-copy-15x16@2x.png" alt="click here to copy your license key" @click="clickCopyLicenseKey()"><span purpose="copied-notification">License key copied!</span>
|
||||
<strong>License key</strong><img class="d-inline-block ml-2" style="height: 14px; cursor: pointer;" src="/images/icon-copy-14x14@2x.png" alt="click here to copy your license key" @click="clickCopyLicenseKey()"><span purpose="copied-notification">License key copied!</span>
|
||||
<p><span purpose="license-key" @click="clickExpandLicenseKey()">{{thisSubscription.fleetLicenseKey}}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -56,28 +56,28 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-4 col-12 pb-2 pb-sm-0">Organization:</div>
|
||||
<div class="col-sm-8 col-12 text-left text-sm-right">
|
||||
<strong>{{me.organization}}</strong><img purpose="edit-button" src="/images/icon-pencil-24x24@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickEditButton()">
|
||||
<strong>{{me.organization}}</strong><img purpose="edit-button" src="/images/icon-pencil-12x12@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickEditButton()">
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 pb-2 pb-sm-0">Name:</div>
|
||||
<div class="col-sm-9 col-12 text-left text-sm-right">
|
||||
<strong>{{me.firstName}} {{me.lastName}}</strong><img purpose="edit-button" src="/images/icon-pencil-24x24@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickEditButton()">
|
||||
<strong>{{me.firstName}} {{me.lastName}}</strong><img purpose="edit-button" src="/images/icon-pencil-12x12@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickEditButton()">
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 pb-2 pb-sm-0">Email:</div>
|
||||
<div class="col-sm-9 col-12 text-left text-sm-right">
|
||||
<strong :class="[me.emailStatus === 'unconfirmed' || me.emailStatus === 'change-requested' ? 'text-muted' : '']">{{me.emailChangeCandidate ? me.emailChangeCandidate : me.emailAddress}}</strong><img purpose="edit-button" src="/images/icon-pencil-24x24@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickEditButton()">
|
||||
<strong :class="[me.emailStatus === 'unconfirmed' || me.emailStatus === 'change-requested' ? 'text-muted' : '']">{{me.emailChangeCandidate ? me.emailChangeCandidate : me.emailAddress}}</strong><img purpose="edit-button" src="/images/icon-pencil-12x12@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickEditButton()">
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-12 pb-2 pb-sm-0">Password:</div>
|
||||
<div class="col-sm-8 col-12 text-left text-sm-right">
|
||||
<strong>••••••••</strong><img purpose="edit-button" src="/images/icon-pencil-24x24@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickChangePassword()">
|
||||
<strong>••••••••</strong><img purpose="edit-button" src="/images/icon-pencil-12x12@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickChangePassword()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
<div class="row pb-3 mx-0">
|
||||
<div style="max-width: 16px;" class="col-1 px-0"><img style="margin-top: 5px; height: 12px; width: 16px;" src="/images/icon-card-32x24@2x.png" alt="A credit card Icon"></div>
|
||||
<div class="col pl-3">
|
||||
<p>{{me.billingCardBrand}} ending in <strong>{{me.billingCardLast4}}</strong><img purpose="edit-button" src="/images/icon-pencil-24x24@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickUpdateBillingCardButton()"></p>
|
||||
<p>{{me.billingCardBrand}} ending in <strong>{{me.billingCardLast4}}</strong><img purpose="edit-button" src="/images/icon-pencil-12x12@2x.png" alt="A pencil icon indicating that this information can be editted" @click="clickUpdateBillingCardButton()"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pb-3 mx-0">
|
||||
|
|
@ -106,7 +106,7 @@
|
|||
<img style="display: inline-block; height: 16px; width: 16px; margin-top: -3px;" src="/images/info-16x16@2x.png" alt="An icon indicating that this section has important information">
|
||||
</div>
|
||||
<div class="col ml-1 pl-1 small">
|
||||
<p class="small"><a href="/contact" target="_blank">Contact us</a> to change your number of devices, or to <strong>cancel</strong> your subscription.</p>
|
||||
<p class="small"><a href="/contact" target="_blank">Contact us</a> to change your number of devices, or to cancel your subscription.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -114,13 +114,11 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
<div class="d-flex flex-md-row flex-column pt-3">
|
||||
<a class="btn btn-info btn-sm btn-md-block mr-md-3 mb-3 mb-md-0" purpose="deploy-button" href="/docs/deploying/introduction">
|
||||
<div class="d-flex flex-md-row flex-column pt-3 align-items-center justify-content-md-start justify-content-center">
|
||||
<a class="btn btn-primary btn-sm btn-md-block mb-3 mb-md-0" purpose="deploy-button" href="/docs/deploying/introduction">
|
||||
How to deploy Fleet
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary btn-sm btn-md-block" purpose="slack-button" href="/slack" target="_blank">
|
||||
<img alt="Slack logo" src="/images/logo-slack-24x24@2x.png"/>
|
||||
Ask for help on Slack
|
||||
<a purpose="animated-arrow-button-red" href="/support" target="_blank">Support
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
22
website/views/pages/customers/new-license.ejs
vendored
22
website/views/pages/customers/new-license.ejs
vendored
|
|
@ -3,7 +3,7 @@
|
|||
<div style="max-width: 560px;" class="container-fluid pb-5 px-lg-0 px-3" v-if="!showSuccessMessage">
|
||||
<div purpose="page-heading">
|
||||
<h1>Welcome to Fleet Premium</h1>
|
||||
<p class="pb-2">We just need a few details in order to get you a self-hosted Fleet Premium license key.</p>
|
||||
<p class="pb-2">We just need a few details in order to get started.</p>
|
||||
</div>
|
||||
<div purpose="customer-portal-form" class="card card-body">
|
||||
<ajax-form action="createQuote" :syncing.sync="syncing" :cloud-error.sync="cloudError" :form-errors.sync="formErrors" :form-data="formData" :form-rules="quoteFormRules" @submitted="submittedQuoteForm($event)">
|
||||
|
|
@ -17,27 +17,27 @@
|
|||
|
||||
<div style="color: #515774;" class="order-last text-left text-sm-right col-12 col-sm-6 pr-0 pl-sm-4 pl-0 pt-sm-4">
|
||||
<p class="small">
|
||||
<strong class="pr-1" style="font-size: 18px; color: #192147">$7.00</strong>/month/device<br>(Billed annually at $84/device)
|
||||
<strong class="pr-1" style="font-size: 18px; color: #192147">$7.00</strong>/ host / month<br>(Billed annually)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<cloud-error purpose="cloud-error" v-if="cloudError && !showBillingForm"></cloud-error>
|
||||
<div class="mt-2 pt-3 pb-3 border-top d-flex flex-column" v-if="showQuotedPrice && formData.numberOfHosts && numberOfHostsQuoted">
|
||||
<div class="mt-2 pt-3 pb-4 border-top d-flex flex-column" v-if="showQuotedPrice && formData.numberOfHosts && numberOfHostsQuoted">
|
||||
<div class="pb-2">
|
||||
<strong>Order total</strong>
|
||||
<strong>Order summary</strong>
|
||||
</div>
|
||||
<div class="d-flex flex-row justify-content-between">
|
||||
<p class="mb-0">Fleet Premium <br purpose="order-form-line-break"><span purpose="over-1000-linebreak"><br :class="[numberOfHostsQuoted >= 1000 ? 'd-block' : 'd-none']"></span>(self-hosted<span v-if="numberOfHostsQuoted >= 1000" > or managed cloud</span>)</p>
|
||||
<div class="ml-auto text-right">
|
||||
<p class="mb-0">Fleet Premium (self-hosted<span v-if="numberOfHostsQuoted > 699" > or managed cloud</span>)</p>
|
||||
<div class="ml-auto text-right" v-if="numberOfHostsQuoted < 700">
|
||||
<strong>${{(!showQuotedPrice || _.isNaN(formData.numberOfHosts * 7.00 * 12)) ? quotedPrice : formData.numberOfHosts * 7.00 * 12}}.00 <br purpose="order-form-line-break">/year</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[showBillingForm ? 'pt-2' : '' ]" v-if="!showBillingForm">
|
||||
<ajax-button purpose="submit-button" spinner="true" type="submit" :syncing="syncing" class="btn btn-block btn-lg btn-primary" v-if="!numberOfHostsQuoted">Continue</ajax-button>
|
||||
<ajax-button spinner="true" purpose="submit-button" :syncing="syncing" class="btn btn-block btn-lg btn-primary" @click="clickScheduleDemo" v-if="showQuotedPrice && numberOfHostsQuoted > 700">Talk to us</ajax-button>
|
||||
<ajax-button spinner="true" purpose="submit-button" :syncing="syncing" class="btn btn-block btn-lg btn-primary" v-if="showQuotedPrice && numberOfHostsQuoted <= 700">Continue</ajax-button>
|
||||
<ajax-button spinner="true" purpose="submit-button" :syncing="syncing" class="btn btn-block btn-lg btn-primary" @click="clickScheduleDemo" v-if="showQuotedPrice && numberOfHostsQuoted > 699">Talk to us</ajax-button>
|
||||
<ajax-button spinner="true" purpose="submit-button" :syncing="syncing" class="btn btn-block btn-lg btn-primary" v-if="showQuotedPrice && numberOfHostsQuoted < 700">Continue</ajax-button>
|
||||
</div>
|
||||
</ajax-form>
|
||||
</div>
|
||||
|
|
@ -72,6 +72,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" purpose="self-hosted-checkbox">
|
||||
<input type="checkbox" id="self-hosted-acknowledgment" v-model.trim="formData.selfHostedAcknowledgment" @input="clickClearOneFormError('selfHostedAcknowledgment')">
|
||||
<label purpose="self-hosted-note" :class="[formErrors.selfHostedAcknowledgment ? 'is-invalid' : '']" for="self-hosted-acknowledgment">I understand that managed cloud hosting is not available for less than 700 hosts. I will host Fleet myself.</label>
|
||||
<div class="invalid-feedback" v-if="formErrors.selfHostedAcknowledgment"><p>Please confirm that you will be hosting Fleet yourself.</p></div>
|
||||
|
||||
</div>
|
||||
<cloud-error purpose="cloud-error" v-if="cloudError === 'couldNotSaveBillingInfo'">
|
||||
<p>The billing card provided could not be used. Please use another card or <a href="/contact" target="_blank">contact support</a>.</p>
|
||||
</cloud-error>
|
||||
|
|
|
|||
2
website/views/pages/entrance/login.ejs
vendored
2
website/views/pages/entrance/login.ejs
vendored
|
|
@ -2,7 +2,7 @@
|
|||
<div :purpose="[showCustomerLogin ? 'customer-login-container' : 'login-container']" class="container-fluid pb-5 px-lg-0 px-3">
|
||||
<div purpose="page-heading" v-if="showCustomerLogin">
|
||||
<h1>Welcome to Premium</h1>
|
||||
<p class="pb-2">Sign in to manage your Fleet Premium subscription.</p>
|
||||
<p class="pb-2">We just need a few details in order to get started.</p>
|
||||
</div>
|
||||
<div purpose="page-heading" v-else>
|
||||
<h1>Welcome to Fleet</h1>
|
||||
|
|
|
|||
28
website/views/pages/entrance/signup.ejs
vendored
28
website/views/pages/entrance/signup.ejs
vendored
|
|
@ -7,44 +7,60 @@
|
|||
<div purpose="customer-portal-form" class="card card-body">
|
||||
<ajax-form action="signup" class="self-service-register" :syncing.sync="syncing" :cloud-error.sync="cloudError" :form-errors.sync="formErrors" :form-data="formData" :form-rules="formRules" @submitted="submittedSignUpForm()">
|
||||
<div class="form-group">
|
||||
<label for="email-address">Email</label>
|
||||
<span style="float: right" class="text-right small"><a :href="loginSlug">I have an account</a></span>
|
||||
<label for="email-address">Work email *</label>
|
||||
<span style="float: right" class="text-right small"><a href="/customers/login">I have an account</a></span>
|
||||
<input class="form-control" id="email-address" :class="[formErrors.emailAddress ? 'is-invalid' : '']" v-model.trim="formData.emailAddress" @input="typeClearOneFormError('emailAddress')">
|
||||
<div class="invalid-feedback" v-if="formErrors.emailAddress" focus-first>This doesn’t appear to be a valid email address</div>
|
||||
</div>
|
||||
<div v-show="formData.emailAddress || showFullForm">
|
||||
<div class="form-group">
|
||||
<label for="password">Choose a password</label>
|
||||
<label for="password">Choose a password *</label>
|
||||
<input class="form-control" id="password" type="password" :class="[formErrors.password ? 'is-invalid' : '']" v-model.trim="formData.password" autocomplete="new-password" @input="typeClearOneFormError('password')">
|
||||
<div class="invalid-feedback" v-if="formErrors.password === 'minLength'">Password too short.</div>
|
||||
<div class="invalid-feedback" v-if="formErrors.password === 'required'">Please enter a password.</div>
|
||||
<p class="mt-2"> Minimum length is 8 characters</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="organization">Organization</label>
|
||||
<label for="organization">Organization *</label>
|
||||
<input class="form-control" id="organization" type="text" :class="[formErrors.organization ? 'is-invalid' : '']" v-model.trim="formData.organization" @input="typeClearOneFormError('organization')">
|
||||
<div class="invalid-feedback" v-if="formErrors.organization">Please enter the name of your organization.</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 pr-sm-2">
|
||||
<div class="form-group">
|
||||
<label for="first-name">First name</label>
|
||||
<label for="first-name">First name *</label>
|
||||
<input class="form-control" id="first-name" type="text" :class="[formErrors.firstName ? 'is-invalid' : '']" v-model.trim="formData.firstName" autocomplete="first-name" @input="typeClearOneFormError('firstName')">
|
||||
<div class="invalid-feedback" v-if="formErrors.firstName">Please enter your first name.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 pl-sm-2">
|
||||
<div class="form-group">
|
||||
<label for="last-name">Last name</label>
|
||||
<label for="last-name">Last name *</label>
|
||||
<input class="form-control" id="last-name" type="text" :class="[formErrors.lastName ? 'is-invalid' : '']" v-model.trim="formData.lastName" autocomplete="last-name" @input="typeClearOneFormError('lastName')">
|
||||
<div class="invalid-feedback" v-if="formErrors.lastName">Please enter your last name.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="primaryBuyingSituation">What will you be using Fleet for? *</label>
|
||||
<div class="selectbox">
|
||||
<select class="form-control" id="primaryBuyingSituation" name="primaryBuyingSituation" :class="[formErrors.primaryBuyingSituation ? 'is-invalid' : '']" v-model="formData.primaryBuyingSituation" @input="typeClearOneFormError('primaryBuyingSituation')">
|
||||
<option disabled hidden value="undefined">Choose an option</option>
|
||||
<option value="endpoint-ops-security">Endpoint operations for security engineers</option>
|
||||
<option value="endpoint-ops-it">Endpoint operations for IT admins</option>
|
||||
<option value="device-management">Device management</option>
|
||||
<option value="vulnerability-management">Vulnerability management</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="d-block invalid-feedback" v-if="formErrors.primaryBuyingSituation">Please select an option.</div>
|
||||
</div>
|
||||
</div>
|
||||
<cloud-error v-if="cloudError==='emailAlreadyInUse'">
|
||||
<p>This email is already linked to a Fleet account.<br> Please <a href="/customers/login">sign in</a> with your email and password.</p>
|
||||
</cloud-error>
|
||||
<cloud-error v-else-if="cloudError === 'invalidEmailDomain'">
|
||||
<p>Please enter a valid work email address</p>
|
||||
</cloud-error>
|
||||
<cloud-error purpose="cloud-error" v-else-if="cloudError"></cloud-error>
|
||||
<p class="small">By signing up you agree to our <a href="/legal/privacy">privacy policy</a> and <a href="/terms">terms of service</a>.</p>
|
||||
<ajax-button purpose="submit-button" spinner="true" type="submit" :syncing="syncing" class="btn btn-block btn-lg btn-primary mt-4" v-if="!cloudError">Agree and continue</ajax-button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue