Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions website/assets/js/components/signup-modal.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ parasails.registerComponent('signupModal', {
firstName: {required: true},
lastName: {required: true},
emailAddress: {required: true, isEmail: true},
password: {required: true},
password: {required: true, minLength: 8},
},
// Login form
loginFormData: {},
Expand Down Expand Up @@ -81,68 +81,68 @@ parasails.registerComponent('signupModal', {
</div>
<ajax-form action="signup" purpose="modal-form" class="self-service-register" :syncing.sync="syncing" :cloud-error.sync="cloudError" :form-errors.sync="signupFormErrors" :form-data="signupFormData" :form-rules="signupFormRules" @submitted="submittedSignupForm()" v-if="formToDisplay === 'signup'">
<div class="form-group">
<label for="email-address">Work email *</label>
<input tabindex="1" class="form-control" id="email-address" :class="[signupFormErrors.emailAddress ? 'is-invalid' : '']" v-model.trim="signupFormData.emailAddress" @input="typeClearOneFormError('emailAddress')">
<label purpose="modal-form-label" for="email-address">Work email *</label>
<input tabindex="1" purpose="modal-form-input" class="form-control" id="email-address" :class="[signupFormErrors.emailAddress ? 'is-invalid' : '']" v-model.trim="signupFormData.emailAddress" @input="typeClearOneFormError('emailAddress')">
<div class="invalid-feedback" v-if="signupFormErrors.emailAddress" focus-first>This doesn’t appear to be a valid email address</div>
</div>
<div class="form-group">
<label for="password">Choose a password *</label>
<input tabindex="2" class="form-control" id="password" type="password" :class="[signupFormErrors.password ? 'is-invalid' : '']" v-model.trim="signupFormData.password" autocomplete="new-password" @input="typeClearOneFormError('password')">
<label purpose="modal-form-label" for="password">Choose a password *</label>
<input tabindex="2" purpose="modal-form-input" class="form-control" id="password" type="password" :class="[signupFormErrors.password ? 'is-invalid' : '']" v-model.trim="signupFormData.password" autocomplete="new-password" @input="typeClearOneFormError('password')">
<div class="invalid-feedback" v-if="signupFormErrors.password === 'minLength'">Password too short.</div>
<div class="invalid-feedback" v-if="signupFormErrors.password === 'required'">Please enter a password.</div>
<p class="mt-2 small"> Minimum length is 8 characters</p>
<p purpose="modal-form-note" class="mt-2"> Minimum length is 8 characters</p>
</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>
<input tabindex="4" class="form-control" id="first-name" type="text" :class="[signupFormErrors.firstName ? 'is-invalid' : '']" v-model.trim="signupFormData.firstName" autocomplete="first-name" @input="typeClearOneFormError('firstName')">
<label purpose="modal-form-label" for="first-name">First name *</label>
<input tabindex="4" purpose="modal-form-input" class="form-control" id="first-name" type="text" :class="[signupFormErrors.firstName ? 'is-invalid' : '']" v-model.trim="signupFormData.firstName" autocomplete="first-name" @input="typeClearOneFormError('firstName')">
<div class="invalid-feedback" v-if="signupFormErrors.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>
<input tabindex="5" class="form-control" id="last-name" type="text" :class="[signupFormErrors.lastName ? 'is-invalid' : '']" v-model.trim="signupFormData.lastName" autocomplete="last-name" @input="typeClearOneFormError('lastName')">
<label purpose="modal-form-label" for="last-name">Last name *</label>
<input tabindex="5" purpose="modal-form-input" class="form-control" id="last-name" type="text" :class="[signupFormErrors.lastName ? 'is-invalid' : '']" v-model.trim="signupFormData.lastName" autocomplete="last-name" @input="typeClearOneFormError('lastName')">
<div class="invalid-feedback" v-if="signupFormErrors.lastName">Please enter your last name.</div>
</div>
</div>
</div>
<cloud-error v-if="cloudError==='emailAlreadyInUse'">
This email is already linked to a Fleet account.<br> Please <a @click="formToDisplay = 'login'">sign in</a> with your email and password.
This email is already linked to a Fleet account.<br> Please <a purpose="modal-form-link" @click="formToDisplay = 'login'">sign in</a> with your email and password.
</cloud-error>
<cloud-error v-if="cloudError === 'invalidEmailDomain'">
Please enter your work or school email address.
</cloud-error>
<blockquote purpose="tip" v-if="cloudError === 'invalidEmailDomain'">
<img src="/images/icon-info-16x16@2x.png" alt="An icon indicating that this section has important information">
<div class="d-block">
<p>Don’t have a work email? Try a local demo of <a href="/try-fleet">Fleet Free</a> instead.</p>
<p>Don’t have a work email? Try a local demo of <a purpose="modal-form-link" href="/try-fleet">Fleet Free</a> instead.</p>
</div>
</blockquote>
<cloud-error purpose="cloud-error" v-if="cloudError && !['emailAlreadyInUse', 'invalidEmailDomain'].includes(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 tabindex="6" 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>
<ajax-button tabindex="7" purpose="submit-button" type="button" :syncing="syncing" class="btn btn-block btn-lg btn-primary mt-4" v-if="cloudError" @click="clickResetForm()">Try again</ajax-button>
<p purpose="modal-form-note">By signing up you agree to our <a purpose="modal-form-link" href="/legal/privacy">privacy policy</a> and <a purpose="modal-form-link" href="/terms">terms of service</a>.</p>
<ajax-button tabindex="6" purpose="modal-form-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>
<ajax-button tabindex="7" purpose="modal-form-submit-button" type="button" :syncing="syncing" class="btn btn-block btn-lg btn-primary mt-4" v-if="cloudError" @click="clickResetForm()">Try again</ajax-button>
</ajax-form>
<ajax-form class="w-100" action="login" purpose="modal-form" :syncing.sync="syncing" :cloud-error.sync="cloudError" :form-data="loginFormData" :form-rules="loginFormRules" :form-errors.sync="loginFormErrors" @submitted="submittedLoginForm()" v-else>
<div class="form-group">
<label for="email">Email</label>
<input tabindex="1" type="email" class="form-control" :class="[loginFormErrors.emailAddress ? 'is-invalid' : '']" v-model.trim="loginFormData.emailAddress" autocomplete="email" focus-first>
<label purpose="modal-form-label" for="email">Email</label>
<input tabindex="1" type="email" purpose="modal-form-input" class="form-control" :class="[loginFormErrors.emailAddress ? 'is-invalid' : '']" v-model.trim="loginFormData.emailAddress" autocomplete="email" focus-first>
<div class="invalid-feedback" v-if="loginFormErrors.emailAddress">Please provide a valid email address.</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input tabindex="2" type="password" class="form-control" :class="[loginFormErrors.password ? 'is-invalid' : '']" v-model.trim="loginFormData.password" autocomplete="current-password">
<label purpose="modal-form-label" for="password">Password</label>
<input tabindex="2" type="password" purpose="modal-form-input" class="form-control" :class="[loginFormErrors.password ? 'is-invalid' : '']" v-model.trim="loginFormData.password" autocomplete="current-password">
<div class="invalid-feedback" v-if="loginFormErrors.password">Please enter your password.</div>
</div>
<cloud-error v-if="cloudError === 'noUser'">The email address provided doesn't match an existing account. Create an account <a @click="formToDisplay = 'signup'">here</a>.</cloud-error>
<cloud-error v-if="cloudError === 'noUser'">The email address provided doesn't match an existing account. Create an account <a purpose="modal-form-link" @click="formToDisplay = 'signup'">here</a>.</cloud-error>
<cloud-error v-else-if="cloudError === 'badCombo'">Something’s not quite right with your email or password.</cloud-error>
<cloud-error v-else-if="cloudError"></cloud-error>
<div class="pb-3">
<ajax-button tabindex="3" :syncing="syncing" spinner="true" purpose="submit-button" class="btn-primary mt-4 btn-lg btn-block">Sign in</ajax-button>
<ajax-button tabindex="3" :syncing="syncing" spinner="true" purpose="modal-form-submit-button" class="btn-primary mt-4 btn-lg btn-block">Sign in</ajax-button>
</div>
<span class="text-center small"><a href="/customers/forgot-password">Forgot your password?</a></span>
<span purpose="modal-form-note" class="text-center"><a purpose="modal-form-link" href="/customers/forgot-password">Forgot your password?</a></span>
</ajax-form>
</div>
</div><!-- /.modal-content -->
Expand Down
102 changes: 64 additions & 38 deletions website/assets/styles/components/signup-modal.component.less
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,24 @@
}
}
[purpose='form-switch'] {

[purpose='form-option'] {
user-select: none;
cursor: pointer;
width: fit-content;
padding: 8px 16px 8px 0px;
margin-bottom: 4px;
margin-bottom: 4px !important;//lesshint-disable-line importantRule
display: flex;
flex-direction: row;
align-items: center;
border-radius: 7px;
border: none;
color: #515774;
font-size: 14px;
font-weight: 400;
color: #515774 !important;//lesshint-disable-line importantRule
font-size: 14px !important;//lesshint-disable-line importantRule
font-weight: 400 !important;//lesshint-disable-line importantRule
line-height: 150%;
white-space: nowrap;
height: fit-content;
input {
input[type='radio'] {
cursor: pointer;
margin-right: 8px;
display: none;
Expand Down Expand Up @@ -66,56 +65,82 @@
transform: scale(1);
}
}
.form-control {
height: 48px;
}
}


}

[purpose='modal-form'] {
.form-control {
[purpose='modal-form-input'] {
height: 40px;
border-radius: 6px;
}
.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;
}
label {
color: var(--text-text-brand, #192147);

/* Body SM (bold) */
[purpose='modal-form-label'] {
color: #192147;
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 700;
line-height: 21px; /* 150% */
}
.small {
font-size: 12px;
[purpose='modal-form-note'] {
font-size: 12px !important;//lesshint-disable-line importantRule
}

[purpose='modal-form-link'] {
color: @core-fleet-black-75 !important;//lesshint-disable-line importantRule
cursor: pointer;
font-size: 12px !important;//lesshint-disable-line importantRule
text-decoration: underline !important;//lesshint-disable-line importantRule
text-underline-offset: 4px !important;//lesshint-disable-line importantRule
text-decoration-color: #C5C7D1 !important;//lesshint-disable-line importantRule
&:hover {
color: @core-fleet-black !important;//lesshint-disable-line importantRule
text-decoration-color: @core-fleet-black !important;//lesshint-disable-line importantRule
}
}
[parasails-component='cloud-error'] {
p {
color: @core-vibrant-red;
color: @core-vibrant-red !important;//lesshint-disable-line importantRule
font-size: 14px !important;//lesshint-disable-line importantRule
a {
text-decoration-color: @core-vibrant-red !important;//lesshint-disable-line importantRule
color: @core-vibrant-red !important;//lesshint-disable-line importantRule
font-size: unset !important;//lesshint-disable-line importantRule
&:hover {
color: darken(@core-vibrant-red, 20%) !important; //lesshint-disable-line importantRule
text-decoration-color: darken(@core-vibrant-red, 20%) !important;//lesshint-disable-line importantRule
}
}
}
}
[purpose='tip'] {
margin: 16px 0 32px;
background: #F4F4FF;
padding: 16px;
border-radius: 8px;
display: flex;
img {
display: flex;
margin: 4px 12px 0 0;
height: 16px;
width: 16px;
padding: 0px;
}
p {
display: block;
margin-bottom: 16px;
line-height: 24px;
font-size: 14px !important;//lesshint-disable-line importantRule
a {
font-size: unset !important;//lesshint-disable-line importantRule
color: unset !important;//lesshint-disable-line importantRule
}
}
p:last-child {
margin-bottom: 0px;
}
}
}
[purpose='submit-button'] {
[purpose='modal-form-submit-button'] {

margin-left: auto;
margin-right: auto;
Expand Down Expand Up @@ -296,3 +321,4 @@
}
}


1 change: 1 addition & 0 deletions website/views/pages/admin/query-generator.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@

</div>
</div>
<signup-modal></signup-modal>
</div>
<%- /* Expose server-rendered data as window.SAILS_LOCALS :: */ exposeLocalsToBrowser() %>
2 changes: 1 addition & 1 deletion website/views/pages/query-library.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div purpose="page-headline" class="d-flex flex-column">
<h2>Queries</h2>
<p class="mb-1">A collection of optional queries you can run anytime. Contributions welcome <a target="_blank" href="https://github.com/fleetdm/fleet/edit/main/docs/queries.yml" no-icon>over on GitHub.</a></p>
<p>Want to create your own? Our <a href="/query-generator">query robot</a> can help</p>
<p>Want to create your own? Our <a href="/query-generator">query robot</a> can help.</p>
</div>
</div>
<div purpose="platform-filters" :class="[bowser.windows ? 'detected-windows' : '']" class="d-flex justify-content-center">
Expand Down
Loading