Skip to content

Commit

Permalink
add final tour steps
Browse files Browse the repository at this point in the history
  • Loading branch information
frostyfan109 committed Sep 12, 2024
1 parent c51c745 commit 2f9df27
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 13 deletions.
137 changes: 130 additions & 7 deletions src/contexts/tour-context/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const waitForSelector = async (selector: string, errorSelector?: string, timeout
}

const getExpandButton = () => document.querySelector<HTMLSpanElement>(`.result-card:first-child span.anticon-expand`)
const getConceptViewRadioOption = () => document.querySelector<HTMLLabelElement>(`.search-layout-radio-group > label:nth-child(1)`)
const getVariableViewRadioOption = () => document.querySelector<HTMLLabelElement>(`.search-layout-radio-group > label:nth-child(2)`)

export const TourProvider = ({ children }: ITourProvider ) => {
Expand All @@ -79,6 +80,24 @@ export const TourProvider = ({ children }: ITourProvider ) => {
const resultCardDomMask = useSyntheticDOMMask(".result-card:first-child", { blockClicks: false })
const resultModalDomMask = useSyntheticDOMMask(".concept-modal > .ant-modal-content", { blockClicks: false })
const variableRadioOptionDomMask = useSyntheticDOMMask(".search-layout-radio-group > label:nth-child(2)", { blockClicks: false })
const studyListItemDomMask = useSyntheticDOMMask(".variables-collapse > div:first-child", {
blockClicks: false,
padding: {
top: 0,
bottom: 0,
left: 32,
right: 32
}
})
const supportNavDomMask = useSyntheticDOMMask(`.helx-header ul.ant-menu > li[data-menu-id$="/support"] > span`, {
blockClicks: false,
padding: {
top: 24,
bottom: 24,
left: 12,
right: 12
}
})

const tourOptions = useMemo<Tour.TourOptions>(() => ({
defaultStepOptions: {
Expand Down Expand Up @@ -125,7 +144,7 @@ export const TourProvider = ({ children }: ITourProvider ) => {
<div>
HSS is an open-access search engine for exploring the HEAL research landscape.<br /><br />
HSS is not the search you use every day - it uses linked knowledge to return concepts related
to your search term. This enables researchers to find biomedical concepts of interest
to your search. This enables researchers to find biomedical concepts of interest
in the HEAL space such as diseases, phenotypes, anatomical parts, and drugs. Click next
to begin a tour.
</div>
Expand Down Expand Up @@ -192,15 +211,15 @@ export const TourProvider = ({ children }: ITourProvider ) => {
attachTo: {
element: "head"
},
title: "Concept overview",
title: "Concept search",
text: renderToStaticMarkup(
<div>
When a user searches for a term, HSS returns relevant biomedical concepts in the form of concept cards.
Each card has some abbreviated information, allowing you to zoom in on studies, variables, and CDEs that
are related to the concept.<br /><br />

In HSS, a concept is a named entity defined in an ontology or another formal knowledge source. This means
the biomedical concept, and its relation to the search term, comes from a well-defined, established source.
the biomedical concept, and its relation to the search query, comes from a well-defined, established source.
</div>
),
beforeShowPromise: async () => {
Expand Down Expand Up @@ -485,9 +504,9 @@ export const TourProvider = ({ children }: ITourProvider ) => {
text: renderToStaticMarkup(
<div>
HSS also offers variable-level searching. Click on the Variables button
shows variables containing the search query or synonyms grouped by study.
shows variables matching the search terms or synonyms grouped by study.
Similar to concepts, variable results are scored based on the level of the match
between variable information (name, description, related terms) and the search term.
between variable information (name, description, related terms) and the search terms.
</div>
),
buttons: [
Expand All @@ -499,7 +518,11 @@ export const TourProvider = ({ children }: ITourProvider ) => {
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
action: function() {
const variableViewOption = getVariableViewRadioOption()!
this.next()
variableViewOption.click()
}
}
],
when: (() => {
Expand Down Expand Up @@ -540,7 +563,107 @@ export const TourProvider = ({ children }: ITourProvider ) => {
}
})()
},

{
id: "main.search.variable-view.intro",
attachTo: {
element: "head"
},
title: "Variable search",
text: renderToStaticMarkup(
<div>
Variable search returns all the variables with a match with the search term.
HSS provides a histogram filter to zoom in on higher-scoring results (those more
relevant to the search query). Hovering the mouse pointer over each variable in the
histogram displays additional information, including its name, description, and study.
</div>
),
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Back',
action: function() {
const conceptGridViewOption = getConceptViewRadioOption()!
this.back()
conceptGridViewOption.click()
}
},
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
}
],
},
{
id: "main.search.variable-view.study-list",
attachTo: {
element: studyListItemDomMask.selector,
on: "bottom"
},
scrollToHandler: () => scrollIntoViewIfNeeded(studyListItemDomMask.originalSelector),
title: "",
text: renderToStaticMarkup(
<div>
You can also click to expand each study to view the study variables associated
with the search query.
</div>
),
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Back',
type: 'back'
},
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
}
],
when: {
show: () => { studyListItemDomMask.showMask() },
hide: () => { studyListItemDomMask.hideMask() },
cancel: () => { studyListItemDomMask.hideMask() },
complete: () => { studyListItemDomMask.hideMask() }
}
},
{
id: "main.outro",
attachTo: {
element: supportNavDomMask.selector,
on: "bottom"
},
scrollToHandler: () => scrollIntoViewIfNeeded(supportNavDomMask.originalSelector),
title: "Conclusion",
text: renderToStaticMarkup(
<div>
This concludes the introductory tour of HSS. For more detailed information,
read our <a href={ context.user_guide_url } target="_blank" rel="noopener noreferrer">User Guide</a>
or visit our support page to revisit the tour or access the Help Portal, where you can report bugs,
request technical assistance, submit feedback, or submit other requests.<br /><br />

Happy searching!
</div>
),
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Back',
type: 'back'
},
{
classes: 'shepherd-button-primary',
text: 'Done',
type: 'next'
}
],
when: {
show: () => { supportNavDomMask.showMask() },
hide: () => { supportNavDomMask.hideMask() },
cancel: () => { supportNavDomMask.hideMask() },
complete: () => { supportNavDomMask.hideMask() }
}
}
]
return []
}, [searchBarDomMask, basePath, navigate, doSearch])
Expand Down
24 changes: 18 additions & 6 deletions src/hooks/use-synthetic-dom-mask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { v4 as uuid } from 'uuid'

