change(ui): change replace and delete, change active session detection, change components and hover states

This commit is contained in:
sylenien 2022-12-02 12:41:05 +01:00 committed by Delirium
parent 92a897b9c0
commit 291e92410f
14 changed files with 272 additions and 109 deletions

View file

@ -6,7 +6,6 @@ import { Notification } from 'UI';
import { Loader } from 'UI';
import { fetchUserInfo } from 'Duck/user';
import withSiteIdUpdater from 'HOCs/withSiteIdUpdater';
import WidgetViewPure from 'Components/Dashboard/components/WidgetView';
import Header from 'Components/Header/Header';
import { fetchList as fetchSiteList } from 'Duck/site';
import { fetchList as fetchAnnouncements } from 'Duck/announcements';
@ -37,6 +36,7 @@ const ErrorsPure = lazy(() => import('Components/Errors/Errors'));
const FunnelDetailsPure = lazy(() => import('Components/Funnels/FunnelDetails'));
const FunnelIssueDetails = lazy(() => import('Components/Funnels/FunnelIssueDetails'));
const FunnelPagePure = lazy(() => import('Components/Funnels/FunnelPage'));
const MultiviewPure = lazy(() => import('Components/Session_/Multiview/Multiview.tsx'));
const BugFinder = withSiteIdUpdater(BugFinderPure);
const Dashboard = withSiteIdUpdater(DashboardPure);
@ -49,6 +49,7 @@ const Errors = withSiteIdUpdater(ErrorsPure);
const FunnelPage = withSiteIdUpdater(FunnelPagePure);
const FunnelsDetails = withSiteIdUpdater(FunnelDetailsPure);
const FunnelIssue = withSiteIdUpdater(FunnelIssueDetails);
const Multiview = withSiteIdUpdater(MultiviewPure)
const withSiteId = routes.withSiteId;
const METRICS_PATH = routes.metrics();
@ -81,6 +82,7 @@ const FORGOT_PASSWORD = routes.forgotPassword();
const CLIENT_PATH = routes.client();
const ONBOARDING_PATH = routes.onboarding();
const ONBOARDING_REDIRECT_PATH = routes.onboarding(OB_DEFAULT_TAB);
const MULTIVIEW_PATH = routes.multiview();
@withStore
@withRouter
@ -172,7 +174,7 @@ class Router extends React.Component {
const { isLoggedIn, jwt, siteId, sites, loading, changePassword, location, existingTenant, onboarding, isEnterprise } = this.props;
const siteIdList = sites.map(({ id }) => id).toJS();
const hideHeader = (location.pathname && location.pathname.includes('/session/')) || location.pathname.includes('/assist/');
const isPlayer = isRoute(SESSION_PATH, location.pathname) || isRoute(LIVE_SESSION_PATH, location.pathname);
const isPlayer = isRoute(SESSION_PATH, location.pathname) || isRoute(LIVE_SESSION_PATH, location.pathname) || isRoute(MULTIVIEW_PATH, location.pathname);
const redirectToOnboarding = !onboarding && localStorage.getItem(GLOBAL_HAS_NO_RECORDINGS) === 'true'
return isLoggedIn ? (
@ -219,6 +221,7 @@ class Router extends React.Component {
<Route exact strict path={withSiteId(DASHBOARD_METRIC_CREATE_PATH, siteIdList)} component={Dashboard} />
<Route exact strict path={withSiteId(DASHBOARD_METRIC_DETAILS_PATH, siteIdList)} component={Dashboard} />
<Route exact strict path={withSiteId(MULTIVIEW_PATH, siteIdList)} component={Multiview} />
<Route exact strict path={withSiteId(ASSIST_PATH, siteIdList)} component={Assist} />
<Route exact strict path={withSiteId(RECORDINGS_PATH, siteIdList)} component={Assist} />
<Route exact strict path={withSiteId(ERRORS_PATH, siteIdList)} component={Errors} />

View file

@ -6,7 +6,7 @@ import withRequest from 'HOCs/withRequest';
import withPermissions from 'HOCs/withPermissions';
import { PlayerContext, defaultContextValue } from './playerContext';
import { makeAutoObservable } from 'mobx';
import { createLiveWebPlayer } from 'Player'
import { createLiveWebPlayer } from 'Player';
import PlayerBlockHeader from '../Session_/PlayerBlockHeader';
import PlayerBlock from '../Session_/PlayerBlock';
import styles from '../Session_/session.module.css';
@ -23,6 +23,8 @@ interface Props {
isEnterprise: boolean;
userEmail: string;
userName: string;
isMultiview?: boolean;
customSession?: Session;
}
function LivePlayer({
@ -36,34 +38,39 @@ function LivePlayer({
isEnterprise,
userEmail,
userName,
isMultiview,
customSession,
}: Props) {
const [contextValue, setContextValue] = useState(defaultContextValue);
const [fullView, setFullView] = useState(false);
// @ts-ignore burn immutable
const usedSession = isMultiview ? customSession : session.toJS();
useEffect(() => {
if (loadingCredentials || !session.sessionId) return;
if (loadingCredentials || !usedSession.sessionId) return;
const sessionWithAgentData = {
// @ts-ignore burn immutable
...session.toJS(),
...usedSession,
agentInfo: {
email: userEmail,
name: userName,
},
}
const [player, store] = createLiveWebPlayer(
sessionWithAgentData,
assistCredendials,
(state) => makeAutoObservable(state)
)
setContextValue({ player, store })
player.play()
return () => player.clean()
}, [ session.sessionId, assistCredendials ])
};
const [player, store] = createLiveWebPlayer(sessionWithAgentData, assistCredendials, (state) =>
makeAutoObservable(state)
);
setContextValue({ player, store });
player.play();
return () => player.clean();
}, [session.sessionId, assistCredendials]);
// LAYOUT (TODO: local layout state - useContext or something..)
useEffect(() => {
const queryParams = new URLSearchParams(window.location.search);
if (queryParams.has('fullScreen') && queryParams.get('fullScreen') === 'true') {
if (
(queryParams.has('fullScreen') && queryParams.get('fullScreen') === 'true') ||
location.pathname.includes('multiview')
) {
setFullView(true);
}
@ -95,8 +102,15 @@ function LivePlayer({
fullscreen={fullscreen}
/>
)}
<div className={styles.session} data-fullscreen={fullscreen}>
<PlayerBlock />
<div
className={styles.session}
style={{
height: isMultiview ? '100%' : undefined,
width: isMultiview ? '100%' : undefined,
}}
data-fullscreen={fullscreen}
>
<PlayerBlock isMultiview={isMultiview} />
</div>
</PlayerContext.Provider>
);

View file

@ -0,0 +1,92 @@
import React from 'react';
import { useStore } from 'App/mstore';
import { BackLink, Icon } from 'UI'
import { observer } from 'mobx-react-lite';
import { connect } from 'react-redux';
import { fetchSessions } from 'Duck/liveSearch';
import { useHistory } from 'react-router-dom';
import { liveSession, assist, withSiteId } from 'App/routes';
import AssistSessionsModal from 'App/components/Session_/Player/Controls/AssistSessionsModal';
import { useModal } from 'App/components/Modal';
import LivePlayer from 'App/components/Session/LivePlayer';
function Multiview({ total, fetchSessions, siteId }: { total: number; fetchSessions: (filter: any) => void, siteId: string }) {
const { showModal, hideModal } = useModal();
const { assistMultiviewStore } = useStore();
const history = useHistory();
React.useEffect(() => {
if (total === 0) {
fetchSessions({});
}
}, []);
const openLiveSession = (e: React.MouseEvent, sessionId: string) => {
e.stopPropagation()
assistMultiviewStore.setActiveSession(sessionId);
history.push(withSiteId(liveSession(sessionId), siteId));
};
const openList = () => {
history.push(withSiteId(assist(), siteId))
}
const openListModal = () => {
showModal(<AssistSessionsModal onAdd={hideModal} />, { right: true });
}
const replaceSession = (e: React.MouseEvent, sessionId: string) => {
e.stopPropagation()
showModal(<AssistSessionsModal onAdd={hideModal} replaceTarget={sessionId} />, { right: true });
}
const deleteSession = (e: React.MouseEvent, sessionId: string) => {
e.stopPropagation()
assistMultiviewStore.removeSession(sessionId)
}
const placeholder = new Array(4 - assistMultiviewStore.sessions.length).fill(0);
return (
<div className="w-screen h-screen flex flex-col">
<div className="w-full p-4 flex justify-between items-center">
{/* @ts-ignore */}
<div><BackLink label="Back to sessions list" onClick={openList}/> </div>
<div>{`Watching ${assistMultiviewStore.sessions.length} of ${total} Live Sessions`}</div>
</div>
<div className="w-full h-full grid grid-cols-2 grid-rows-2">
{assistMultiviewStore.sortedSessions.map((session) => (
<div
key={session.key}
className="border hover:border-active-blue-border relative group cursor-pointer"
>
<div onClick={(e) => openLiveSession(e, session.sessionId)} className="w-full h-full">
<LivePlayer isMultiview customSession={session} />
</div>
<div className="absolute bottom-0 w-full left-0 p-2 opacity-70 bg-gray-darkest text-white flex justify-between">
<div>{session.userDisplayName}</div>
<div className="hidden group-hover:flex items-center gap-2">
<div className="cursor-pointer hover:font-semibold" onClick={(e) => replaceSession(e, session.sessionId)}>Replace Session</div>
<div className="cursor-pointer hover:font-semibold" onClick={(e) => deleteSession(e, session.sessionId)}>
<Icon name="trash" size={18} color="white" />
</div>
</div>
</div>
</div>
))}
{placeholder.map((_, i) => (
<div key={i} className="border hover:border-active-blue-border flex items-center justify-center cursor-pointer" onClick={openListModal}>
Add Session
</div>
))}
</div>
</div>
);
}
export default connect(
(state: any) => ({
total: state.getIn(['liveSearch', 'total']),
siteId: state.getIn([ 'site', 'siteId' ])
}),
{
fetchSessions,
}
)(observer(Multiview));

View file

@ -27,6 +27,7 @@ interface ConnectProps {
metaList: any;
sort: any;
total: number;
replaceTarget?: string;
addFilterByKeyAndValue: (key: FilterKey, value: string) => void;
updateCurrentPage: (page: number) => void;
applyFilter: (filter: any) => void;
@ -36,7 +37,7 @@ interface ConnectProps {
type Props = OwnProps & ConnectProps;
function AssistSessionsModal(props: Props) {
const { assistTabStore } = useStore();
const { assistMultiviewStore } = useStore();
const { loading, list, metaList = [], filter, currentPage, total, onAdd } = props;
const onUserClick = () => false;
const { filters } = filter;
@ -56,7 +57,11 @@ function AssistSessionsModal(props: Props) {
props.applyFilter({ sort: value.value });
};
const onSessionAdd = (session: Session) => {
assistTabStore.addSession(session);
if (props.replaceTarget) {
assistMultiviewStore.replaceSession(props.replaceTarget, session)
} else {
assistMultiviewStore.addSession(session);
}
onAdd()
}
@ -87,7 +92,7 @@ function AssistSessionsModal(props: Props) {
<>
{list.map((session) => (
<React.Fragment key={session.sessionID}>
<div className={cn("rounded bg-white mb-2 overflow-hidden border", session.sessionId === assistTabStore.activeSession.sessionId ? 'cursor-not-allowed' : '')}>
<div className={cn("rounded bg-white mb-2 overflow-hidden border", assistMultiviewStore.sessions.findIndex(s => s.sessionId === session.sessionId) !== -1 ? 'cursor-not-allowed' : '')}>
<SessionItem
key={session.sessionId}
session={session}
@ -95,7 +100,7 @@ function AssistSessionsModal(props: Props) {
hasUserFilter={hasUserFilter}
onUserClick={onUserClick}
metaList={metaList}
isDisabled={session.sessionId === assistTabStore.activeSession.sessionId}
isDisabled={assistMultiviewStore.sessions.findIndex(s => s.sessionId === session.sessionId) !== -1}
isAdd
onClick={() => onSessionAdd(session)}
/>

View file

@ -1,22 +1,20 @@
import React from 'react';
import cn from 'classnames';
import { useModal } from 'App/components/Modal';
import { Icon } from 'UI';
import AssistSessionsModal from '../AssistSessionsModal';
import { useStore } from 'App/mstore'
import Session from 'App/mstore/types/session'
import { observer } from 'mobx-react-lite'
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { useHistory } from 'react-router-dom';
import { multiview, liveSession, withSiteId } from 'App/routes';
import { connect } from 'react-redux';
interface ITab {
onClick?: () => void;
onDoubleClick?: () => void;
classNames?: string;
children: React.ReactNode;
}
const Tab = (props: ITab) => (
<div
onDoubleClick={props.onDoubleClick}
onClick={props.onClick}
className={cn('p-1 rounded flex items-center justify-center cursor-pointer', props.classNames)}
>
@ -24,13 +22,13 @@ const Tab = (props: ITab) => (
</div>
);
const InactiveTab = (props: Omit<ITab, 'children' | 'onDoubleClick'>) => (
const InactiveTab = (props: Omit<ITab, 'children'>) => (
<Tab onClick={props.onClick} classNames="hover:bg-gray-bg bg-gray-light">
<Icon name="plus" size="22" color="white" />
</Tab>
);
const ActiveTab = (props: Omit<ITab, 'children'>) => (
<Tab onDoubleClick={props.onDoubleClick} classNames="hover:bg-teal bg-borderColor-primary">
<Tab onClick={props.onClick} classNames="hover:bg-teal bg-borderColor-primary">
<Icon name="play-fill-new" size="22" color="white" />
</Tab>
);
@ -40,37 +38,47 @@ const CurrentTab = () => (
</Tab>
);
function AssistTabs({ session }: { session: Session }) {
const { showModal, hideModal } = useModal();
const { assistTabStore } = useStore()
function AssistTabs({ session, siteId }: { session: Record<string, any>; siteId: string }) {
const history = useHistory();
const { assistMultiviewStore } = useStore();
const placeholder = new Array(4 - assistTabStore.sessions.length).fill(0)
const placeholder = new Array(4 - assistMultiviewStore.sessions.length).fill(0);
React.useEffect(() => {
if (assistTabStore.sessions.length === 0) {
assistTabStore.addSession(session)
assistTabStore.setActiveSession(session.sessionId)
console.log(assistTabStore.sessions, assistTabStore.activeSession, session.sessionId)
if (assistMultiviewStore.sessions.length === 0) {
assistMultiviewStore.setDefault(session);
}
}, [])
}, []);
const showAssistList = () => showModal(<AssistSessionsModal onAdd={hideModal} />, { right: true });
const openGrid = () => {
history.push(withSiteId(multiview(), siteId));
};
const openLiveSession = (sessionId: string) => {
assistMultiviewStore.setActiveSession(sessionId);
history.push(withSiteId(liveSession(sessionId), siteId));
};
console.log(assistMultiviewStore.activeSessionId)
return (
<div className="grid grid-cols-2 w-28 h-full" style={{ gap: '4px' }}>
{assistTabStore.sessions.map(session => (
<React.Fragment key={session.sessionId}>
{assistTabStore.isActive(session.sessionId)
? <CurrentTab /> : <ActiveTab onClick={() => assistTabStore.setActiveSession(session.sessionId)} />}
{assistMultiviewStore.sortedSessions.map((session) => (
<React.Fragment key={session.key}>
{assistMultiviewStore.isActive(session.sessionId) ? (
<CurrentTab />
) : (
<ActiveTab onClick={() => openLiveSession(session.sessionId)} />
)}
</React.Fragment>
)
)}
))}
{placeholder.map((_, i) => (
<React.Fragment key={i}>
<InactiveTab onClick={showAssistList} />
<InactiveTab onClick={openGrid} />
</React.Fragment>
))}
</div>
);
}
export default observer(AssistTabs);
export default connect((state: any) => ({ siteId: state.getIn(['site', 'siteId']) }))(
observer(AssistTabs)
);

View file

@ -23,6 +23,7 @@ import {
} from 'Duck/components/player';
import { PlayerContext } from 'App/components/Session/playerContext';
import { observer } from 'mobx-react-lite';
import { fetchSessions } from 'Duck/liveSearch';
import { AssistDuration } from './Time';
import Timeline from './Timeline';
@ -98,8 +99,11 @@ function Controls(props: any) {
showStorageRedux,
session,
// showStackRedux,
fetchSessions: fetchAssistSessions,
totalAssistSessions,
} = props;
const isAssist = window.location.pathname.includes('/assist/');
const storageType = selectStorageType(store.get());
const disabled = disabledRedux || cssLoading || messagesLoading || inspectorMode || markedTargets;
const profilesCount = profilesList.length;
@ -141,6 +145,9 @@ function Controls(props: any) {
React.useEffect(() => {
document.addEventListener('keydown', onKeyDown.bind(this));
if (isAssist && totalAssistSessions === 0) {
fetchAssistSessions();
}
return () => {
document.removeEventListener('keydown', onKeyDown.bind(this));
};
@ -148,12 +155,12 @@ function Controls(props: any) {
const forthTenSeconds = () => {
// @ts-ignore
player.jumpInterval(SKIP_INTERVALS[skipInterval])
player.jumpInterval(SKIP_INTERVALS[skipInterval]);
};
const backTenSeconds = () => {
// @ts-ignore
player.jumpInterval(-SKIP_INTERVALS[skipInterval])
player.jumpInterval(-SKIP_INTERVALS[skipInterval]);
};
const renderPlayBtn = () => {
@ -261,9 +268,11 @@ function Controls(props: any) {
)}
</div>
<div>
<AssistSessionsTabs session={session} />
</div>
{isAssist && totalAssistSessions > 1 ? (
<div>
<AssistSessionsTabs session={session} />
</div>
) : null}
<div className="flex items-center h-full">
<ControlButton
@ -375,6 +384,7 @@ export default connect(
showStorageRedux: !state.getIn(['components', 'player', 'hiddenHints', 'storage']),
showStackRedux: !state.getIn(['components', 'player', 'hiddenHints', 'stack']),
session: state.getIn(['sessions', 'current']),
totalAssistSessions: state.getIn(['liveSearch', 'total']),
closedLive:
!!state.getIn(['sessions', 'errors']) || !state.getIn(['sessions', 'current', 'live']),
skipInterval: state.getIn(['components', 'player', 'skipInterval']),
@ -385,6 +395,7 @@ export default connect(
fullscreenOff,
toggleBottomBlock,
changeSkipInterval,
fetchSessions,
}
)(ControlPlayer);

View file

@ -44,6 +44,7 @@ function Player(props) {
bottomBlock,
activeTab,
fullView,
isMultiview,
} = props;
const playerContext = React.useContext(PlayerContext)
const screenWrapper = React.useRef();
@ -80,7 +81,6 @@ function Player(props) {
{bottomBlock === OVERVIEW && <OverviewPanel />}
{bottomBlock === CONSOLE && <ConsolePanel />}
{bottomBlock === NETWORK && (
// <Network />
<NetworkPanel />
)}
{/* {bottomBlock === STACKEVENTS && <StackEvents />} */}
@ -93,7 +93,7 @@ function Player(props) {
{bottomBlock === INSPECTOR && <Inspector />}
</div>
)}
{!fullView && <Controls
{!fullView && !isMultiview && <Controls
speedDown={playerContext.player.speedDown}
speedUp={playerContext.player.speedUp}
jump={playerContext.player.jump}

View file

@ -14,19 +14,19 @@ import styles from './playerBlock.module.css';
}))
export default class PlayerBlock extends React.PureComponent {
render() {
const { fullscreen, sessionId, disabled, activeTab, jiraConfig, fullView = false } = this.props;
const { fullscreen, sessionId, disabled, activeTab, jiraConfig, fullView = false, isMultiview } = this.props;
return (
<div className={cn(styles.playerBlock, 'flex flex-col overflow-x-hidden')}>
{!fullscreen && !fullView && (
<div className={cn(styles.playerBlock, 'flex flex-col overflow-x-hidden')} style={{ minWidth: isMultiview ? '100%' : undefined }}>
{!fullscreen && !fullView && !isMultiview && (
<SubHeader sessionId={sessionId} disabled={disabled} jiraConfig={jiraConfig} />
)}
<Player
className="flex-1"
// bottomBlockIsActive={ true }
fullscreen={fullscreen}
activeTab={activeTab}
fullView={fullView}
isMultiview={isMultiview}
/>
</div>
);

View file

@ -4,7 +4,7 @@ import cls from './backLink.module.css';
import cn from 'classnames';
export default function BackLink ({
className, to, onClick, label, vertical = false, style
className, to, onClick, label = '', vertical = false, style
}) {
const children = (
<div className={ cn('flex items-center', {'border w-10 h-10 rounded-full bg-white p-3 items-center justify-center hover:bg-active-blue' : !label })}>
@ -18,7 +18,7 @@ export default function BackLink ({
className={ verticalClassName }
to={ to }
>
{ children }
{ children }
</Link>
:
<button
@ -29,4 +29,3 @@ export default function BackLink ({
{ children }
</button>
}

View file

@ -1,4 +1,4 @@
import { List, Map } from 'immutable';
import { List, Map } from 'immutable';
import { fetchListType, fetchType, editType } from './funcTools/crud';
import { createRequestReducer } from './funcTools/request';
import { mergeReducers, success } from './funcTools/tools';
@ -23,6 +23,7 @@ const initialState = Map({
instance: new Filter({ filters: [], sort: '' }),
filterSearchList: {},
currentPage: 1,
total: 0,
});
function reducer(state = initialState, action = {}) {
@ -138,4 +139,4 @@ export function fetchFilterSearch(params) {
call: client => client.get('/events/search', params),
params,
};
}
}

View file

@ -0,0 +1,68 @@
import { makeAutoObservable } from 'mobx';
type MultiSessions = [
LiveSessionListItem?,
LiveSessionListItem?,
LiveSessionListItem?,
LiveSessionListItem?
];
export interface LiveSessionListItem extends Record<string, any> {
key: number | string;
}
export default class AssistMultiviewStore {
sessions: MultiSessions = [];
activeSession: LiveSessionListItem = null;
constructor() {
makeAutoObservable(this);
}
isActive(sessionId: string): boolean {
console.log(sessionId, this.activeSessionId)
return this.activeSessionId === sessionId;
}
get sortedSessions() {
// @ts-ignore ???
return this.sessions.slice().sort((a, b) => a.key - b.key);
}
get activeSessionId() {
return this.activeSession?.sessionId || '';
}
addSession(session: Record<string, any>) {
if (this.sessions.length < 4) {
this.sessions.push({ ...session.toJS(), key: this.sessions.length });
}
}
replaceSession(targetId: string, session: Record<string, any>) {
const targetIndex = this.sessions.findIndex(s => s.sessionId === targetId);
if (targetIndex !== -1) {
this.sessions[targetIndex] = { ...session.toJS(), key: targetIndex }
}
}
removeSession(sessionId: string) {
return this.sessions = this.sessions.filter(session => session.sessionId !== sessionId) as MultiSessions;
}
setActiveSession(sessionId: string) {
this.activeSession = this.sessions.find((session) => session.sessionId === sessionId);
}
setDefault(session: Record<string, any>) {
if (this.sessions.length === 0) {
const firstItem = {...session.toJS?.(), key: 0}
this.sessions = [firstItem]
this.activeSession = firstItem
}
}
reset() {
this.sessions = [];
this.activeSession = null;
}
}

View file

@ -1,40 +0,0 @@
import { makeAutoObservable } from "mobx"
import Session from './types/session';
type TabSessions = [Session?,Session?,Session?,Session?]
export default class AssistTabStore {
sessions: TabSessions = []
activeSession: Session = null
constructor() {
makeAutoObservable(this)
}
isActive(sessionId: string): boolean {
return this.activeSession.sessionId === sessionId
}
get activeSessionId() {
return this.activeSession?.sessionId || ''
}
setSessions(sessions: TabSessions) {
this.sessions = sessions
}
addSession(session: Session) {
if (this.sessions.length < 4) {
this.sessions.push(session)
}
}
setActiveSession(sessionId: string) {
this.activeSession = this.sessions.find(session => session.sessionId === sessionId)
}
reset() {
this.sessions = []
this.activeSession = null
}
}

View file

@ -24,7 +24,7 @@ import SessionStore from './sessionStore';
import NotesStore from './notesStore';
import BugReportStore from './bugReportStore'
import RecordingsStore from './recordingsStore'
import AssistTabStore from './assistTabStore';
import AssistMultiviewStore from './assistMultiviewStore';
export class RootStore {
dashboardStore: DashboardStore;
@ -40,7 +40,7 @@ export class RootStore {
notesStore: NotesStore;
bugReportStore: BugReportStore;
recordingsStore: RecordingsStore;
assistTabStore: AssistTabStore;
assistMultiviewStore: AssistMultiviewStore;
constructor() {
this.dashboardStore = new DashboardStore();
@ -56,7 +56,7 @@ export class RootStore {
this.notesStore = new NotesStore();
this.bugReportStore = new BugReportStore();
this.recordingsStore = new RecordingsStore();
this.assistTabStore = new AssistTabStore();
this.assistMultiviewStore = new AssistMultiviewStore();
}
initClient() {

View file

@ -85,6 +85,7 @@ export const onboarding = (tab = routerOBTabString) => `/onboarding/${ tab }`;
export const sessions = params => queried('/sessions', params);
export const assist = params => queried('/assist', params);
export const recordings = params => queried("/recordings", params);
export const multiview = params => queried("/assist/multiview", params);
export const session = (sessionId = ':sessionId', hash) => hashed(`/session/${ sessionId }`, hash);
export const liveSession = (sessionId = ':sessionId', params, hash) => hashed(queried(`/assist/${ sessionId }`, params), hash);
@ -125,6 +126,7 @@ const REQUIRED_SITE_ID_ROUTES = [
sessions(),
assist(),
recordings(),
multiview(),
metrics(),
metricDetails(''),