- Created demo emails with various states (inbox, sent, drafts, trash, etc.) in `emails.ts`. - Added demo file nodes representing directories and files in `files.ts`. - Implemented demo Sieve capabilities and scripts in `filters.ts`. - Defined demo identities for users in `identities.ts`. - Established demo mailboxes with permissions and counts in `mailboxes.ts`. - Created a demo vacation response in `vacation.ts`. - Introduced a comprehensive JMAP client interface in `client-interface.ts` to standardize interactions with the JMAP API.
222 lines
5.9 KiB
TypeScript
222 lines
5.9 KiB
TypeScript
export interface TourStep {
|
|
id: string;
|
|
target: string;
|
|
titleKey: string;
|
|
descriptionKey: string;
|
|
placement: "top" | "bottom" | "left" | "right";
|
|
interactive?: boolean;
|
|
spotlight?: "rect" | "circle";
|
|
page?: string;
|
|
demoOnly?: boolean;
|
|
beforeAction?: () => void;
|
|
}
|
|
|
|
export const BASE_TOUR_STEPS: TourStep[] = [
|
|
{
|
|
id: "sidebar",
|
|
target: '[data-tour="sidebar"]',
|
|
titleKey: "tour.sidebar_title",
|
|
descriptionKey: "tour.sidebar_desc",
|
|
placement: "right",
|
|
},
|
|
{
|
|
id: "compose",
|
|
target: '[data-tour="compose-button"]',
|
|
titleKey: "tour.compose_title",
|
|
descriptionKey: "tour.compose_desc",
|
|
placement: "right",
|
|
interactive: true,
|
|
},
|
|
{
|
|
id: "search",
|
|
target: '[data-tour="search-input"]',
|
|
titleKey: "tour.search_title",
|
|
descriptionKey: "tour.search_desc",
|
|
placement: "bottom",
|
|
interactive: true,
|
|
},
|
|
{
|
|
id: "email-list",
|
|
target: '[data-tour="email-list"]',
|
|
titleKey: "tour.email_list_title",
|
|
descriptionKey: "tour.email_list_desc",
|
|
placement: "right",
|
|
},
|
|
{
|
|
id: "email-viewer",
|
|
target: '[data-tour="email-viewer"]',
|
|
titleKey: "tour.email_viewer_title",
|
|
descriptionKey: "tour.email_viewer_desc",
|
|
placement: "left",
|
|
beforeAction: () => {
|
|
// Click the "Welcome to Bulwark Mail!" email (or the first email) to open the viewer
|
|
const emailList = document.querySelector('[data-tour="email-list"]');
|
|
if (!emailList) return;
|
|
// Try to find the welcome email by subject text
|
|
const items = emailList.querySelectorAll('.cursor-pointer');
|
|
let target: HTMLElement | null = null;
|
|
for (const item of items) {
|
|
if (item.textContent?.includes("Welcome to Bulwark Mail")) {
|
|
target = item as HTMLElement;
|
|
break;
|
|
}
|
|
}
|
|
// Fallback to first email if welcome email not found
|
|
if (!target) target = emailList.querySelector('.cursor-pointer') as HTMLElement | null;
|
|
if (target) target.click();
|
|
},
|
|
},
|
|
{
|
|
id: "keywords",
|
|
target: '[data-tour="keyword-tags"]',
|
|
titleKey: "tour.keywords_title",
|
|
descriptionKey: "tour.keywords_desc",
|
|
placement: "right",
|
|
},
|
|
{
|
|
id: "nav-calendar",
|
|
target: '[data-tour="nav-calendar"]',
|
|
titleKey: "tour.calendar_title",
|
|
descriptionKey: "tour.calendar_desc",
|
|
placement: "right",
|
|
},
|
|
{
|
|
id: "nav-contacts",
|
|
target: '[data-tour="nav-contacts"]',
|
|
titleKey: "tour.contacts_title",
|
|
descriptionKey: "tour.contacts_desc",
|
|
placement: "right",
|
|
},
|
|
{
|
|
id: "nav-settings",
|
|
target: '[data-tour="nav-settings"]',
|
|
titleKey: "tour.settings_title",
|
|
descriptionKey: "tour.settings_desc",
|
|
placement: "right",
|
|
},
|
|
{
|
|
id: "shortcuts",
|
|
target: '[data-tour="nav-shortcuts"]',
|
|
titleKey: "tour.shortcuts_title",
|
|
descriptionKey: "tour.shortcuts_desc",
|
|
placement: "right",
|
|
interactive: true,
|
|
},
|
|
];
|
|
|
|
export const DEMO_TOUR_STEPS: TourStep[] = [
|
|
{
|
|
id: "compose-open",
|
|
target: '[data-tour="composer"]',
|
|
titleKey: "tour.compose_open_title",
|
|
descriptionKey: "tour.compose_open_desc",
|
|
placement: "left",
|
|
demoOnly: true,
|
|
beforeAction: () => {
|
|
// Click the compose button to open the composer
|
|
const btn = document.querySelector('[data-tour="compose-button"]') as HTMLElement | null;
|
|
if (btn) btn.click();
|
|
},
|
|
},
|
|
{
|
|
id: "calendar-view",
|
|
target: '[data-tour="calendar-view"]',
|
|
titleKey: "tour.calendar_view_title",
|
|
descriptionKey: "tour.calendar_view_desc",
|
|
placement: "bottom",
|
|
page: "/calendar",
|
|
demoOnly: true,
|
|
},
|
|
{
|
|
id: "create-event",
|
|
target: '[data-tour="create-event-button"]',
|
|
titleKey: "tour.create_event_title",
|
|
descriptionKey: "tour.create_event_desc",
|
|
placement: "bottom",
|
|
page: "/calendar",
|
|
interactive: true,
|
|
demoOnly: true,
|
|
},
|
|
{
|
|
id: "event-modal",
|
|
target: '[data-tour="event-modal"]',
|
|
titleKey: "tour.event_modal_title",
|
|
descriptionKey: "tour.event_modal_desc",
|
|
placement: "left",
|
|
page: "/calendar",
|
|
interactive: true,
|
|
demoOnly: true,
|
|
beforeAction: () => {
|
|
// Click the create event button to open the modal
|
|
const btn = document.querySelector('[data-tour="create-event-button"]') as HTMLElement | null;
|
|
if (btn) btn.click();
|
|
},
|
|
},
|
|
{
|
|
id: "contacts-list",
|
|
target: '[data-tour="contacts-list"]',
|
|
titleKey: "tour.contacts_list_title",
|
|
descriptionKey: "tour.contacts_list_desc",
|
|
placement: "right",
|
|
page: "/contacts",
|
|
demoOnly: true,
|
|
},
|
|
{
|
|
id: "settings-tabs",
|
|
target: '[data-tour="settings-tabs"]',
|
|
titleKey: "tour.settings_tabs_title",
|
|
descriptionKey: "tour.settings_tabs_desc",
|
|
placement: "right",
|
|
page: "/settings",
|
|
demoOnly: true,
|
|
},
|
|
{
|
|
id: "nav-files",
|
|
target: '[data-tour="nav-files"]',
|
|
titleKey: "tour.files_title",
|
|
descriptionKey: "tour.files_desc",
|
|
placement: "right",
|
|
demoOnly: true,
|
|
},
|
|
{
|
|
id: "demo-banner",
|
|
target: '[data-tour="demo-banner"]',
|
|
titleKey: "tour.demo_banner_title",
|
|
descriptionKey: "tour.demo_banner_desc",
|
|
placement: "bottom",
|
|
page: "/",
|
|
demoOnly: true,
|
|
},
|
|
{
|
|
id: "quota",
|
|
target: '[data-tour="storage-quota"]',
|
|
titleKey: "tour.quota_title",
|
|
descriptionKey: "tour.quota_desc",
|
|
placement: "right",
|
|
demoOnly: true,
|
|
},
|
|
];
|
|
|
|
export function getTourSteps(options: {
|
|
isDemoMode: boolean;
|
|
supportsCalendar: boolean;
|
|
supportsWebDAV: boolean;
|
|
}): TourStep[] {
|
|
let steps = [...BASE_TOUR_STEPS];
|
|
|
|
if (!options.supportsCalendar) {
|
|
steps = steps.filter((s) => s.id !== "nav-calendar");
|
|
}
|
|
|
|
if (options.isDemoMode) {
|
|
const demoSteps = DEMO_TOUR_STEPS.filter((s) => {
|
|
if (s.id === "nav-files" && !options.supportsWebDAV) return false;
|
|
if ((s.id === "calendar-view" || s.id === "create-event" || s.id === "event-modal") && !options.supportsCalendar) return false;
|
|
return true;
|
|
});
|
|
steps = [...steps, ...demoSteps];
|
|
}
|
|
|
|
return steps;
|
|
}
|