This repository has been archived by the owner on Dec 22, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #218 from mikenikles/improve-onboarding
Improve onboarding
- Loading branch information
Showing
9 changed files
with
245 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<script lang="ts"> | ||
import onboarding from "../../stores/onboarding"; | ||
import StepWrapper from "./step-wrapper.svelte"; | ||
let firstName = ""; | ||
const handleSubmit = () => { | ||
$onboarding.user.firstName = firstName; | ||
}; | ||
const handleKeyup = (event) => { | ||
if (event.code === "Enter") { | ||
handleSubmit(); | ||
} | ||
}; | ||
</script> | ||
|
||
<StepWrapper> | ||
<div> | ||
<label for="firstName" class="text-sm font-medium leading-5 text-gray-700"> | ||
What's your first name? | ||
</label> | ||
<div class="mt-1 rounded-md shadow-sm"> | ||
<input id="firstName" bind:value={firstName} on:keyup|preventDefault={handleKeyup} type="text" required class="appearance-none w-full px-3 py-2 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5"> | ||
</div> | ||
</div> | ||
|
||
<div class="mt-6"> | ||
<span class="w-full rounded-md shadow-sm"> | ||
<button type="button" on:click={handleSubmit} class="w-full flex justify-center mt-4 py-4 px-10 bg-blue-600 rounded-lg font-semibold text-white sm:mt-0"> | ||
Next: Configure your website | ||
</button> | ||
</span> | ||
</div> | ||
</StepWrapper> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<script lang="ts"> | ||
import { onDestroy } from "svelte"; | ||
import { addNewWebsite } from "../../api/onboarding"; | ||
import { fetchUniqueVisitorsOnOnboardingPage } from "../../api/stats"; | ||
import dateRange from "../../stores/date-range"; | ||
import onboarding from "../../stores/onboarding"; | ||
import { session } from "../../stores/session"; | ||
import StepWrapper from "./step-wrapper.svelte"; | ||
import TimezoneSelect from "../timezone-select.svelte"; | ||
export let hasUserAlreadyConfiguredSite: boolean; | ||
export let isUrlInvalid: boolean; | ||
let fetchUniqueVisitorsInterval: number; | ||
$: existingUserSites = Object.keys($onboarding.user.sites || {}) || []; | ||
$: hasUserAlreadyConfiguredSite = existingUserSites.includes($onboarding.url); | ||
$: isUrlInvalid = hasUserAlreadyConfiguredSite || $onboarding.isSiteAlreadyConfiguredGlobally; | ||
const handleSubmit = async () => { | ||
const firstName = $onboarding.user.firstName; | ||
const url = $onboarding.url; | ||
const timezone = $onboarding.timezone; | ||
const responseCode = await addNewWebsite({firstName, url, timezone}); | ||
switch (responseCode) { | ||
case 201: | ||
$onboarding.isSiteAdded = true; | ||
$session.user.sites[url] = {}; | ||
dateRange.setPreset("today"); | ||
fetchUniqueVisitorsInterval = setInterval(() => { | ||
fetchUniqueVisitorsOnOnboardingPage(window.fetch, window.location.hostname, url); | ||
}, 10000); | ||
break; | ||
case 400: | ||
$onboarding.isSiteAlreadyConfiguredGlobally = true; | ||
break; | ||
} | ||
}; | ||
onDestroy(() => { | ||
if (fetchUniqueVisitorsInterval) { | ||
window.clearInterval(fetchUniqueVisitorsInterval); | ||
} | ||
}); | ||
</script> | ||
|
||
<style> | ||
button:disabled { | ||
@apply bg-indigo-500; | ||
@apply cursor-not-allowed; | ||
} | ||
</style> | ||
|
||
<StepWrapper> | ||
<div> | ||
<label for="url" class="text-sm font-medium leading-5 text-gray-700"> | ||
What's your website URL? | ||
</label> | ||
<div class="mt-1 relative flex rounded-md shadow-sm"> | ||
<span class="inline-flex items-center px-3 rounded-l-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm"> | ||
http(s)://www. | ||
</span> | ||
<input id="url" bind:value={$onboarding.url} on:focus={() => $onboarding.isSiteAlreadyConfiguredGlobally = false} type="text" name="url" required class="px-3 py-2 w-full border border-gray-300 rounded-none rounded-r-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 sm:text-sm sm:leading-5"> | ||
{#if isUrlInvalid && !$onboarding.isSiteAdded} | ||
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"> | ||
<svg class="h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20"> | ||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd" /> | ||
</svg> | ||
</div> | ||
{/if} | ||
</div> | ||
<p class="mt-2 text-sm text-red-600"> | ||
{#if !$onboarding.isSiteAdded && hasUserAlreadyConfiguredSite} | ||
You've already configured this website. | ||
{:else if !$onboarding.isSiteAdded && $onboarding.isSiteAlreadyConfiguredGlobally} | ||
This site has already been configured. If it belongs to you, please contact us. | ||
{/if} | ||
</p> | ||
</div> | ||
|
||
<div class="mt-6"> | ||
<label for="url" class="text-sm font-medium leading-5 text-gray-700"> | ||
What's your preferred reporting timezone | ||
</label> | ||
<div class="mt-1 rounded-md shadow-sm"> | ||
<TimezoneSelect name="timezone" /> | ||
</div> | ||
</div> | ||
|
||
<div class="mt-6"> | ||
<span class="w-full rounded-md shadow-sm"> | ||
<button type="button" on:click={handleSubmit} disabled={isUrlInvalid} class="w-full flex justify-center mt-4 py-4 px-10 bg-blue-600 rounded-lg font-semibold text-white sm:mt-0"> | ||
Let's go | ||
</button> | ||
</span> | ||
</div> | ||
</StepWrapper> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<script lang="ts"> | ||
import onboarding from "../../stores/onboarding"; | ||
import StepWrapper from "./step-wrapper.svelte"; | ||
import UniqueVisitors from "../stats/unique-visitors.svelte"; | ||
$: script = `<script async defer src="https://your-analytics.org/ya.js" data-domain="${$onboarding.url}"><\/script>`; | ||
const copyScriptToClipboard = () => { | ||
const textarea = document.getElementById('script') as HTMLTextAreaElement; | ||
textarea.focus(); | ||
textarea.select(); | ||
document.execCommand('copy'); | ||
}; | ||
</script> | ||
|
||
<StepWrapper> | ||
<p>Add the following script to all pages you want to track on your website.</p> | ||
<div class="relative mt-6"> | ||
<textarea id="script" value={script} rows="3" readonly class="w-full p-2 bg-gray-100 resize-none"></textarea> | ||
<button on:click={copyScriptToClipboard}> | ||
<svg class="absolute" style="top: 24px; right: 12px;" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg> | ||
</button> | ||
</div> | ||
<p class="mt-6">Once added, please visit <a href="https://{$onboarding.url}" target="_blank" rel="noopener" class="text-pink-600 hover:underline">{$onboarding.url}</a> to see the first few visits logged below.</p> | ||
<div class="relative mt-6 pb-6 flex justify-center"> | ||
<UniqueVisitors /> | ||
</div> | ||
<p class="mt-6">Don't want to wait? <a href="/{$onboarding.url}" class="text-pink-600 hover:underline">Go to your dashboard.</a></p> | ||
</StepWrapper> |
22 changes: 22 additions & 0 deletions
22
services/website/src/components/onboarding/step-header.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<script lang="ts"> | ||
export let label: string; | ||
export let stepNumber: number; | ||
export let isUpcoming: boolean = false; | ||
</script> | ||
|
||
<style> | ||
.isUpcoming div { | ||
@apply border-gray-200; | ||
} | ||
.isUpcoming h3 { | ||
@apply text-gray-500; | ||
} | ||
</style> | ||
|
||
<li class:isUpcoming class="md:flex-1"> | ||
<div class="pl-4 py-2 block border-l-4 border-indigo-600 md:pl-0 md:pt-4 md:pb-0 md:border-l-0 md:border-t-4"> | ||
<h3 class="text-xs leading-4 text-indigo-600 font-semibold uppercase">Step {stepNumber}</h3> | ||
<p class="text-sm leading-5 font-medium">{label}</p> | ||
</div> | ||
</li> |
10 changes: 10 additions & 0 deletions
10
services/website/src/components/onboarding/step-wrapper.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<script lang="ts"> | ||
import { fly } from 'svelte/transition'; | ||
import Card from "../card.svelte"; | ||
</script> | ||
|
||
<div in:fly={{x:1000, delay:500, duration:500}} out:fly={{x:-500, duration:500}}> | ||
<Card clazz="p-4"> | ||
<slot /> | ||
</Card> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
519c65b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: