aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/frontend/src/main/components/pageSummary/pageSummary.tsx
blob: c5a8344fcfb3691db609d0aeaa1eaf5a8dca21cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import React, { useState, useEffect } from "react";
import './pageSummary.scss'
import _ from "lodash";
import Scrollspy from 'react-scrollspy'

type PageSummaryProps = {
    entries: PageSummaryEntry[],
    containerId: string, //Id of a container that has scroll enabled 
    offsetComponentId: string, //Id of a top navbar component
}

type PageSummaryEntry = {
    location: string,
    label: string,
    sourceSets: SourceSetFilterKey[]
}

type SourceSetFilterKey = string

const getElementHeightFromDom = (elementId: string): number => document.getElementById(elementId).offsetHeight

export const PageSummary: React.FC<PageSummaryProps> = ({ entries, containerId, offsetComponentId }: PageSummaryProps) => {
    const [hidden, setHidden] = useState<Boolean>(true);
    const [displayableEntries, setDisplayableEntries] = useState<PageSummaryEntry[]>(entries)
    const topOffset = getElementHeightFromDom(offsetComponentId)

    useEffect(() => {
        const handeEvent = (event: CustomEvent<SourceSetFilterKey[]>) => {
            const displayable = entries.filter((entry) => entry.sourceSets.some((sourceset) => event.detail.includes(sourceset)))
            setDisplayableEntries(displayable)
        }

        window.addEventListener('sourceset-filter-change', handeEvent)
        return () => window.removeEventListener('sourceset-filter-change', handeEvent)
    }, [entries])

    const handleMouseHover = () => {
        setHidden(!hidden)
    }

    const handleClick = (entry: PageSummaryEntry) => {
        document.getElementById(containerId).scrollTo({
            top: document.getElementById(entry.location).offsetTop - topOffset,
            behavior: 'smooth'
        })
    }

    let classnames = "page-summary"
    if (hidden) classnames += " hidden"

    return (
        <div
            className={classnames}
            onMouseEnter={handleMouseHover}
            onMouseLeave={handleMouseHover}
        >
            <div className={"content-wrapper"}>
                <h4>On this page</h4>
                {!hidden && <Scrollspy items={displayableEntries.map((e) => e.location)} currentClassName="selected">
                    {displayableEntries.map((item) => <li><a onClick={() => handleClick(item)}>{item.label}</a></li>)}
                </Scrollspy>}
            </div>
        </div>
    )
}