(core) Show tooltips in other Grist flavors

Summary:
This enables tooltips in other Grist deployment types (e.g. grist-core). Previously,
most of these tooltips were only enabled in the SaaS offering of Grist.

Test Plan: Browser tests.

Reviewers: jarek

Reviewed By: jarek

Subscribers: jarek

Differential Revision: https://phab.getgrist.com/D4097
This commit is contained in:
George Gevoian 2023-10-29 23:21:28 -04:00
parent 4fb1df567b
commit 51f7402297
6 changed files with 128 additions and 108 deletions

View File

@ -74,20 +74,27 @@ export class BehavioralPromptsManager extends Disposable {
return this._dismissedTips.get().has(prompt);
}
public shouldShowTips() {
return !this._prefs.get().dontShowTips;
}
public shouldShowTip(prompt: BehavioralPrompt): boolean {
if (this._isDisabled) { return false; }
// For non-SaaS flavors of Grist, don't show tips if the Help Center is explicitly
// disabled. A separate opt-out feature could be added down the road for more granularity,
// but will require communication in advance to avoid disrupting users.
const {deploymentType, features} = getGristConfig();
if (
!features?.includes('helpCenter') &&
// This one is an easter egg, so we make an exception.
prompt !== 'rickRow'
) {
return false;
}
const {
showContext = 'desktop',
showDeploymentTypes,
forceShow = false,
} = GristBehavioralPrompts[prompt];
const {deploymentType} = getGristConfig();
if (
showDeploymentTypes !== '*' &&
(!deploymentType || !showDeploymentTypes.includes(deploymentType))

View File

@ -67,6 +67,7 @@ import {undef, waitObs} from 'app/common/gutil';
import {LocalPlugin} from "app/common/plugin";
import {StringUnion} from 'app/common/StringUnion';
import {TableData} from 'app/common/TableData';
import {getGristConfig} from 'app/common/urlUtils';
import {DocStateComparison} from 'app/common/UserAPI';
import {AttachedCustomWidgets, IAttachedCustomWidget, IWidgetType} from 'app/common/widgetTypes';
import {CursorPos} from 'app/plugin/GristAPI';
@ -1644,6 +1645,14 @@ export class GristDoc extends DisposableWithEvents {
* a doc tutorial or tour isn't available.
*/
private _shouldAutoStartWelcomeTour(): boolean {
// For non-SaaS flavors of Grist, don't show the tour if the Help Center is explicitly
// disabled. A separate opt-out feature could be added down the road for more granularity,
// but will require communication in advance to avoid disrupting users.
const {features} = getGristConfig();
if (!features?.includes('helpCenter')) {
return false;
}
// If a doc tutorial or tour are available, leave the welcome tour for another
// doc (e.g. a new one).
if (this._disableAutoStartingTours || this.docModel.isTutorial() || this.docModel.hasDocTour()) {

View File

@ -144,7 +144,7 @@ export const GristBehavioralPrompts: Record<BehavioralPrompt, BehavioralPromptCo
),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
referenceColumnsConfig: {
title: () => t('Reference Columns'),
@ -159,7 +159,7 @@ record in that table, but you may select which column from that record to show.'
),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
rawDataPage: {
title: () => t('Raw Data page'),
@ -169,7 +169,7 @@ including summary tables and tables not included in page layouts.')),
dom('div', cssLink({href: commonUrls.helpRawData, target: '_blank'}, t('Learn more.'))),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
accessRules: {
title: () => t('Access Rules'),
@ -179,7 +179,7 @@ to determine who can see or edit which parts of your document.')),
dom('div', cssLink({href: commonUrls.helpAccessRules, target: '_blank'}, t('Learn more.'))),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
filterButtons: {
title: () => t('Pinning Filters'),
@ -189,7 +189,7 @@ to determine who can see or edit which parts of your document.')),
dom('div', cssLink({href: commonUrls.helpFilterButtons, target: '_blank'}, t('Learn more.'))),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
nestedFiltering: {
title: () => t('Nested Filtering'),
@ -198,7 +198,7 @@ to determine who can see or edit which parts of your document.')),
dom('div', t('Only those rows will appear which match all of the filters.')),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
pageWidgetPicker: {
title: () => t('Selecting Data'),
@ -207,7 +207,7 @@ to determine who can see or edit which parts of your document.')),
dom('div', t('Use the 𝚺 icon to create summary (or pivot) tables, for totals or subtotals.')),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
pageWidgetPickerSelectBy: {
title: () => t('Linking Widgets'),
@ -217,7 +217,7 @@ to determine who can see or edit which parts of your document.')),
dom('div', cssLink({href: commonUrls.helpLinkingWidgets, target: '_blank'}, t('Learn more.'))),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
editCardLayout: {
title: () => t('Editing Card Layout'),
@ -228,7 +228,7 @@ to determine who can see or edit which parts of your document.')),
})),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
addNew: {
title: () => t('Add New'),
@ -236,7 +236,7 @@ to determine who can see or edit which parts of your document.')),
dom('div', t('Click the Add New button to create new documents or workspaces, or import data.')),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
rickRow: {
title: () => t('Anchor Links'),
@ -261,13 +261,13 @@ to determine who can see or edit which parts of your document.')),
content: (...args: DomElementArg[]) => cssTooltipContent(
dom('div',
t(
'You can choose one of our pre-made widgets or embed your own by providing its full URL.'
'You can choose from widgets available to you in the dropdown, or embed your own by providing its full URL.'
),
),
dom('div', cssLink({href: commonUrls.helpCustomWidgets, target: '_blank'}, t('Learn more.'))),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
calendarConfig: {
title: () => t('Calendar'),
@ -279,6 +279,6 @@ data.")),
dom('div', cssLink({href: commonUrls.helpCalendarWidget, target: '_blank'}, t('Learn more.'))),
...args,
),
showDeploymentTypes: ['saas'],
showDeploymentTypes: ['saas', 'core', 'enterprise', 'electron'],
},
};

View File

@ -19,6 +19,7 @@ import {AppModel} from 'app/client/models/AppModel';
import {testId, theme, vars} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {commonUrls, isFeatureEnabled} from 'app/common/gristUrls';
import {getGristConfig} from 'app/common/urlUtils';
import {dom, DomContents, Observable, styled} from 'grainjs';
const t = makeT('LeftPanelCommon');
@ -31,12 +32,15 @@ export function createHelpTools(appModel: AppModel): DomContents {
if (!isFeatureEnabled("helpCenter")) {
return [];
}
const {deploymentType} = getGristConfig();
return cssSplitPageEntry(
cssPageEntryMain(
cssPageLink(cssPageIcon('Help'),
cssLinkText(t("Help Center")),
dom.cls('tour-help-center'),
dom.on('click', (ev) => beaconOpenMessage({appModel})),
deploymentType === 'saas'
? dom.on('click', () => beaconOpenMessage({appModel}))
: {href: commonUrls.help, target: '_blank'},
testId('left-feedback'),
),
),

View File

@ -13,12 +13,9 @@ export function shouldShowWelcomeCoachingCall(appModel: AppModel) {
const {deploymentType} = getGristConfig();
if (deploymentType !== 'saas') { return false; }
const {behavioralPromptsManager, dismissedWelcomePopups} = appModel;
// Defer showing coaching call until Add New tip is dismissed.
const hasSeenAddNewTip = behavioralPromptsManager.hasSeenTip('addNew');
const shouldShowTips = behavioralPromptsManager.shouldShowTips();
if (!hasSeenAddNewTip && shouldShowTips) { return false; }
const {behavioralPromptsManager, dismissedWelcomePopups} = appModel;
if (behavioralPromptsManager.shouldShowTip('addNew')) { return false; }
const popup = dismissedWelcomePopups.get().find(p => p.id === 'coachingCall');
return (

View File

@ -6,98 +6,101 @@ import { ShortcutKey, ShortcutKeyContent } from 'app/client/ui/ShortcutKey';
import { theme } from 'app/client/ui2018/cssVars';
import { icon } from "app/client/ui2018/icons";
import { cssLink } from "app/client/ui2018/links";
import { getGristConfig } from "app/common/urlUtils";
import { dom, styled } from "grainjs";
const t = makeT('WelcomeTour');
export const WelcomeTour: IOnBoardingMsg[] = [
{
title: t('Editing Data'),
body: () => [
dom('p',
t('Double-click or hit {{enter}} on a cell to edit it. ', {
enter: ShortcutKey(ShortcutKeyContent(t('Enter'))),
}),
t('Start with {{equal}} to enter a formula.', {
equal: ShortcutKey(ShortcutKeyContent('=')),
})),
],
selector: '.field_clip',
placement: 'bottom',
},
{
selector: '.tour-creator-panel',
title: t('Configuring your document'),
body: () => [
dom('p',
t('Toggle the {{creatorPanel}} to format columns, ', {creatorPanel: dom('em', t('creator panel'))}),
t('convert to card view, select data, and more.')
)
],
placement: 'left',
cropPadding: true,
},
{
selector: '.tour-type-selector',
title: t('Customizing columns'),
body: () => [
dom('p',
t('Set formatting options, formulas, or column types, such as dates, choices, or attachments. ')),
dom('p',
t('Make it relational! Use the {{ref}} type to link tables. ', {
ref: ShortcutKey(t('Reference')),
export function getOnBoardingMessages(): IOnBoardingMsg[] {
const {features} = getGristConfig();
return [
{
title: t('Editing Data'),
body: () => [
dom('p',
t('Double-click or hit {{enter}} on a cell to edit it. ', {
enter: ShortcutKey(ShortcutKeyContent(t('Enter'))),
}),
t('Start with {{equal}} to enter a formula.', {
equal: ShortcutKey(ShortcutKeyContent('=')),
})),
],
placement: 'right',
},
{
selector: '.tour-add-new',
title: t('Building up'),
body: () => [
dom('p', t('Use {{addNew}} to add widgets, pages, or import more data. ', {
addNew: ShortcutKey(t('Add New')),
})),
],
placement: 'right',
},
{
selector: '.tour-share-icon',
title: t('Sharing'),
body: () => [
dom('p', t('Use the Share button ({{share}}) to share the document or export data.',
{share: TopBarButtonIcon(t('Share'))}))
],
placement: 'bottom',
cropPadding: true,
},
{
selector: '.tour-help-center',
title: t('Flying higher'),
body: () => [
dom('p', t('Use {{helpCenter}} for documentation or questions.',
{helpCenter: ShortcutKey(GreyIcon('Help'), t('Help Center'))}))
],
placement: 'right',
},
{
selector: '.tour-welcome',
title: t('Welcome to Grist!'),
body: () => [
dom('p', t("Browse our {{templateLibrary}} to discover what's possible and get inspired.",
{
templateLibrary: cssLink({ target: '_blank', href: urlState().makeUrl({ homePage: "templates" }) },
t('template library'), cssInlineIcon('FieldLink'))
}
)),
],
showHasModal: true,
}
];
],
selector: '.field_clip',
placement: 'bottom',
},
{
selector: '.tour-creator-panel',
title: t('Configuring your document'),
body: () => [
dom('p',
t('Toggle the {{creatorPanel}} to format columns, ', {creatorPanel: dom('em', t('creator panel'))}),
t('convert to card view, select data, and more.')
)
],
placement: 'left',
cropPadding: true,
},
{
selector: '.tour-type-selector',
title: t('Customizing columns'),
body: () => [
dom('p',
t('Set formatting options, formulas, or column types, such as dates, choices, or attachments. ')),
dom('p',
t('Make it relational! Use the {{ref}} type to link tables. ', {
ref: ShortcutKey(t('Reference')),
})),
],
placement: 'right',
},
{
selector: '.tour-add-new',
title: t('Building up'),
body: () => [
dom('p', t('Use {{addNew}} to add widgets, pages, or import more data. ', {
addNew: ShortcutKey(t('Add New')),
})),
],
placement: 'right',
},
{
selector: '.tour-share-icon',
title: t('Sharing'),
body: () => [
dom('p', t('Use the Share button ({{share}}) to share the document or export data.',
{share: TopBarButtonIcon(t('Share'))}))
],
placement: 'bottom',
cropPadding: true,
},
{
selector: '.tour-help-center',
title: t('Flying higher'),
body: () => [
dom('p', t('Use {{helpCenter}} for documentation or questions.',
{helpCenter: ShortcutKey(GreyIcon('Help'), t('Help Center'))}))
],
placement: 'right',
},
...(features?.includes('templates') && Boolean(getGristConfig().templateOrg) ? [{
selector: '.tour-welcome',
title: t('Welcome to Grist!'),
body: () => [
dom('p', t("Browse our {{templateLibrary}} to discover what's possible and get inspired.",
{
templateLibrary: cssLink({ target: '_blank', href: urlState().makeUrl({ homePage: "templates" }) },
t('template library'), cssInlineIcon('FieldLink'))
}
)),
],
showHasModal: true,
}] : []),
];
}
export function startWelcomeTour(onFinishCB: () => void) {
commands.allCommands.fieldTabOpen.run();
startOnBoarding(WelcomeTour, onFinishCB);
startOnBoarding(getOnBoardingMessages(), onFinishCB);
}
const TopBarButtonIcon = styled(icon, `