* feat tracker: add document titles to tabs * feat: titles for tabs * feat tracker: send initial title, parse titles better * feat ui: tab name styles * feat tracker: update changelogs * fix tracker: fix tests * fix tracker: fix failing tests, add some coverage * fix tracker: fix failing tests, add some coverage * Heatmaps (#2264) * feat ui: start heatmaps ui and tracker update * fix ui: drop clickmap from session * fix ui: refactor heatmap painter * fix ui: store click coords as int percent * feat(backend): insert normalized x and y to PG * feat(backend): insert normalized x and y to CH * feat(connector): added missing import * feat(backend): fixed different uint type issue * fix tracker: use max scrollable size for doc * fix gen files * fix ui: fix random crash, remove demo data generator * fix ui: rm some dead code --------- Co-authored-by: Alexander <zavorotynskiy@pm.me> * fix tracker: add heatmap changelog to tracker CHANGELOG.md * fix tracker: fix peerjs version to 1.5.4 (was 1.5.1) * fix document height calculation * Crossdomain tracking (#2277) * feat tracker: crossdomain tracking (start commit) * catch crossdomain messages, add nodeid placeholder * click scroll * frame placeholder number -> dynamic * click rewriter, fix scroll prop * some docs * some docs * fix options merging * CHANGELOG.md update * checking that crossdomain will not fire automatically * simplify func declaration * update test data * change clickmap document height calculation to scrollheight (which should be true height) --------- Co-authored-by: Alexander <zavorotynskiy@pm.me>
107 lines
2.9 KiB
TypeScript
107 lines
2.9 KiB
TypeScript
import React from 'react';
|
|
import { observer } from 'mobx-react-lite';
|
|
import cn from 'classnames';
|
|
import Tab from './Tab';
|
|
import { PlayerContext } from 'Components/Session/playerContext';
|
|
import { useModal } from 'Components/Modal';
|
|
|
|
interface Props {
|
|
tabs: { tab: string; idx: number }[];
|
|
currentTab: string;
|
|
changeTab: (tab: string) => void;
|
|
hideModal: () => void;
|
|
}
|
|
|
|
function Modal({ tabs, currentTab, changeTab, hideModal }: Props) {
|
|
return (
|
|
<div className={'h-screen overflow-y-scroll'}>
|
|
<div className={'text-2xl font-semibold p-4'}>{tabs.length} Tabs</div>
|
|
{tabs.map((tab, i) => (
|
|
<div
|
|
key={tab.idx}
|
|
onClick={() => {
|
|
changeTab(tab.tab);
|
|
hideModal();
|
|
}}
|
|
className={cn(
|
|
currentTab === tab.tab ? 'font-semibold ' : 'text-disabled-text',
|
|
'cursor-pointer border-b p-4 hover:bg-active-blue'
|
|
)}
|
|
>
|
|
Tab {i + 1}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function SessionTabs({ isLive }: { isLive?: boolean }) {
|
|
const { showModal, hideModal } = useModal();
|
|
const { player, store } = React.useContext(PlayerContext);
|
|
const { tabs = new Set('back-compat'), currentTab, closedTabs, tabNames } = store.get();
|
|
|
|
const tabsArr = Array.from(tabs).map((tab, idx) => ({
|
|
tab,
|
|
idx,
|
|
isClosed: closedTabs.includes(tab)
|
|
}));
|
|
const shouldTruncate = tabsArr.length > 10;
|
|
const actualTabs = shouldTruncate ? tabsArr.slice(0, 10) : tabsArr;
|
|
|
|
const shownTabs =
|
|
actualTabs.findIndex((el) => el.tab === currentTab) !== -1
|
|
? actualTabs
|
|
: actualTabs.concat({
|
|
tab: currentTab,
|
|
isClosed: false,
|
|
idx: tabsArr.findIndex((tEl) => tEl.tab === currentTab),
|
|
});
|
|
const changeTab = (tab: string) => {
|
|
if (isLive) return;
|
|
player.changeTab(tab);
|
|
};
|
|
|
|
const openModal = () => {
|
|
showModal(
|
|
<Modal hideModal={hideModal} currentTab={currentTab} changeTab={changeTab} tabs={tabsArr} />,
|
|
{
|
|
right: true,
|
|
}
|
|
);
|
|
};
|
|
return (
|
|
<>
|
|
{shownTabs.map((tab, i) => (
|
|
<React.Fragment key={tab.tab}>
|
|
<Tab
|
|
i={tab.idx}
|
|
tab={tab.tab}
|
|
currentTab={actualTabs.length === 1 ? tab.tab : currentTab}
|
|
changeTab={changeTab}
|
|
isLive={isLive}
|
|
isClosed={tab.isClosed}
|
|
name={tabNames[tab.tab]}
|
|
/>
|
|
</React.Fragment>
|
|
))}
|
|
{shouldTruncate ? (
|
|
<>
|
|
{tabsArr.length > 11 ? (
|
|
<div
|
|
onClick={openModal}
|
|
className={cn(
|
|
'self-end py-1 px-4 text-sm',
|
|
'cursor-pointer bg-active-blue text-blue',
|
|
'!border-t-transparent !border-l-transparent !border-r-transparent'
|
|
)}
|
|
>
|
|
+{tabsArr.length - 11} More
|
|
</div>
|
|
) : null}
|
|
</>
|
|
) : null}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default observer(SessionTabs);
|