(core) Enable auto triggering of Welcome Tour, and various improvements.

Summary:
- Add showGristTour preference, and trigger tour automatically.
- Tour is only triggered for new and anonymous users on a personal org, with
  edit permission.

- Automatically open the right panel at tour start.
- Don't show tours on mobile, since that's not ready (popups are cut off
  and can't be dismissed)
- Cancel previous tour if a new one is somehow started.
- Remove #repeat- trigger hash tags from the URL when the tour starts.
- Ensure Help Center popup is positioned even when left panel is collapsed.
- Polish up the content of the last two cards in the tour.

Test Plan: Added test case for triggering and opening right panel.

Reviewers: alexmojaki, paulfitz

Reviewed By: alexmojaki

Differential Revision: https://phab.getgrist.com/D2955
This commit is contained in:
Dmitry S
2021-07-30 11:16:33 -04:00
parent 73c4efa315
commit 1605e18f66
12 changed files with 120 additions and 35 deletions

View File

@@ -37,6 +37,7 @@ describe("Smoke", function() {
await openMainPage();
await driver.findContent('button', /Create Empty Document/).click();
await gu.waitForDocToLoad(20000);
await gu.dismissWelcomeTourIfNeeded();
await gu.getCell('A', 1).click();
await gu.enterCell('123');
await driver.navigate().refresh();

View File

@@ -154,6 +154,15 @@ export async function waitForUrl(pattern: RegExp|string, waitMs: number = 2000)
await driver.wait(() => testCurrentUrl(pattern), waitMs);
}
export async function dismissWelcomeTourIfNeeded() {
const elem = driver.find('.test-onboarding-close');
if (await elem.isPresent()) {
await elem.click();
}
await waitForServer();
}
// Selects all text when a text element is currently active.
export async function selectAll() {
await driver.executeScript('document.activeElement.select()');

View File

@@ -52,14 +52,17 @@ export class HomeUtil {
loginMethod?: UserProfile['loginMethod'],
freshAccount?: boolean,
isFirstLogin?: boolean,
showGristTour?: boolean,
cacheCredentials?: boolean,
} = {}) {
const {loginMethod, isFirstLogin} = defaults(options, {loginMethod: 'Email + Password'});
const showGristTour = options.showGristTour ?? (options.freshAccount ?? isFirstLogin);
// For regular tests, we can log in through a testing hook.
if (!this.server.isExternalServer()) {
if (options.freshAccount) { await this._deleteUserByEmail(email); }
if (isFirstLogin !== undefined) { await this._setFirstLogin(email, isFirstLogin); }
if (showGristTour !== undefined) { await this._initShowGristTour(email, showGristTour); }
// TestingHooks communicates via JSON, so it's impossible to send an `undefined` value for org
// through it. Using the empty string happens to work though.
const testingHooks = await this.server.getTestingHooks();
@@ -86,6 +89,9 @@ export class HomeUtil {
await this._fillWelcomePageIfPresent(name);
}
}
if (options.freshAccount) {
this._apiKey.delete(email);
}
if (options.cacheCredentials) {
// Take this opportunity to cache access info.
if (!this._apiKey.has(email)) {
@@ -302,6 +308,16 @@ export class HomeUtil {
}
}
private async _initShowGristTour(email: string, showGristTour: boolean) {
if (this.server.isExternalServer()) { throw new Error('not supported'); }
const dbManager = await this.server.getDatabase();
const user = await dbManager.getUserByLogin(email);
if (user && user.personalOrg) {
const userOrgPrefs = {showGristTour};
await dbManager.updateOrg({userId: user.id}, user.personalOrg.id, {userOrgPrefs});
}
}
// Get past the user welcome page if it is present.
private async _fillWelcomePageIfPresent(name?: string) {
// TODO: check treatment of welcome/team page when necessary.