From 31f8c7e5483a7f7f770f170845b6bca93eb5922c Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 16 May 2024 15:38:09 -0500 Subject: [PATCH 1/3] Website: Create new Salesforce helper, update contact form actions and signup action. (#19082) Changes: - Added a new helper: `salesforce/update-or-create-contact-and-account-and-create-lead`, a wrapper for the `update-or-create-contact-and-account` and `create-lead` helpers that is intended to be run in the background. - Updated the `signup`, `deliver-contact-form-message`, and `deliver-talk-to-us-form-submission` actions to use the new helper --- .../deliver-contact-form-message.js | 37 +++----- .../deliver-talk-to-us-form-submission.js | 44 ++++----- website/api/controllers/entrance/signup.js | 18 ++-- ...ate-contact-and-account-and-create-lead.js | 90 +++++++++++++++++++ 4 files changed, 123 insertions(+), 66 deletions(-) create mode 100644 website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js diff --git a/website/api/controllers/deliver-contact-form-message.js b/website/api/controllers/deliver-contact-form-message.js index 532308baf2..03696e07b2 100644 --- a/website/api/controllers/deliver-contact-form-message.js +++ b/website/api/controllers/deliver-contact-form-message.js @@ -71,31 +71,18 @@ module.exports = { `Name: ${firstName + ' ' + lastName}, Email: ${emailAddress}, Message: ${message ? message : 'No message.'}` }); - await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ - emailAddress: emailAddress, - firstName: firstName, - lastName: lastName, - }); - - - // Send a POST request to Zapier - await sails.helpers.http.post( - 'https://hooks.zapier.com/hooks/catch/3627242/3cxcriz/', - { - 'emailAddress': emailAddress, - 'firstName': firstName, - 'lastName': lastName, - 'message': message, - 'webhookSecret': sails.config.custom.zapierSandboxWebhookSecret - } - ) - .timeout(5000) - .tolerate(['non200Response', 'requestFailed'], (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 a contact form message, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Raw error: ${err}`); - return; - }); - + // Use timers.setImmediate() to update/create CRM records in the background. + require('timers').setImmediate(async ()=>{ + await sails.helpers.salesforce.updateOrCreateContactAndAccountAndCreateLead.with({ + emailAddress: emailAddress, + firstName: firstName, + lastName: lastName, + leadSource: 'Website - Contact forms', + leadDescription: `Sent a contact form message: ${message}`, + }).tolerate((err)=>{ + sails.log.warn(`Background task failed: When a user submitted a contact form message, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Error:`, err.raw); + }); + });//_∏_ (Meanwhile...) } diff --git a/website/api/controllers/deliver-talk-to-us-form-submission.js b/website/api/controllers/deliver-talk-to-us-form-submission.js index d07f2474b4..9978b856f5 100644 --- a/website/api/controllers/deliver-talk-to-us-form-submission.js +++ b/website/api/controllers/deliver-talk-to-us-form-submission.js @@ -74,37 +74,23 @@ module.exports = { throw 'invalidEmailDomain'; } - await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ - emailAddress, - firstName, - lastName, - organization: organization, - primaryBuyingSituation: primaryBuyingSituation === 'eo-security' ? 'Endpoint operations - Security' : primaryBuyingSituation === 'eo-it' ? 'Endpoint operations - IT' : primaryBuyingSituation === 'mdm' ? 'Device management (MDM)' : 'Vulnerability management', - }); - - await sails.helpers.http.post.with({ - url: 'https://hooks.zapier.com/hooks/catch/3627242/3cxwxdo/', - data: { - emailAddress, - firstName, - lastName, - organization, - numberOfHosts, - primaryBuyingSituation, - webhookSecret: sails.config.custom.zapierSandboxWebhookSecret, - } - }) - .timeout(5000) - .tolerate(['non200Response', 'requestFailed'], (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 a contact form message, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Raw error: ${err}`); - return; - }); - - + // Use timers.setImmediate() to update/create CRM records in the background. + require('timers').setImmediate(async ()=>{ + await sails.helpers.salesforce.updateOrCreateContactAndAccountAndCreateLead.with({ + emailAddress: emailAddress, + firstName: firstName, + lastName: lastName, + organization: organization, + numberOfHosts: numberOfHosts, + primaryBuyingSituation: primaryBuyingSituation === 'eo-security' ? 'Endpoint operations - Security' : primaryBuyingSituation === 'eo-it' ? 'Endpoint operations - IT' : primaryBuyingSituation === 'mdm' ? 'Device management (MDM)' : primaryBuyingSituation === 'vm' ? 'Vulnerability management' : undefined, + leadSource: 'Website - Contact forms', + leadDescription: `Submitted the "Talk to us" form.`, + }).tolerate((err)=>{ + sails.log.warn(`Background task failed: When a user submitted the "Talk to us" form, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}. Error:`, err.raw); + }); + });//_∏_ (Meanwhile...) return; - } diff --git a/website/api/controllers/entrance/signup.js b/website/api/controllers/entrance/signup.js index 387cd8f8ae..2aecd88055 100644 --- a/website/api/controllers/entrance/signup.js +++ b/website/api/controllers/entrance/signup.js @@ -138,24 +138,18 @@ the account verification message.)`, .intercept({name: 'UsageError'}, 'invalid') .fetch(); - if(sails.config.environment === 'production') { - let recordIds = await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ + // Use timers.setImmediate() to update/create CRM records in the background. + require('timers').setImmediate(async ()=>{ + await sails.helpers.salesforce.updateOrCreateContactAndAccountAndCreateLead.with({ emailAddress: newEmailAddress, firstName: firstName, lastName: lastName, organization: organization, - }); - - await sails.helpers.salesforce.createLead.with({ - salesforceContactId: recordIds.salesforceContactId, - salesforceAccountId: recordIds.salesforceAccountId, leadSource: 'Website - Sign up', - }) - .tolerate((err)=>{ - sails.log.warn(`When a user signed up, a lead could not be created in the CRM for this email address: ${newEmailAddress}. Error from create-lead helper: ${err}`); - return; + }).tolerate((err)=>{ + sails.log.warn(`Background task failed: When a user (email: ${newEmailAddress} sign up for a fleetdm.com account, a Contact, Account, and Lead record could not be created/updated in the CRM. Error:`, err.raw); }); - } + });//_∏_ (Meanwhile...) // Store the user's new id in their session. this.req.session.userId = newUserRecord.id; diff --git a/website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js b/website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js new file mode 100644 index 0000000000..0b5e8f2023 --- /dev/null +++ b/website/api/helpers/salesforce/update-or-create-contact-and-account-and-create-lead.js @@ -0,0 +1,90 @@ +module.exports = { + + + friendlyName: 'Update or create contact and account and create lead', + + + description: 'Updates or creates a contact and account in Salesforce, then uses the IDs of the created records to create a Lead record.', + + extendedDescription: 'This is a wrapper for the update-or-create-contact-and-account and create-lead helpers used to run both of them in the background with timers.setImmediate().', + + inputs: { + + // Find by… + emailAddress: { type: 'string' }, + linkedinUrl: { type: 'string' }, + + // Set… + firstName: { type: 'string', required: true }, + lastName: { type: 'string', required: true }, + organization: { type: 'string' }, + primaryBuyingSituation: { type: 'string' }, + psychologicalStage: { + type: 'string', + isIn: [ + '1 - Unaware', + '2 - Aware', + '3 - Intrigued', + '4 - Has use case', + '5 - Personally confident', + '6 - Has team buy-in' + ] + }, + // For new leads. + leadDescription: { + type: 'string', + description: 'A description of what this lead is about; e.g. a contact form message, or the size of t-shirt being requested.' + }, + leadSource: { + type: 'string', + required: true, + isIn: [ + 'Website - Contact forms', + 'Website - Sign up', + 'Website - Waitlist', + 'Website - swag request', + ], + }, + numberOfHosts: { type: 'number' }, + }, + + exits: { + + success: { + extendedDescription: 'Note that this deliberately has no return value.', + }, + + }, + + + + fn: async function ({emailAddress, linkedinUrl, firstName, lastName, organization, primaryBuyingSituation, psychologicalStage, leadSource, leadDescription, numberOfHosts}) { + if(sails.config.environment !== 'production') { + sails.log('Skipping Salesforce integration...'); + return; + } + + let recordIds = await sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ + emailAddress, + firstName, + lastName, + organization, + linkedinUrl, + primaryBuyingSituation, + psychologicalStage, + }); + + await sails.helpers.salesforce.createLead.with({ + salesforceContactId: recordIds.salesforceContactId, + salesforceAccountId: recordIds.salesforceAccountId, + leadDescription, + leadSource, + numberOfHosts, + }); + + return; + } + + +}; + From 4d671e63d4ab7ac6a85eb00d313387453e6232b3 Mon Sep 17 00:00:00 2001 From: Victor Lyuboslavsky Date: Thu, 16 May 2024 16:39:36 -0500 Subject: [PATCH 2/3] fleetd-chrome v1.3.1 release (#19087) #18811 * Fixed bug where fleetd-chrome sent multiple read requests to Fleet server at the same time. * Improved console log output messages when Fleet server is down. --- .github/workflows/release-fleetd-chrome-beta.yml | 8 +++++++- .github/workflows/release-fleetd-chrome.yml | 8 +++++++- ee/fleetd-chrome/CHANGELOG.md | 6 ++++++ ee/fleetd-chrome/README.md | 15 +++++++-------- ee/fleetd-chrome/changes/18775-2-main-threads | 1 - .../changes/18940-error-when-server-down | 1 - ee/fleetd-chrome/package-lock.json | 4 ++-- ee/fleetd-chrome/package.json | 2 +- ee/fleetd-chrome/updates-beta.xml | 2 +- ee/fleetd-chrome/updates.xml | 2 +- 10 files changed, 32 insertions(+), 17 deletions(-) delete mode 100644 ee/fleetd-chrome/changes/18775-2-main-threads delete mode 100644 ee/fleetd-chrome/changes/18940-error-when-server-down diff --git a/.github/workflows/release-fleetd-chrome-beta.yml b/.github/workflows/release-fleetd-chrome-beta.yml index 8f50b02d60..90f3d4dc27 100644 --- a/.github/workflows/release-fleetd-chrome-beta.yml +++ b/.github/workflows/release-fleetd-chrome-beta.yml @@ -37,13 +37,19 @@ jobs: run: | npm install && npm run test + - name: Set the version + working-directory: ./ee/fleetd-chrome + run: | + echo "FLEETD_CHROME_VERSION=$(npm pkg get version --workspaces=false | tr -d \")" >> $GITHUB_ENV + - name: Build & sign extension working-directory: ./ee/fleetd-chrome env: CHROME_SIGNING_KEY: ${{ secrets.FLEETD_CHROME_SIGNING_KEY_BETA }} run: | echo -e 'FLEET_URL=""\nFLEET_ENROLL_SECRET=""' > .env - npm install && npm run build + npm run build + sed -i "s/FLEETD_CHROME_VERSION/${{ env.FLEETD_CHROME_VERSION }}/g" updates-beta.xml echo "$CHROME_SIGNING_KEY" > chrome.pem /usr/bin/google-chrome --pack-extension=./dist --pack-extension-key=chrome.pem diff --git a/.github/workflows/release-fleetd-chrome.yml b/.github/workflows/release-fleetd-chrome.yml index 6751d7705e..1655b1c865 100644 --- a/.github/workflows/release-fleetd-chrome.yml +++ b/.github/workflows/release-fleetd-chrome.yml @@ -38,13 +38,19 @@ jobs: run: | npm install && npm run test + - name: Set the version + working-directory: ./ee/fleetd-chrome + run: | + echo "FLEETD_CHROME_VERSION=$(npm pkg get version --workspaces=false | tr -d \")" >> $GITHUB_ENV + - name: Build & sign extension working-directory: ./ee/fleetd-chrome env: CHROME_SIGNING_KEY: ${{ secrets.FLEETD_CHROME_SIGNING_KEY }} run: | echo -e 'FLEET_URL=""\nFLEET_ENROLL_SECRET=""' > .env - npm install && npm run build + npm run build + sed -i "s/FLEETD_CHROME_VERSION/${{ env.FLEETD_CHROME_VERSION }}/g" updates.xml echo "$CHROME_SIGNING_KEY" > chrome.pem /usr/bin/google-chrome --pack-extension=./dist --pack-extension-key=chrome.pem diff --git a/ee/fleetd-chrome/CHANGELOG.md b/ee/fleetd-chrome/CHANGELOG.md index 41f70d9d4b..727727bf3a 100644 --- a/ee/fleetd-chrome/CHANGELOG.md +++ b/ee/fleetd-chrome/CHANGELOG.md @@ -1,3 +1,9 @@ +## fleetd-chrome 1.3.1 (May 20, 2024) + +* Fixed bug where fleetd-chrome sent multiple read requests to Fleet server at the same time. + +* Improved console log output messages when Fleet server is down. + ## fleetd-chrome 1.3.0 (Apr 29, 2024) * Created a fix to recover after a rare RuntimeError coming from sqlite web assembly code by reinitializing the DB. diff --git a/ee/fleetd-chrome/README.md b/ee/fleetd-chrome/README.md index f4486488cd..4eb2ea1505 100644 --- a/ee/fleetd-chrome/README.md +++ b/ee/fleetd-chrome/README.md @@ -67,18 +67,17 @@ npm run test ## Release -1. Update CHANGELOG.md by running `version="X.X.X" make changelog-chrome` +1. At the top of the repo, update CHANGELOG.md by running `version="X.X.X" make changelog-chrome` 2. Review CHANGELOG.md -3. Run `npm version X.X.X` to update the version in `package.json` and `package-lock.json` -4. Update [updates.xml](./updates.xml) and [updates-beta.xml](./updates-beta.xml) versions. -5. Commit the changes and tag the commit with `fleetd-chrome-vX.X.X-beta`. This will trigger the beta release workflow. -6. Once the beta release is tested and PR merged, tag the commit with `fleetd-chrome-vX.X.X`. This will trigger the release workflow. -7. Announce the release in the #help-engineering channel in Slack. +3. At `ee/fleetd-chrome`, run `npm version X.X.X` to update the version in `package.json` and `package-lock.json` +4. Commit the changes and tag the commit with `fleetd-chrome-vX.X.X-beta`. This will trigger the beta release workflow. +5. Once the beta release is tested and PR merged, tag the commit with `fleetd-chrome-vX.X.X`. This will trigger the release workflow. +6. Announce the release in the #help-engineering channel in Slack. -Release a new version via GitHub automation. Update the [package.json](./package.json) and [updates.xml](./updates.xml) versions, then tag a commit with `fleetd-chrome-vX.X.X` to kick off the build and deploy. The build is automatically uploaded to R2 and properly configured clients should be able to update immediately when the job completes. Note that automatic updates seem to only happen about once a day in Chrome -- Hit the "Update" button in `chrome://extensions` to trigger the update manually. +Using GitHub Actions, the build is automatically uploaded to R2 and properly configured clients should be able to update immediately when the job completes. Note that automatic updates seem to only happen about once a day in Chrome -- Hit the "Update" button in `chrome://extensions` to trigger the update manually. ### Beta releases Beta releases are pushed to `https://chrome-beta.fleetdm.com/updates.xml` with the extension ID `bfleegjcoffelppfmadimianphbcdjkb`. -Kick off a beta release by updating the [package.json](./package.json) and [updates-beta.xml](./updates-beta.xml) versions, then tag a commit with `fleetd-chrome-vX.X.X-beta` to kick off the build and deploy. +Kick off a beta release by updating the [package.json](./package.json), then tag a commit with `fleetd-chrome-vX.X.X-beta` to kick off the build and deploy. diff --git a/ee/fleetd-chrome/changes/18775-2-main-threads b/ee/fleetd-chrome/changes/18775-2-main-threads deleted file mode 100644 index 621c94758f..0000000000 --- a/ee/fleetd-chrome/changes/18775-2-main-threads +++ /dev/null @@ -1 +0,0 @@ -Fixed bug where fleetd-chrome sent multiple read requests to Fleet server at the same time. diff --git a/ee/fleetd-chrome/changes/18940-error-when-server-down b/ee/fleetd-chrome/changes/18940-error-when-server-down deleted file mode 100644 index 93b9c665fa..0000000000 --- a/ee/fleetd-chrome/changes/18940-error-when-server-down +++ /dev/null @@ -1 +0,0 @@ -Improved console log output messages when Fleet server is down. diff --git a/ee/fleetd-chrome/package-lock.json b/ee/fleetd-chrome/package-lock.json index 1a2b0ffc91..0984574666 100644 --- a/ee/fleetd-chrome/package-lock.json +++ b/ee/fleetd-chrome/package-lock.json @@ -1,12 +1,12 @@ { "name": "fleetd-for-chrome", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fleetd-for-chrome", - "version": "1.3.0", + "version": "1.3.1", "dependencies": { "async-mutex": "^0.5.0", "dotenv": "^16.0.3", diff --git a/ee/fleetd-chrome/package.json b/ee/fleetd-chrome/package.json index ea7bbf7336..e8c3f9e322 100644 --- a/ee/fleetd-chrome/package.json +++ b/ee/fleetd-chrome/package.json @@ -1,7 +1,7 @@ { "name": "fleetd-for-chrome", "description": "Extension for Fleetd on ChromeOS", - "version": "1.3.0", + "version": "1.3.1", "dependencies": { "async-mutex": "^0.5.0", "dotenv": "^16.0.3", diff --git a/ee/fleetd-chrome/updates-beta.xml b/ee/fleetd-chrome/updates-beta.xml index 90bbeda472..56554d590a 100644 --- a/ee/fleetd-chrome/updates-beta.xml +++ b/ee/fleetd-chrome/updates-beta.xml @@ -1,6 +1,6 @@ - + diff --git a/ee/fleetd-chrome/updates.xml b/ee/fleetd-chrome/updates.xml index 1e07bdc864..a09ce904df 100644 --- a/ee/fleetd-chrome/updates.xml +++ b/ee/fleetd-chrome/updates.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file From 038526a3e9998eca8af16732c56ac02e1d1250ab Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 16 May 2024 17:01:37 -0500 Subject: [PATCH 3/3] Website: Update quote links on landing pages and frontend redirects (#19095) Closes: #18965 Changes: - Updated page scripts that used `window.locaiton` to use parasail's `goto` method. - Updated the quotes at the top of the landing pages to be wrapped in links to give them a proper hover state. - Updated the quote on the /vulnerability-management page to be a link to the author's LinkedIn page. --- .../assets/js/pages/account/edit-password.page.js | 2 +- website/assets/js/pages/account/edit-profile.page.js | 2 +- website/assets/js/pages/connect-vanta.page.js | 2 +- website/assets/js/pages/contact.page.js | 4 ++-- .../assets/js/pages/customers/new-license.page.js | 4 ++-- .../assets/js/pages/docs/basic-documentation.page.js | 2 +- website/assets/js/pages/entrance/login.page.js | 2 +- .../assets/js/pages/entrance/new-password.page.js | 2 +- website/assets/js/pages/entrance/signup.page.js | 2 +- website/assets/js/pages/query-detail.page.js | 2 +- website/assets/js/pages/query-library.page.js | 4 ++-- website/assets/js/pages/start.page.js | 6 +++--- .../assets/js/pages/try-fleet/query-report.page.js | 9 ++++----- .../js/pages/try-fleet/sandbox-teleporter.page.js | 2 +- website/assets/styles/pages/device-management.less | 12 ++++++++++++ website/assets/styles/pages/endpoint-ops.less | 7 +++++++ .../styles/pages/vulnerability-management.less | 7 +++++++ website/views/pages/device-management.ejs | 4 +++- website/views/pages/endpoint-ops.ejs | 12 +++++++++--- website/views/pages/vulnerability-management.ejs | 2 ++ 20 files changed, 62 insertions(+), 27 deletions(-) diff --git a/website/assets/js/pages/account/edit-password.page.js b/website/assets/js/pages/account/edit-password.page.js index c6a614e058..b745d92a13 100644 --- a/website/assets/js/pages/account/edit-password.page.js +++ b/website/assets/js/pages/account/edit-password.page.js @@ -43,7 +43,7 @@ parasails.registerPage('edit-password', { // > (Note that we re-enable the syncing state here. This is on purpose-- // > to make sure the spinner stays there until the page navigation finishes.) this.syncing = true; - window.location = '/account'; + this.goto('/account'); }, } diff --git a/website/assets/js/pages/account/edit-profile.page.js b/website/assets/js/pages/account/edit-profile.page.js index 4a9ce71221..6a13dc6a4b 100644 --- a/website/assets/js/pages/account/edit-profile.page.js +++ b/website/assets/js/pages/account/edit-profile.page.js @@ -45,7 +45,7 @@ parasails.registerPage('edit-profile', { // > (Note that we re-enable the syncing state here. This is on purpose-- // > to make sure the spinner stays there until the page navigation finishes.) this.syncing = true; - window.location = '/account'; + this.goto('/account'); }, } diff --git a/website/assets/js/pages/connect-vanta.page.js b/website/assets/js/pages/connect-vanta.page.js index 2733f5f687..be024d0125 100644 --- a/website/assets/js/pages/connect-vanta.page.js +++ b/website/assets/js/pages/connect-vanta.page.js @@ -39,7 +39,7 @@ parasails.registerPage('connect-vanta', { submittedAuthorizationForm: async function() { this.syncing = true; - window.location = this.vantaAuthorizationRequestURL; + this.goto(this.vantaAuthorizationRequestURL); }, clickClearErrors: async function() { diff --git a/website/assets/js/pages/contact.page.js b/website/assets/js/pages/contact.page.js index d5f36f1d0c..3a4314bf01 100644 --- a/website/assets/js/pages/contact.page.js +++ b/website/assets/js/pages/contact.page.js @@ -88,9 +88,9 @@ parasails.registerPage('contact', { submittedTalkToUsForm: async function() { this.syncing = true; if(this.formData.numberOfHosts > 700){ - window.location = `https://calendly.com/fleetdm/talk-to-us?email=${encodeURIComponent(this.formData.emailAddress)}&name=${encodeURIComponent(this.formData.firstName+' '+this.formData.lastName)}`; + this.goto(`https://calendly.com/fleetdm/talk-to-us?email=${encodeURIComponent(this.formData.emailAddress)}&name=${encodeURIComponent(this.formData.firstName+' '+this.formData.lastName)}`); } else { - window.location = `https://calendly.com/fleetdm/chat?email=${encodeURIComponent(this.formData.emailAddress)}&name=${encodeURIComponent(this.formData.firstName+' '+this.formData.lastName)}`; + this.goto(`https://calendly.com/fleetdm/chat?email=${encodeURIComponent(this.formData.emailAddress)}&name=${encodeURIComponent(this.formData.firstName+' '+this.formData.lastName)}`); } }, diff --git a/website/assets/js/pages/customers/new-license.page.js b/website/assets/js/pages/customers/new-license.page.js index f49312ffff..6917592f51 100644 --- a/website/assets/js/pages/customers/new-license.page.js +++ b/website/assets/js/pages/customers/new-license.page.js @@ -67,7 +67,7 @@ parasails.registerPage('new-license', { clickGoToDashboard: async function() { this.syncing = true; - window.location = '/customers/dashboard?order-complete'; + this.goto('/customers/dashboard?order-complete'); }, submittedQuoteForm: async function(quote) { @@ -90,7 +90,7 @@ parasails.registerPage('new-license', { clickScheduleDemo: async function() { this.syncing = true; // Note: we keep loading spinner present indefinitely so that it is apparent that a new page is loading - window.location = `https://calendly.com/fleetdm/talk-to-us?email=${encodeURIComponent(this.me.emailAddress)}&name=${encodeURIComponent(this.me.firstName+' '+this.me.lastName)}`; + this.goto(`https://calendly.com/fleetdm/talk-to-us?email=${encodeURIComponent(this.me.emailAddress)}&name=${encodeURIComponent(this.me.firstName+' '+this.me.lastName)}`); }, clickResetForm: async function() { diff --git a/website/assets/js/pages/docs/basic-documentation.page.js b/website/assets/js/pages/docs/basic-documentation.page.js index 978277a36a..5b7262b8f2 100644 --- a/website/assets/js/pages/docs/basic-documentation.page.js +++ b/website/assets/js/pages/docs/basic-documentation.page.js @@ -223,7 +223,7 @@ parasails.registerPage('basic-documentation', { methods: { clickCTA: function (slug) { - window.location = slug; + this.goto(slug); }, isCurrentSection: function (section) { diff --git a/website/assets/js/pages/entrance/login.page.js b/website/assets/js/pages/entrance/login.page.js index a73ca3fc79..a506effa58 100644 --- a/website/assets/js/pages/entrance/login.page.js +++ b/website/assets/js/pages/entrance/login.page.js @@ -59,7 +59,7 @@ parasails.registerPage('login', { // > (Note that we re-enable the syncing state here. This is on purpose-- // > to make sure the spinner stays there until the page navigation finishes.) this.syncing = true; - window.location = this.pageToRedirectToAfterLogin; + this.goto(this.pageToRedirectToAfterLogin); }, } diff --git a/website/assets/js/pages/entrance/new-password.page.js b/website/assets/js/pages/entrance/new-password.page.js index 74a032f5ab..0b934c8326 100644 --- a/website/assets/js/pages/entrance/new-password.page.js +++ b/website/assets/js/pages/entrance/new-password.page.js @@ -45,7 +45,7 @@ parasails.registerPage('new-password', { // > (Note that we re-enable the syncing state here. This is on purpose-- // > to make sure the spinner stays there until the page navigation finishes.) this.syncing = true; - window.location = '/customers/login'; + this.goto('/customers/login'); }, } diff --git a/website/assets/js/pages/entrance/signup.page.js b/website/assets/js/pages/entrance/signup.page.js index 0680b39b98..598e3b073e 100644 --- a/website/assets/js/pages/entrance/signup.page.js +++ b/website/assets/js/pages/entrance/signup.page.js @@ -68,7 +68,7 @@ parasails.registerPage('signup', { // > (Note that we re-enable the syncing state here. This is on purpose-- // > to make sure the spinner stays there until the page navigation finishes.) this.syncing = true; - window.location = this.pageToRedirectToAfterRegistration;// « / start if the user came here from the start now button, or customers/new-license if the user came here from the "Get your license" link. + this.goto(this.pageToRedirectToAfterRegistration);// « / start if the user came here from the start now button, or customers/new-license if the user came here from the "Get your license" link. } diff --git a/website/assets/js/pages/query-detail.page.js b/website/assets/js/pages/query-detail.page.js index f05e8e97eb..e273a48243 100644 --- a/website/assets/js/pages/query-detail.page.js +++ b/website/assets/js/pages/query-detail.page.js @@ -23,7 +23,7 @@ parasails.registerPage('query-detail', { // ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝ methods: { clickAvatar: function (contributor) { - window.location = contributor.htmlUrl; + this.goto(contributor.htmlUrl); }, getDisplayName: function (contributor) { return !contributor.name ? contributor.handle : contributor.name; diff --git a/website/assets/js/pages/query-library.page.js b/website/assets/js/pages/query-library.page.js index 053682d737..7da650d012 100644 --- a/website/assets/js/pages/query-library.page.js +++ b/website/assets/js/pages/query-library.page.js @@ -57,11 +57,11 @@ parasails.registerPage('query-library', { }, clickCard: function (querySlug) { - window.location = '/queries/' + querySlug; // we can trust the query slug is url-safe + this.goto('/queries/' + querySlug); // we can trust the query slug is url-safe }, clickAvatar: function (contributor) { - window.location = contributor.htmlUrl; + this.goto(contributor.htmlUrl); }, getAvatarUrl: function (contributorData) { diff --git a/website/assets/js/pages/start.page.js b/website/assets/js/pages/start.page.js index 7be20fa6ba..846c700647 100644 --- a/website/assets/js/pages/start.page.js +++ b/website/assets/js/pages/start.page.js @@ -104,7 +104,7 @@ parasails.registerPage('start', { }); this.previouslyAnsweredQuestions[this.currentStep] = getStartedProgress[this.currentStep]; if(_.startsWith(nextStep, '/')){ - window.location = nextStep; + this.goto(nextStep); } else { this.syncing = false; this.currentStep = nextStep; @@ -282,10 +282,10 @@ parasails.registerPage('start', { return nextStepInForm; }, clickGoToCalendly: function() { - window.location = `https://calendly.com/fleetdm/talk-to-us?email=${encodeURIComponent(this.me.emailAddress)}&name=${encodeURIComponent(this.me.firstName+' '+this.me.lastName)}`; + this.goto(`https://calendly.com/fleetdm/talk-to-us?email=${encodeURIComponent(this.me.emailAddress)}&name=${encodeURIComponent(this.me.firstName+' '+this.me.lastName)}`); }, clickGoToContactPage: function() { - window.location = `/contact?prefillFormDataFromUserRecord`; + this.goto(`/contact`); }, clickClearOneFormError: function(field) { if(this.formErrors[field]){ diff --git a/website/assets/js/pages/try-fleet/query-report.page.js b/website/assets/js/pages/try-fleet/query-report.page.js index 2d453c0bff..f3d76c9494 100644 --- a/website/assets/js/pages/try-fleet/query-report.page.js +++ b/website/assets/js/pages/try-fleet/query-report.page.js @@ -55,17 +55,17 @@ parasails.registerPage('query-report', { watch: { selectedTable: function(val){ if(val !== this.tableToDisplay){ - window.location = `/try-fleet/explore-data/${this.selectedHost}/${this.selectedTable}`; + this.goto(`/try-fleet/explore-data/${this.selectedHost}/${this.selectedTable}`); } }, hostToDisplayResultsFor: function(val){ if(val !== this.selectedHost){ if(val === 'Linux'){ - window.location = `/try-fleet/explore-data/linux/apparmor_events`; + this.goto(`/try-fleet/explore-data/linux/apparmor_events`); } else if(val === 'Windows'){ - window.location = `/try-fleet/explore-data/windows/appcompat_shims`; + this.goto(`/try-fleet/explore-data/windows/appcompat_shims`); } else { - window.location = `/try-fleet/explore-data/macos/account_policy_data`; + this.goto(`/try-fleet/explore-data/macos/account_policy_data`); } } } @@ -85,7 +85,6 @@ parasails.registerPage('query-report', { tableContainer.addEventListener('scroll', (event)=>{ let container = event.target; - console.log(container); let isScrolledFullyToLeft = container.scrollLeft === 0; let isScrolledFullyToRight = (container.scrollWidth - container.scrollLeft <= container.clientWidth + 1); // Update the class on the table container based on how much the table is scrolled. diff --git a/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js b/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js index 730a9b3869..964af18ca6 100644 --- a/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js +++ b/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js @@ -22,7 +22,7 @@ parasails.registerPage('sandbox-teleporter', { // Binding an event handler to 'onpageshow', if a user navigates to a locally cached version of this page (e.g., A Safari user clicking the back button from their Fleet Sandbox), they will be taken to the fleetdm.com homepage. window.onpageshow = function(event) { if(event.persisted) { - window.location = '/'; + this.goto('/'); } }; // Confused? Understandable, this approach is a bit unusual. See this page's view action for more info on what this code is doing and why, as well as a link where you can read more information. diff --git a/website/assets/styles/pages/device-management.less b/website/assets/styles/pages/device-management.less index 21d927f058..70df383852 100644 --- a/website/assets/styles/pages/device-management.less +++ b/website/assets/styles/pages/device-management.less @@ -38,6 +38,11 @@ font-size: 16px; line-height: @text-lineheight; color: @core-fleet-black-75; + a[href] { + text-decoration: underline; + color: @core-fleet-black-75; + text-underline-offset: 3px; + } } strong { color: @core-fleet-black; @@ -185,6 +190,13 @@ } [purpose='testimonial-quote'] { width: 640px; + a { + text-decoration: none; + color: unset; + &:hover { + text-decoration: none; + } + } [purpose='quote'] { p { color: @core-fleet-black-75; diff --git a/website/assets/styles/pages/endpoint-ops.less b/website/assets/styles/pages/endpoint-ops.less index 7f69ef95e6..10ea15b5c9 100644 --- a/website/assets/styles/pages/endpoint-ops.less +++ b/website/assets/styles/pages/endpoint-ops.less @@ -174,6 +174,13 @@ } } [purpose='testimonial-quote'] { + a { + text-decoration: none; + color: unset; + &:hover { + text-decoration: none; + } + } max-width: 591px; [purpose='quote'] { p { diff --git a/website/assets/styles/pages/vulnerability-management.less b/website/assets/styles/pages/vulnerability-management.less index 93bdc23532..db96337311 100644 --- a/website/assets/styles/pages/vulnerability-management.less +++ b/website/assets/styles/pages/vulnerability-management.less @@ -172,6 +172,13 @@ } [purpose='testimonial-quote'] { width: 380px; + a { + text-decoration: none; + color: unset; + &:hover { + text-decoration: none; + } + } [purpose='quote'] { p { color: @core-fleet-black-75; diff --git a/website/views/pages/device-management.ejs b/website/views/pages/device-management.ejs index 8486a80a11..08fc39c3ac 100644 --- a/website/views/pages/device-management.ejs +++ b/website/views/pages/device-management.ejs @@ -25,7 +25,8 @@ diff --git a/website/views/pages/endpoint-ops.ejs b/website/views/pages/endpoint-ops.ejs index af014a96aa..8438268c60 100644 --- a/website/views/pages/endpoint-ops.ejs +++ b/website/views/pages/endpoint-ops.ejs @@ -42,7 +42,8 @@