Website: add MDM launch party page (#10731)

Changes:
- Added `/imagine/launch-party` a page advertising our MDM launch
party/RSA happy hour where users can join the launch party waitlist. If
a user visits fleetdm.com/imagine/launch-party?showForm, a modal with a
waitlist signup form opens when the page loads.
- Added a new action, `deliver-launch-party-signup.js`. This action
sends a POST request to a Zapier webhook.
- Updated routes, policies, and cloud-SDK

---------

Co-authored-by: Mike Thomas <mthomas@fleetdm.com>
Co-authored-by: Jarod Reyes <jarodreyes@gmail.com>
Co-authored-by: Mike Thomas <78363703+mike-j-thomas@users.noreply.github.com>
This commit is contained in:
Eric 2023-03-28 12:20:00 -05:00 committed by GitHub
parent 1fbc44a326
commit 24aa8e6732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 490 additions and 1 deletions

View File

@ -0,0 +1,78 @@
module.exports = {
friendlyName: 'Deliver launch party signup',
description: 'Delivers a form submission to a Zapier webhook when someone RSVPs to our MDM launch party.',
inputs: {
emailAddress: {
required: true,
type: 'string',
description: 'The email address provided when a user submitted the launch party waitlist form.',
example: 'hermione@hogwarts.edu'
},
firstName: {
required: true,
type: 'string',
description: 'The first name provided when a user submitted the launch party waitlist form',
},
lastName: {
required: true,
type: 'string',
description: 'The last name provided when a user submitted the launch party waitlist form',
},
jobTitle: {
type: 'string',
description: 'The job title provided when a user submitted the launch party waitlist form',
},
phoneNumber: {
type: 'string',
description: 'The phone number provided when a user submitted the launch party waitlist form',
},
},
exits: {
success: {
description: 'The message was sent successfully.'
}
},
fn: async function({emailAddress, firstName, lastName, jobTitle, phoneNumber}) {
if(!sails.config.custom.zapierSandboxWebhookSecret) {
throw new Error('Message not delivered: zapierSandboxWebhookSecret needs to be configured in sails.config.custom.');
}
// Send a POST request to Zapier
await sails.helpers.http.post(
'https://hooks.zapier.com/hooks/catch/3627242/33kdpw0/',
{
'firstName': firstName,
'lastName': lastName,
'emailAddress': emailAddress,
'jobTitle': jobTitle,
'phoneNumber': phoneNumber,
'webhookSecret': sails.config.custom.zapierSandboxWebhookSecret
}
)
.timeout(5000)
.tolerate(['non200Response', 'requestFailed', {name: 'TimeoutError'}], (err)=>{
// Note that Zapier responds with a 2xx status code even if something goes wrong, so just because this message is not logged doesn't mean everything is hunky dory. More info: https://github.com/fleetdm/fleet/pull/6380#issuecomment-1204395762
sails.log.warn(`When a user submitted the launch party waitlist form, an error occurred while sending a request to Zapier. Raw error: ${require('util').inspect(err)}`);
return;
});
}
};

View File

@ -0,0 +1,27 @@
module.exports = {
friendlyName: 'View launch party',
description: 'Display "Launch party" page.',
exits: {
success: {
viewTemplatePath: 'pages/imagine/launch-party'
}
},
fn: async function () {
// Respond with view.
return {};
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@ -13,7 +13,7 @@
Cloud.setup({
/* eslint-disable */
methods: {"downloadSitemap":{"verb":"GET","url":"/sitemap.xml","args":[]},"downloadRssFeed":{"verb":"GET","url":"/rss/:categoryName","args":["categoryName"]},"receiveUsageAnalytics":{"verb":"POST","url":"/api/v1/webhooks/receive-usage-analytics","args":["anonymousIdentifier","fleetVersion","licenseTier","numHostsEnrolled","numUsers","numTeams","numPolicies","numLabels","softwareInventoryEnabled","vulnDetectionEnabled","systemUsersEnabled","hostStatusWebhookEnabled","numWeeklyActiveUsers","numWeeklyPolicyViolationDaysActual","numWeeklyPolicyViolationDaysPossible","hostsEnrolledByOperatingSystem","hostsEnrolledByOrbitVersion","hostsEnrolledByOsqueryVersion","storedErrors","numHostsNotResponding","organization"]},"receiveFromGithub":{"verb":"GET","url":"/api/v1/webhooks/github","args":["botSignature","action","sender","repository","changes","issue","comment","pull_request","label"]},"receiveFromStripe":{"verb":"POST","url":"/api/v1/webhooks/receive-from-stripe","args":["id","type","data","webhookSecret"]},"deliverContactFormMessage":{"verb":"POST","url":"/api/v1/deliver-contact-form-message","args":["emailAddress","topic","firstName","lastName","message"]},"sendPasswordRecoveryEmail":{"verb":"POST","url":"/api/v1/entrance/send-password-recovery-email","args":["emailAddress"]},"signup":{"verb":"POST","url":"/api/v1/customers/signup","args":["emailAddress","password","organization","firstName","lastName","signupReason"]},"updateProfile":{"verb":"POST","url":"/api/v1/account/update-profile","args":["firstName","lastName","organization","emailAddress"]},"updatePassword":{"verb":"POST","url":"/api/v1/account/update-password","args":["oldPassword","newPassword"]},"updateBillingCard":{"verb":"POST","url":"/api/v1/account/update-billing-card","args":["stripeToken","billingCardLast4","billingCardBrand","billingCardExpMonth","billingCardExpYear"]},"login":{"verb":"POST","url":"/api/v1/customers/login","args":["emailAddress","password","rememberMe"]},"logout":{"verb":"GET","url":"/api/v1/account/logout","args":[]},"createQuote":{"verb":"POST","url":"/api/v1/customers/create-quote","args":["numberOfHosts"]},"saveBillingInfoAndSubscribe":{"verb":"POST","url":"/api/v1/customers/save-billing-info-and-subscribe","args":["quoteId","organization","firstName","lastName","paymentSource"]},"updatePasswordAndLogin":{"verb":"POST","url":"/api/v1/entrance/update-password-and-login","args":["password","token"]},"deliverDemoSignup":{"verb":"POST","url":"/api/v1/deliver-demo-signup","args":["emailAddress"]},"createOrUpdateOneNewsletterSubscription":{"verb":"POST","url":"/api/v1/create-or-update-one-newsletter-subscription","args":["emailAddress","subscribeTo"]},"unsubscribeFromAllNewsletters":{"verb":"GET","url":"/api/v1/unsubscribe-from-all-newsletters","args":["emailAddress"]},"generateLicenseKey":{"verb":"POST","url":"/api/v1/admin/generate-license-key","args":["numberOfHosts","organization","expiresAt"]},"createVantaAuthorizationRequest":{"verb":"POST","url":"/api/v1/create-vanta-authorization-request","args":["emailAddress","fleetInstanceUrl","fleetApiKey"]},"deliverMdmBetaSignup":{"verb":"POST","url":"/api/v1/deliver-mdm-beta-signup","args":["emailAddress","fullName","jobTitle","numberOfHosts"]},"deliverAppleCsr":{"verb":"POST","url":"/api/v1/deliver-apple-csr","args":["unsignedCsrData"]},"deliverPremiumUpgradeForm":{"verb":"POST","url":"/api/v1/deliver-premium-upgrade-form","args":["organization","monthsUsingFleetFree","emailAddress","numberOfHosts"]}}
methods: {"downloadSitemap":{"verb":"GET","url":"/sitemap.xml","args":[]},"downloadRssFeed":{"verb":"GET","url":"/rss/:categoryName","args":["categoryName"]},"receiveUsageAnalytics":{"verb":"POST","url":"/api/v1/webhooks/receive-usage-analytics","args":["anonymousIdentifier","fleetVersion","licenseTier","numHostsEnrolled","numUsers","numTeams","numPolicies","numLabels","softwareInventoryEnabled","vulnDetectionEnabled","systemUsersEnabled","hostStatusWebhookEnabled","numWeeklyActiveUsers","numWeeklyPolicyViolationDaysActual","numWeeklyPolicyViolationDaysPossible","hostsEnrolledByOperatingSystem","hostsEnrolledByOrbitVersion","hostsEnrolledByOsqueryVersion","storedErrors","numHostsNotResponding","organization"]},"receiveFromGithub":{"verb":"GET","url":"/api/v1/webhooks/github","args":["botSignature","action","sender","repository","changes","issue","comment","pull_request","label"]},"receiveFromStripe":{"verb":"POST","url":"/api/v1/webhooks/receive-from-stripe","args":["id","type","data","webhookSecret"]},"deliverContactFormMessage":{"verb":"POST","url":"/api/v1/deliver-contact-form-message","args":["emailAddress","topic","firstName","lastName","message"]},"sendPasswordRecoveryEmail":{"verb":"POST","url":"/api/v1/entrance/send-password-recovery-email","args":["emailAddress"]},"signup":{"verb":"POST","url":"/api/v1/customers/signup","args":["emailAddress","password","organization","firstName","lastName","signupReason"]},"updateProfile":{"verb":"POST","url":"/api/v1/account/update-profile","args":["firstName","lastName","organization","emailAddress"]},"updatePassword":{"verb":"POST","url":"/api/v1/account/update-password","args":["oldPassword","newPassword"]},"updateBillingCard":{"verb":"POST","url":"/api/v1/account/update-billing-card","args":["stripeToken","billingCardLast4","billingCardBrand","billingCardExpMonth","billingCardExpYear"]},"login":{"verb":"POST","url":"/api/v1/customers/login","args":["emailAddress","password","rememberMe"]},"logout":{"verb":"GET","url":"/api/v1/account/logout","args":[]},"createQuote":{"verb":"POST","url":"/api/v1/customers/create-quote","args":["numberOfHosts"]},"saveBillingInfoAndSubscribe":{"verb":"POST","url":"/api/v1/customers/save-billing-info-and-subscribe","args":["quoteId","organization","firstName","lastName","paymentSource"]},"updatePasswordAndLogin":{"verb":"POST","url":"/api/v1/entrance/update-password-and-login","args":["password","token"]},"deliverDemoSignup":{"verb":"POST","url":"/api/v1/deliver-demo-signup","args":["emailAddress"]},"createOrUpdateOneNewsletterSubscription":{"verb":"POST","url":"/api/v1/create-or-update-one-newsletter-subscription","args":["emailAddress","subscribeTo"]},"unsubscribeFromAllNewsletters":{"verb":"GET","url":"/api/v1/unsubscribe-from-all-newsletters","args":["emailAddress"]},"generateLicenseKey":{"verb":"POST","url":"/api/v1/admin/generate-license-key","args":["numberOfHosts","organization","expiresAt"]},"createVantaAuthorizationRequest":{"verb":"POST","url":"/api/v1/create-vanta-authorization-request","args":["emailAddress","fleetInstanceUrl","fleetApiKey"]},"deliverMdmBetaSignup":{"verb":"POST","url":"/api/v1/deliver-mdm-beta-signup","args":["emailAddress","fullName","jobTitle","numberOfHosts"]},"deliverLaunchPartySignup":{"verb":"POST","url":"/api/v1/deliver-launch-party-signup","args":["emailAddress","fullName","jobTitle","phoneNumber"]},"deliverAppleCsr":{"verb":"POST","url":"/api/v1/deliver-apple-csr","args":["unsignedCsrData"]},"deliverPremiumUpgradeForm":{"verb":"POST","url":"/api/v1/deliver-premium-upgrade-form","args":["organization","monthsUsingFleetFree","emailAddress","numberOfHosts"]}}
/* eslint-enable */
});

View File

@ -0,0 +1,69 @@
parasails.registerPage('launch-party', {
// ╦╔╗╔╦╔╦╗╦╔═╗╦ ╔═╗╔╦╗╔═╗╔╦╗╔═╗
// ║║║║║ ║ ║╠═╣║ ╚═╗ ║ ╠═╣ ║ ║╣
// ╩╝╚╝╩ ╩ ╩╩ ╩╩═╝ ╚═╝ ╩ ╩ ╩ ╩ ╚═╝
data: {
formData: { /* … */ },
// For tracking client-side validation errors in our form.
// > Has property set to `true` for each invalid property in `formData`.
formErrors: { /* … */ },
// Form rules
formRules: {
firstName: {required: true },
lastName: {required: true },
emailAddress: {required: true, isEmail: true},
},
cloudError: '',
// Syncing / loading state
syncing: false,
showSignupFormSuccess: false,
// Modal
modal: '',
},
// ╦ ╦╔═╗╔═╗╔═╗╦ ╦╔═╗╦ ╔═╗
// ║ ║╠╣ ║╣ ║ ╚╦╝║ ║ ║╣
// ╩═╝╩╚ ╚═╝╚═╝ ╩ ╚═╝╩═╝╚═╝
beforeMount: function() {
//…
},
mounted: async function() {
if(window.location.search && window.location.search === '?showForm') {
this.modal = 'happy-hour-waitlist';
}
},
// ╦╔╗╔╔╦╗╔═╗╦═╗╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
// ║║║║ ║ ║╣ ╠╦╝╠═╣║ ║ ║║ ║║║║╚═╗
// ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
methods: {
clickOpenModal: function() {
this.modal = 'happy-hour-waitlist';
},
closeModal: async function () {
this.modal = '';
await this._resetForms();
},
typeClearOneFormError: async function(field) {
if(this.formErrors[field]){
this.formErrors = _.omit(this.formErrors, field);
}
},
submittedForm: function() {
this.showSignupFormSuccess = true;
},
_resetForms: async function() {
this.cloudError = '';
this.formData = {};
this.formRules = {};
this.formErrors = {};
await this.forceRender();
},
}
});

View File

@ -78,4 +78,5 @@
@import 'pages/press-kit.less';
// Imagine = landing pages for Marketing
@import 'pages/imagine/launch-party.less';
@import 'pages/imagine/unused-software.less';

View File

@ -0,0 +1,192 @@
#launch-party {
padding-top: 60px;
padding-left: 40px;
padding-right: 40px;
max-width: 760px;
margin-left: auto;
margin-right: auto;
overflow-x: hidden;
h1 {
font-weight: 800;
font-size: 36px;
line-height: 40px;
margin-bottom: 12px;
}
h2 {
font-weight: 800;
font-size: 24px;
line-height: 34px;
}
p {
margin-bottom: 0;
font-size: 16px;
line-height: 24px;
color: #515774;
}
[purpose='map-container'] {
width: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
align-content: center;
align-items: center;
border-radius: 8px;
}
[purpose='meet-the-team'] {
width: 100%;
img {
width: 210px;
}
}
[purpose='hero-text'] {
max-width: 420px;
p {
font-size: 18px;
}
}
[purpose='hero'] {
background-image: url('/images/rsa-map-hero-680x480@2x.png');
height: 530px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
width: 100%;
margin-bottom: 40px;
border-radius: 8px;
}
[purpose='rsa-cta'] {
background: #F9FAFC;
padding: 16px 24px;
width: 100%;
border: 1px solid #E2E4EA;
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 40px;
text-align: center;
p {
font-weight: 700;
color: #515774;
}
}
[purpose='cta-button'] {
cursor: pointer;
font-size: 18px;
font-weight: 700;
margin-right: 32px;
background: @core-vibrant-red;
border-radius: 8px;
padding-left: 32px;
padding-right: 32px;
height: 48px;
display: flex;
justify-content: center;
align-items: center;
color: #FFF;
position: relative;
max-width: 420px;
width: 100%;
}
[purpose='cta-button']::before {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
opacity: 1;
content: ' ';
position: absolute;
top: 0;
left: -5px;
width: 60%;
height: 100%;
transform: skew(-10deg);
transition: left 0.5s ease-in, opacity 0.50s ease-in, width 0.5s ease-in;
}
[purpose='cta-button']:hover:before {
opacity: 0;
left: 160px;
width: 110%;
}
[purpose='section'] {
margin-bottom: 40px;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
[purpose='checklist'] {
margin-bottom: 40px;
p {
padding-left: 28px;
text-indent: -28px;
margin-bottom: 16px;
}
p::before {
content: ' ';
background-image: url('/images/icon-checkmark-circle.svg');
background-size: 16px 16px;
display: inline-block;
position: relative;
top: 2px;
margin-right: 12px;
width: 16px;
height: 16px;
}
}
[purpose='modal-dialog'] {
padding-left: 15px;
padding-right: 15px;
max-width: 100%;
}
[purpose='modal-content'] {
margin-top: 40px;
padding-top: 80px;
padding-left: 80px;
padding-right: 80px;
padding-bottom: 120px;
margin-right: auto;
margin-left: auto;
max-width: 680px;
width: 100%;
}
[purpose='modal-form'] {
input {
border-radius: 6px;
height: 48px;
}
label {
font-weight: 700;
}
width: 100%;
}
[purpose='submit-button'] {
border-radius: 8px;
}
@media(max-width: 756px) {
[purpose='modal-content'] {
padding: 40px;
}
}
@media(max-width: 575px) {
padding-left: 20px;
padding-right: 20px;
[purpose='hero'] {
background-image: url('/images/rsa-map-hero-small-335x480@2x.png');
background-size: cover;
}
}
@media(max-width: 459px) {
[purpose='meet-the-team'] {
img:first-of-type {
margin-top: 24px;
}
}
}
@media(max-width: 375px) {
[purpose='modal-content'] {
padding: 40px 20px 40px 20px;
}
h1 {
font-size: 28px;
}
}
}

View File

@ -293,11 +293,22 @@ module.exports.routes = {
// ╦╔╦╗╔═╗╔═╗╦╔╗╔╔═╗ ┌─┬ ┌─┐┌┐┌┌┬┐┬┌┐┌┌─┐ ┌─┐┌─┐┌─┐┌─┐┌─┐─┐
// ║║║║╠═╣║ ╦║║║║║╣ │ │ ├─┤│││ │││││││ ┬ ├─┘├─┤│ ┬├┤ └─┐ │
// ╩╩ ╩╩ ╩╚═╝╩╝╚╝╚═╝ └─┴─┘┴ ┴┘└┘─┴┘┴┘└┘└─┘ ┴ ┴ ┴└─┘└─┘└─┘─┘
'GET /imagine/unused-software': { action: 'imagine/view-unused-software' },
'GET /imagine/launch-party': {
action: 'imagine/view-launch-party',
locals: {
layout: 'layouts/layout-sandbox',
pageTitleForMeta: 'Fleet MDM launch party waitlist | Fleet for osquery',
pageDescriptionForMeta: 'Celebrate with us at our MDM launch party on April 27th, 2023 at Press Club. Meet our team, enjoy drinks and learn how our MDM solution can benefit your organization.',
headerCTAHidden: true,
}
},
// ╦ ╔═╗╔═╗╔═╗╔═╗╦ ╦ ╦═╗╔═╗╔╦╗╦╦═╗╔═╗╔═╗╔╦╗╔═╗
// ║ ║╣ ║ ╦╠═╣║ ╚╦╝ ╠╦╝║╣ ║║║╠╦╝║╣ ║ ║ ╚═╗
@ -452,4 +463,5 @@ module.exports.routes = {
'POST /api/v1/deliver-mdm-beta-signup': { action: 'deliver-mdm-beta-signup' },
'POST /api/v1/deliver-apple-csr ': { action: 'deliver-apple-csr', csrf: false},
'POST /api/v1/deliver-premium-upgrade-form': { action: 'deliver-premium-upgrade-form' },
'POST /api/v1/deliver-launch-party-signup': { action: 'imagine/deliver-launch-party-signup' },
};

View File

@ -253,6 +253,7 @@
<script src="/js/pages/get-started.page.js"></script>
<script src="/js/pages/handbook/basic-handbook.page.js"></script>
<script src="/js/pages/homepage.page.js"></script>
<script src="/js/pages/imagine/launch-party.page.js"></script>
<script src="/js/pages/imagine/unused-software.page.js"></script>
<script src="/js/pages/landing.page.js"></script>
<script src="/js/pages/legal/privacy.page.js"></script>

View File

@ -254,6 +254,7 @@
<script src="/js/pages/get-started.page.js"></script>
<script src="/js/pages/handbook/basic-handbook.page.js"></script>
<script src="/js/pages/homepage.page.js"></script>
<script src="/js/pages/imagine/launch-party.page.js"></script>
<script src="/js/pages/imagine/unused-software.page.js"></script>
<script src="/js/pages/landing.page.js"></script>
<script src="/js/pages/legal/privacy.page.js"></script>

View File

@ -382,6 +382,7 @@
<script src="/js/pages/get-started.page.js"></script>
<script src="/js/pages/handbook/basic-handbook.page.js"></script>
<script src="/js/pages/homepage.page.js"></script>
<script src="/js/pages/imagine/launch-party.page.js"></script>
<script src="/js/pages/imagine/unused-software.page.js"></script>
<script src="/js/pages/landing.page.js"></script>
<script src="/js/pages/legal/privacy.page.js"></script>

View File

@ -457,6 +457,7 @@
<script src="/js/pages/get-started.page.js"></script>
<script src="/js/pages/handbook/basic-handbook.page.js"></script>
<script src="/js/pages/homepage.page.js"></script>
<script src="/js/pages/imagine/launch-party.page.js"></script>
<script src="/js/pages/imagine/unused-software.page.js"></script>
<script src="/js/pages/landing.page.js"></script>
<script src="/js/pages/legal/privacy.page.js"></script>

View File

@ -0,0 +1,106 @@
<div id="launch-party" v-cloak>
<div class="container mx-auto d-flex flex-column align-items-center px-0">
<div purpose="hero">
<div purpose="hero-text" class="text-center mx-auto">
<h1>The path to a better<br> MDM starts here</h1>
<p>Introducing an MDM your security team will love</p>
</div>
</div>
<div purpose="rsa-cta">
<h2>Launch party at Press Club</h2>
<p class="mb-2"><strong>April 27, 2023 | 5 - 8pm PT</strong></p>
<a class="mx-auto" purpose="cta-button" @click="clickOpenModal()">Join the wait list</a>
</div>
<h2 class="text-center mb-4">Join us in celebrating Fleets new MDM features</h2>
<div purpose="checklist" class="mx-auto">
<p>Report on disk encryption status</p>
<p>User-initiated device enrollment</p>
<p>Remotely enforce OS settings</p>
<p>Zero-touch device setup</p>
<p>Remotely update OS version</p>
<p>Low-level MDM commands</p>
<p>Keep OS up to date through reminders</p>
<p>Encrypt computer hard disks</p>
<p>Manage queued MDM commands</p>
<p>Remotely lock and wipe computers</p>
<p>Trigger a workflow based on a failing policy</p>
<p>Update apps on computers</p>
</div>
<div purpose="section">
<h2 class="mb-4">Enjoy drinks and talk to the Fleet team</h2>
<div purpose="meet-the-team" class="d-flex flex-row justify-content-md-between justify-content-around flex-wrap">
<img alt="Mike McNeil - Co-founder, CEO Fleet" class="mb-4" style="height: 223px;" src="/images/rsa-team-mike-210x223@2x.png">
<img alt="Zach Wasserman - Co-founder, CTO Fleet & Co-creator, osquery" style="height: 242px;" class="mb-4" src="/images/rsa-team-zach-210x242@2x.png">
<img alt="Reid Christian - General Partner, CRV" class="mb-4" style="height: 223px;"src="/images/rsa-team-reid-210x223@2x.png">
</div>
</div>
<div purpose="section">
<div class="mb-4 text-center">
<h2 class="mb-2">Easy walking distance from RSA</h2>
</div>
<div purpose="map-container">
<a href="https://goo.gl/maps/YHD5S3fJcYz46r1h6" target="_blank"><img alt="A map showing the location of Press Club" style="width: 680px;" src="/images/rsa-static-map-681x342@2x.png"></a>
</div>
</div>
<div purpose="rsa-cta">
<h2>Launch party at Press Club</h2>
<p class="mb-2"><strong>April 27, 2023 | 5 - 8pm PT</strong></p>
<a class="mx-auto" purpose="cta-button" @click="clickOpenModal()">Join the wait list</a>
</div>
<hr>
<div style="display: inline-flex; padding-bottom: 40px">
<a href="https://fleetdm.com"><img style="height: 20px; width: 20px; margin-right: 24px;" alt="Fleet logo" src="/images/logo-fleet-20x20@2x.png"></a>
<a href="https://twitter.com/fleetctl"><img style="height: 20px; width: 24px; margin-right: 24px;" alt="Follow Fleet on Twitter" src="/images/logo-twitter-50x44@2x.png"></a>
<a href="https://fleetdm.com/slack"><img style="height: 20px; width: 20px;" alt="Join the osquery Slack community" src="/images/logo-slack-24x24@2x.png"></a>
</div>
</div>
<modal v-if="modal === 'happy-hour-waitlist'" @close="closeModal()" data-backdrop="false" v-cloak purpose="modal">
<div class="d-flex flex-column justify-content-around align-items-center" purpose="modal-container">
<div class="modal-header" v-if="!showSignupFormSuccess">
<h1>Join us at Fleets MDM<br> launch party</h1>
</div>
<div purpose="modal-form" class="pt-5" v-if="!showSignupFormSuccess">
<ajax-form action="deliverLaunchPartySignup" :syncing.sync="syncing" :cloud-error.sync="cloudError" :form-data="formData" :form-rules="formRules" :form-errors.sync="formErrors" @submitted="submittedForm()">
<div class="d-flex flex-md-row flex-column">
<div class="form-group pr-0 pr-md-3 w-100">
<label for="firstName">First Name <span class="text-danger">*</span></label>
<input class="form-control" id="firstName" :class="[formErrors.firstName ? 'is-invalid' : '']" v-model.trim="formData.firstName" @input="typeClearOneFormError('firstName')" focus-first>
<div class="invalid-feedback" v-if="formErrors.firstName">Please enter your first name.</div>
</div>
<div class="form-group w-100">
<label for="lastName">Last Name <span class="text-danger">*</span></label>
<input class="form-control" id="lastName" :class="[formErrors.lastName ? 'is-invalid' : '']" v-model.trim="formData.lastName" @input="typeClearOneFormError('lastName')">
<div class="invalid-feedback" v-if="formErrors.lastName">Please enter your last name.</div>
</div>
</div>
<div class="form-group">
<label for="emailAddress">Work Email <span class="text-danger">*</span></label>
<input class="form-control" id="emailAddress" :class="[formErrors.emailAddress ? 'is-invalid' : '']" v-model.trim="formData.emailAddress" @input="typeClearOneFormError('emailAddress')">
<div class="invalid-feedback" v-if="formErrors.emailAddress">This doesnt appear to be a valid email address</div>
</div>
<div class="form-group">
<label for="phoneNumber">Phone</label>
<input class="form-control" id="phoneNumber" :class="[formErrors.phoneNumber ? 'is-invalid' : '']" v-model.trim="formData.phoneNumber" @input="typeClearOneFormError('phoneNumber')">
<div class="invalid-feedback" v-if="formErrors.phoneNumber">This doesnt appear to be a valid email address</div>
</div>
<div class="form-group">
<label for="jobTitle">Job title</label>
<input class="form-control" id="jobTitle" :class="[formErrors.jobTitle ? 'is-invalid' : '']" v-model.trim="formData.jobTitle" placeholder="E.g., Client Platform Engineer" @input="typeClearOneFormError('jobTitle')">
<div class="invalid-feedback" v-if="formErrors.jobTitle">Please enter your job title.
</div>
</div>
<cloud-error v-if="cloudError"></cloud-error>
<div class="border-0 justify-content-center">
<ajax-button purpose="submit-button" spinner="true" type="submit" :syncing="syncing" class="btn btn-sm btn-block btn-primary">Join the wait list</ajax-button>
</div>
</ajax-form>
</div>
<div purpose="modal-form" class="text-center" v-else>
<h3>You're all set!</h3>
<p>A Fleet team member will reach out via email with more information.</p>
</div>
</div>
</modal>
</div>
<%- /* Expose server-rendered data as window.SAILS_LOCALS :: */ exposeLocalsToBrowser() %>