mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Allow adding a single link at the bottom of a document tour card
Summary: Checks for new special columns in GristDocTour: Link_Text, Link_URL, and Link_Icon. No link is generated if Link_Text is blank or Link_URL cannot be parsed as a URL. No icon is shown if Link_Icon is not the name of an icon in IconList.ts Test Plan: Expanded tests, but they now assert things about HTML which may be brittle Reviewers: georgegevoian, dsagal Reviewed By: georgegevoian, dsagal Subscribers: dsagal Differential Revision: https://phab.getgrist.com/D2947
This commit is contained in:
parent
37eed2d3c2
commit
aec360498c
@ -4,11 +4,14 @@ import * as _ from "lodash";
|
|||||||
import {Placement} from "@popperjs/core";
|
import {Placement} from "@popperjs/core";
|
||||||
import {placements} from "@popperjs/core/lib/enums";
|
import {placements} from "@popperjs/core/lib/enums";
|
||||||
import {sameDocumentUrlState} from "../models/gristUrlState";
|
import {sameDocumentUrlState} from "../models/gristUrlState";
|
||||||
|
import {dom} from "grainjs";
|
||||||
|
import {IconList, IconName} from "../ui2018/IconList";
|
||||||
|
import {cssButtons, cssLinkBtn, cssLinkIcon} from "./ExampleCard";
|
||||||
|
|
||||||
|
|
||||||
export async function startDocTour(docData: DocData, onFinishCB: () => void) {
|
export async function startDocTour(docData: DocData, onFinishCB: () => void) {
|
||||||
const docTour: IOnBoardingMsg[] = await makeDocTour(docData) || invalidDocTour;
|
const docTour: IOnBoardingMsg[] = await makeDocTour(docData) || invalidDocTour;
|
||||||
(window as any)._gristDocTour = docTour; // for easy testing
|
exposeDocTour(docTour);
|
||||||
startOnBoarding(docTour, onFinishCB);
|
startOnBoarding(docTour, onFinishCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +35,10 @@ async function makeDocTour(docData: DocData): Promise<IOnBoardingMsg[] | null> {
|
|||||||
return String(tableData.getValue(rowId, colId) || "");
|
return String(tableData.getValue(rowId, colId) || "");
|
||||||
}
|
}
|
||||||
const title = getValue("Title");
|
const title = getValue("Title");
|
||||||
const body = getValue("Body");
|
let body: HTMLElement | string = getValue("Body");
|
||||||
|
const linkText = getValue("Link_Text");
|
||||||
|
const linkUrl = getValue("Link_URL");
|
||||||
|
const linkIcon = getValue("Link_Icon") as IconName;
|
||||||
const locationValue = getValue("Location");
|
const locationValue = getValue("Location");
|
||||||
let placement = getValue("Placement");
|
let placement = getValue("Placement");
|
||||||
|
|
||||||
@ -45,6 +51,27 @@ async function makeDocTour(docData: DocData): Promise<IOnBoardingMsg[] | null> {
|
|||||||
placement = "auto";
|
placement = "auto";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let validLinkUrl = true;
|
||||||
|
try {
|
||||||
|
new URL(linkUrl);
|
||||||
|
} catch {
|
||||||
|
validLinkUrl = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validLinkUrl && linkText) {
|
||||||
|
body = dom(
|
||||||
|
'div',
|
||||||
|
dom('p', body),
|
||||||
|
dom('p',
|
||||||
|
cssButtons(cssLinkBtn(
|
||||||
|
IconList.includes(linkIcon) ? cssLinkIcon(linkIcon) : null,
|
||||||
|
linkText,
|
||||||
|
{href: linkUrl, target: '_blank'},
|
||||||
|
))
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
body,
|
body,
|
||||||
@ -60,3 +87,15 @@ async function makeDocTour(docData: DocData): Promise<IOnBoardingMsg[] | null> {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for easy testing
|
||||||
|
function exposeDocTour(docTour: IOnBoardingMsg[]) {
|
||||||
|
(window as any)._gristDocTour = () =>
|
||||||
|
docTour.map(msg => ({
|
||||||
|
...msg,
|
||||||
|
body: typeof msg.body === "string" ? msg.body
|
||||||
|
: (msg.body as HTMLElement)?.outerHTML
|
||||||
|
.replace(/_grain\d+_/g, "_grainXXX_"),
|
||||||
|
urlState: msg.urlState?.hash
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
@ -143,17 +143,17 @@ const cssInfo = styled('div', `
|
|||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const cssButtons = styled('div', `
|
export const cssButtons = styled('div', `
|
||||||
display: flex;
|
display: flex;
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const cssLinkBtn = styled(cssLink, `
|
export const cssLinkBtn = styled(cssLink, `
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
margin-right: 32px;
|
margin-right: 32px;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const cssLinkIcon = styled(icon, `
|
export const cssLinkIcon = styled(icon, `
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
`);
|
`);
|
||||||
|
Loading…
Reference in New Issue
Block a user