interface SyntheticDOMMaskOptions {
padding?: number
padding?: number | { top: number, right: number, bottom: number, left: number }
resizeInterval?: number
selectorInterval?: number
blockClicks?: boolean
Expand Down Expand Up @@ -45,6 +45,18 @@ export const useSyntheticDOMMask = (
element: mask
}) as const, [mask, selector])

const [paddingTop, paddingRight, paddingBottom, paddingLeft] = useMemo(() => (typeof padding === "number" ? [
padding,
padding,
padding,
padding
] : [
padding.top,
padding.right,
padding.bottom,
padding.left
]), [padding])

const resize = useCallback((element: HTMLElement, bb: DOMRect) => {
const elBB = element.getBoundingClientRect()
if (elBB.x !== bb.x) element.style.left = (bb.x) + "px"
Expand All @@ -59,13 +71,13 @@ export const useSyntheticDOMMask = (
elements.forEach((element) => {
const bb = element.getBoundingClientRect()
if (bb.width === 0 || bb.height === 0) return
x1 = Math.min(x1, bb.x - padding)
y1 = Math.min(y1, bb.y - padding)
x2 = Math.max(x2, bb.right + padding)
y2 = Math.max(y2, bb.bottom + padding)
x1 = Math.min(x1, bb.x - paddingLeft)
y1 = Math.min(y1, bb.y - paddingTop)
x2 = Math.max(x2, bb.right + paddingRight)
y2 = Math.max(y2, bb.bottom + paddingBottom)
})
return new DOMRect(x1, y1, x2 - x1, y2 - y1)
}, [padding])
}, [paddingTop, paddingRight, paddingBottom, paddingLeft])

useEffect(() => {
mask.style.pointerEvents = blockClicks ? "auto" : "none"
Expand Down

0 comments on commit 2f9df27

Please sign in to comment.