mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Update HelpScout beacon to work with embedded documentation articles.
Summary: - Fix base href in HelpScout beacon when showing articles (in particular for Firefox) - Show the 'Answers' tab normally except when reporting an error. - Combine the "Give Feedback" and "Help Center" buttons into one that normally opens the beacon (with a link to Help Center and to Community Forum), and a smaller one that opens the Help Center site in a new tab. - Update HELP_SCOUT_* env vars to use _V2 suffix, to allow them to coexist with code using the previous beacon. Test Plan: Updated the browser test to check the new behavior. Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3170
This commit is contained in:
@@ -29,6 +29,8 @@ export type BeaconCmd = 'init' | 'destroy' | 'open' | 'close' | 'toggle' | 'sear
|
||||
'article' | 'navigate' | 'identify' | 'prefill' | 'reset' | 'logout' | 'config' | 'on' | 'off' |
|
||||
'once' | 'event' | 'session-data';
|
||||
|
||||
export type BeaconRoute = '/ask/message/' | '/answers/';
|
||||
|
||||
export interface IUserObj {
|
||||
name?: string;
|
||||
email?: string;
|
||||
@@ -70,6 +72,8 @@ export function Beacon(method: BeaconCmd, options?: unknown, data?: unknown) {
|
||||
(window as any).Beacon(method, options, data);
|
||||
}
|
||||
|
||||
// This is essentially what's done by the code snippet that HelpScout suggests to install in every
|
||||
// page. In Grist app pages, we only load HelpScout code when the beacon is opened.
|
||||
function _beacon(method: BeaconCmd, options?: unknown, data?: unknown) {
|
||||
_beacon.readyQueue.push({method, options, data});
|
||||
}
|
||||
@@ -103,7 +107,7 @@ let lastOpenType: 'error' | 'message' = 'message';
|
||||
* If errors is given, prepares a form for submitting an error report, and includes stack traces
|
||||
* into the session-data.
|
||||
*/
|
||||
function _beaconOpen(userObj: IUserObj|null, options: {onOpen?: () => void, errors?: IAppError[]}) {
|
||||
function _beaconOpen(userObj: IUserObj|null, options: IBeaconOpenOptions) {
|
||||
const {onOpen, errors} = options;
|
||||
|
||||
// The beacon remembers its content, so reset it when switching between reporting errors and
|
||||
@@ -119,6 +123,16 @@ function _beaconOpen(userObj: IUserObj|null, options: {onOpen?: () => void, erro
|
||||
if (iframe) { iframe.focus(); }
|
||||
if (onOpen) { onOpen(); }
|
||||
});
|
||||
Beacon('once', 'article-viewed' as any, () => {
|
||||
// HelpScout creates an iframe with an empty 'src' attribute, then writes to it. In such an
|
||||
// iframe, different browsers interpret relative links differently: Chrome's are relative to
|
||||
// the parent page's URL; Firefox's are relative to the parent page's <base href>.
|
||||
//
|
||||
// Here we set a <base href> explicitly in the iframe to get consistent behavior of links
|
||||
// relative to the top page's URL (HelpScout then seems to handle clicks on them correctly).
|
||||
const iframe = document.querySelector('#beacon-container iframe') as HTMLIFrameElement;
|
||||
iframe?.contentDocument?.head.appendChild(dom('base', {href: ''}));
|
||||
});
|
||||
Beacon('once', 'close', () => {
|
||||
const iframe = document.querySelector('#beacon-container iframe') as HTMLIFrameElement;
|
||||
if (iframe) { iframe.blur(); }
|
||||
@@ -128,6 +142,7 @@ function _beaconOpen(userObj: IUserObj|null, options: {onOpen?: () => void, erro
|
||||
}
|
||||
|
||||
const attrs: ISessionData = {};
|
||||
let route: BeaconRoute;
|
||||
if (errors?.length) {
|
||||
// If sending errors, prefill part of the message (the user sees this and can add to it), and
|
||||
// include more detailed errors with stack traces into session-data.
|
||||
@@ -147,8 +162,10 @@ function _beaconOpen(userObj: IUserObj|null, options: {onOpen?: () => void, erro
|
||||
attrs[`error-${i}-stack`] = JSON.stringify(error.stack.trim().split('\n'));
|
||||
}
|
||||
});
|
||||
route = options.route || '/ask/message/';
|
||||
} else {
|
||||
Beacon('config', {messaging: {contactForm: {showSubject: true}}});
|
||||
route = options.route || '/answers/';
|
||||
}
|
||||
|
||||
Beacon('session-data', {
|
||||
@@ -156,7 +173,7 @@ function _beaconOpen(userObj: IUserObj|null, options: {onOpen?: () => void, erro
|
||||
...attrs,
|
||||
});
|
||||
Beacon('open');
|
||||
Beacon('navigate', '/ask/message/');
|
||||
Beacon('navigate', route);
|
||||
}
|
||||
|
||||
export interface IBeaconOpenOptions {
|
||||
@@ -164,6 +181,7 @@ export interface IBeaconOpenOptions {
|
||||
includeAppErrors?: boolean;
|
||||
onOpen?: () => void;
|
||||
errors?: IAppError[];
|
||||
route?: BeaconRoute;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user