From 896895c69af427511c4edac05a46e5dad5e38e8c Mon Sep 17 00:00:00 2001 From: Bauke Date: Sat, 1 Jul 2023 15:46:23 +0200 Subject: [PATCH] Add the beginnings of the account settings tour. Also added an error tour for displaying error messages when starting a tour and a TourRequirements object. --- source/content-scripts/setup.ts | 22 ++++++++- source/options/components/tour.tsx | 17 ++++++- source/options/components/tours.tsx | 1 + source/tours/exports.ts | 52 ++++++++++++++++++--- source/tours/interface/account-settings.tsx | 17 +++++++ source/tours/interface/exports.ts | 4 ++ source/tours/shared/exports.ts | 1 + source/tours/shared/tour-error.tsx | 26 +++++++++++ 8 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 source/tours/interface/account-settings.tsx create mode 100644 source/tours/shared/tour-error.tsx diff --git a/source/content-scripts/setup.ts b/source/content-scripts/setup.ts index 9f5a4b0..d43d69b 100644 --- a/source/content-scripts/setup.ts +++ b/source/content-scripts/setup.ts @@ -4,7 +4,7 @@ import { createIntroductionUnderstood, } from "../storage/common.js"; import {introductionSteps} from "../tours/introduction.js"; -import {TourId, tourIdsAndSteps} from "../tours/exports.js"; +import {TourId, showTourError, tourIdsAndSteps} from "../tours/exports.js"; /** The main entry point for the content script. */ async function main(): Promise { @@ -38,10 +38,28 @@ async function main(): Promise { return; } + const userIsLoggedIn = + document.querySelector(".logged-in-user-username") !== null; + // Then run through all of the tours we have and start the first match for the // ID. - for (const [id, steps, eventHandlers] of tourIdsAndSteps) { + for (const [id, steps, eventHandlers, requirements] of tourIdsAndSteps) { if (anchorTourId === id) { + if (requirements.mustBeLoggedIn && !userIsLoggedIn) { + showTourError( + `The ${id} tour can only be shown with a logged in account.`, + ); + return; + } + + if (requirements.path !== window.location.pathname) { + // This tour's path requirement does not match. + showTourError( + `The ${id} tour can only be start on the ${requirements.path} page.`, + ); + return; + } + startTour(id, steps, eventHandlers, false); return; } diff --git a/source/options/components/tour.tsx b/source/options/components/tour.tsx index ba4ed3c..acb42b4 100644 --- a/source/options/components/tour.tsx +++ b/source/options/components/tour.tsx @@ -25,6 +25,14 @@ function tourDescription(tourId: Props["tourId"]): JSX.Element { ); } + if (tourId === TourId.InterfaceAccountSettings) { + return ( +

+ View your account settings and all that you can customize. +

+ ); + } + return (

Tour ID "{tourId}" does not have a description, this should probably be @@ -45,7 +53,14 @@ function tourLink(tourId: Props["tourId"]): string { break; } - default: + case TourId.InterfaceAccountSettings: { + path = "/settings"; + break; + } + + default: { + throw new Error(`Unswitched tour ID: ${tourId as string}`); + } } return `${baseUrl}${path}${anchor}`; diff --git a/source/options/components/tours.tsx b/source/options/components/tours.tsx index 93c30dd..7bcd29b 100644 --- a/source/options/components/tours.tsx +++ b/source/options/components/tours.tsx @@ -37,6 +37,7 @@ export class Tours extends Component { const tourProps: Array = [ createTour(TourId.Introduction, "Introduction"), createTour(TourId.InterfaceHomepage, "The Homepage"), + createTour(TourId.InterfaceAccountSettings, "Your Account Settings"), ]; return ( diff --git a/source/tours/exports.ts b/source/tours/exports.ts index d178134..ba5b823 100644 --- a/source/tours/exports.ts +++ b/source/tours/exports.ts @@ -1,14 +1,54 @@ -import {homepageEventHandlers, homepageSteps} from "./interface/exports.js"; +import { + accountSettingsEventHandlers, + accountSettingsSteps, + homepageEventHandlers, + homepageSteps, +} from "./interface/exports.js"; import {introductionSteps} from "./introduction.js"; +export * from "./shared/exports.js"; + export enum TourId { + InterfaceAccountSettings = "interface-account-settings", InterfaceHomepage = "interface-homepage", Introduction = "introduction", } -export const tourIdsAndSteps: Array< - [TourId, TourStepOptions[], TourStepEventHandler[]] -> = [ - [TourId.Introduction, introductionSteps, []], - [TourId.InterfaceHomepage, homepageSteps, homepageEventHandlers], +export type TourRequirement = { + mustBeLoggedIn: boolean; + path: string; +}; + +export type TourIdsAndSteps = Array< + [TourId, TourStepOptions[], TourStepEventHandler[], TourRequirement] +>; + +export const tourIdsAndSteps: TourIdsAndSteps = [ + [ + TourId.Introduction, + introductionSteps, + [], + { + mustBeLoggedIn: false, + path: "/", + }, + ], + [ + TourId.InterfaceAccountSettings, + accountSettingsSteps, + accountSettingsEventHandlers, + { + mustBeLoggedIn: true, + path: "/settings", + }, + ], + [ + TourId.InterfaceHomepage, + homepageSteps, + homepageEventHandlers, + { + mustBeLoggedIn: false, + path: "/", + }, + ], ]; diff --git a/source/tours/interface/account-settings.tsx b/source/tours/interface/account-settings.tsx new file mode 100644 index 0000000..1170168 --- /dev/null +++ b/source/tours/interface/account-settings.tsx @@ -0,0 +1,17 @@ +import type Shepherd from "shepherd.js"; +import {renderInContainer} from "../utilities.js"; + +const step01 = renderInContainer( + <> +

Your Account Settings

+ , +); + +export const steps: Shepherd.Step.StepOptions[] = [ + { + id: "account-settings-01", + text: step01, + }, +]; + +export const eventHandlers: TourStepEventHandler[] = []; diff --git a/source/tours/interface/exports.ts b/source/tours/interface/exports.ts index 393473b..a2b2518 100644 --- a/source/tours/interface/exports.ts +++ b/source/tours/interface/exports.ts @@ -1,3 +1,7 @@ +export { + eventHandlers as accountSettingsEventHandlers, + steps as accountSettingsSteps, +} from "./account-settings.js"; export { eventHandlers as homepageEventHandlers, steps as homepageSteps, diff --git a/source/tours/shared/exports.ts b/source/tours/shared/exports.ts index 3d84d0d..78dc4ea 100644 --- a/source/tours/shared/exports.ts +++ b/source/tours/shared/exports.ts @@ -1 +1,2 @@ export * from "./logged-out-warning.js"; +export * from "./tour-error.js"; diff --git a/source/tours/shared/tour-error.tsx b/source/tours/shared/tour-error.tsx new file mode 100644 index 0000000..b374bce --- /dev/null +++ b/source/tours/shared/tour-error.tsx @@ -0,0 +1,26 @@ +import Shepherd from "shepherd.js"; +import {type TourId} from "../exports.js"; +import {renderInContainer} from "../utilities.js"; + +export function showTourError(text: string) { + const tour = new Shepherd.Tour({ + defaultStepOptions: { + buttons: [ + { + classes: "btn", + text: "Continue", + action() { + this.complete(); + }, + }, + ], + }, + useModalOverlay: true, + }); + + tour.addStep({ + text: renderInContainer(

{text}

), + }); + + tour.start(); +}