diff --git a/frontend/.prettierrc b/frontend/.prettierrc index 322be28b9..7c2b61247 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,7 +1,7 @@ { "tabWidth": 2, "useTabs": false, - "printWidth": 100, + "printWidth": 80, "singleQuote": true, "importOrderSeparation": true, "importOrderSortSpecifiers": true, diff --git a/frontend/app/components/Session/Player/MobilePlayer/MobileControls.tsx b/frontend/app/components/Session/Player/MobilePlayer/MobileControls.tsx index c8fbea5c9..2ba520525 100644 --- a/frontend/app/components/Session/Player/MobilePlayer/MobileControls.tsx +++ b/frontend/app/components/Session/Player/MobilePlayer/MobileControls.tsx @@ -1,33 +1,39 @@ -import { - LaunchConsoleShortcut, LaunchEventsShortcut, - LaunchNetworkShortcut, LaunchPerformanceShortcut, - LaunchXRaShortcut -} from "Components/Session_/Player/Controls/components/KeyboardHelp"; -import React from 'react'; -import cn from 'classnames'; -import { connect } from 'react-redux'; -import { PlayButton, PlayingState, FullScreenButton } from 'App/player-ui'; +import cn from 'classnames'; +import { observer } from 'mobx-react-lite'; +import React from 'react'; +import { connect } from 'react-redux'; -import { Tooltip } from 'UI'; +import { MobilePlayerContext } from 'App/components/Session/playerContext'; +import { FullScreenButton, PlayButton, PlayingState } from 'App/player-ui'; +import ControlButton from 'Components/Session_/Player/Controls/ControlButton'; +import Timeline from 'Components/Session_/Player/Controls/Timeline'; import { + LaunchConsoleShortcut, + LaunchEventsShortcut, + LaunchNetworkShortcut, + LaunchPerformanceShortcut, + LaunchXRaShortcut, +} from 'Components/Session_/Player/Controls/components/KeyboardHelp'; +import PlayerControls from 'Components/Session_/Player/Controls/components/PlayerControls'; +import styles from 'Components/Session_/Player/Controls/controls.module.css'; +import { + CONSOLE, + EXCEPTIONS, + NETWORK, + OVERVIEW, + PERFORMANCE, + STACKEVENTS, + changeSkipInterval, fullscreenOff, fullscreenOn, - OVERVIEW, toggleBottomBlock, - changeSkipInterval, - CONSOLE, STACKEVENTS, NETWORK, PERFORMANCE, EXCEPTIONS, } from 'Duck/components/player'; -import { MobilePlayerContext } from 'App/components/Session/playerContext'; -import { observer } from 'mobx-react-lite'; import { fetchSessions } from 'Duck/liveSearch'; +import { Tooltip } from 'UI'; -import Timeline from 'Components/Session_/Player/Controls/Timeline'; -import ControlButton from 'Components/Session_/Player/Controls/ControlButton'; -import PlayerControls from 'Components/Session_/Player/Controls/components/PlayerControls'; - -import styles from 'Components/Session_/Player/Controls/controls.module.css'; import XRayButton from 'Shared/XRayButton'; -import CreateNote from 'Components/Session_/Player/Controls/components/CreateNote'; +import { useStore } from "../../../../mstore"; +import { SummaryButton } from "../../../Session_/Player/Controls/Controls"; export const SKIP_INTERVALS = { 2: 2e3, @@ -44,13 +50,22 @@ function Controls(props: any) { const { playing, completed, skip, speed, messagesLoading } = store.get(); - const { bottomBlock, toggleBottomBlock, fullscreen, changeSkipInterval, skipInterval, session } = - props; + const { + bottomBlock, + toggleBottomBlock, + fullscreen, + changeSkipInterval, + skipInterval, + session, + } = props; const disabled = messagesLoading; const sessionTz = session?.timezone; const onKeyDown = (e: any) => { - if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) { + if ( + e.target instanceof HTMLInputElement || + e.target instanceof HTMLTextAreaElement + ) { return; } if (e.key === 'Esc' || e.key === 'Escape') { @@ -112,22 +127,38 @@ function Controls(props: any) { forthTenSeconds={forthTenSeconds} toggleSpeed={(speedIndex) => player.toggleSpeed(speedIndex)} toggleSkip={() => player.toggleSkip()} - playButton={} + playButton={ + + } skipIntervals={SKIP_INTERVALS} setSkipInterval={changeSkipInterval} currentInterval={skipInterval} startedAt={session.startedAt} />
-
+
- - + +
@@ -142,14 +173,42 @@ interface DevtoolsButtonsProps { bottomBlock: number; } -function DevtoolsButtons({ toggleBottomTools, bottomBlock }: DevtoolsButtonsProps) { - const { store } = React.useContext(MobilePlayerContext); +function DevtoolsButtons({ + toggleBottomTools, + bottomBlock, +}: DevtoolsButtonsProps) { + const { aiSummaryStore } = useStore(); + const { store, player } = React.useContext(MobilePlayerContext); - const { exceptionsList, logMarkedCountNow, messagesLoading, stackMarkedCountNow, resourceMarkedCountNow } = store.get(); + const { + exceptionsList, + logMarkedCountNow, + messagesLoading, + stackMarkedCountNow, + resourceMarkedCountNow, + } = store.get(); const showExceptions = exceptionsList.length > 0; + // @ts-ignore + const originStr = window.env.ORIGIN || window.location.origin; + const isSaas = /app\.openreplay\.com/.test(originStr); + + const showSummary = () => { + player.pause(); + if (bottomBlock !== OVERVIEW) { + toggleBottomTools(OVERVIEW); + } + aiSummaryStore.setToggleSummary(!aiSummaryStore.toggleSummary); + }; return ( <> + {isSaas ? ( + + ) : null} @@ -187,7 +246,7 @@ function DevtoolsButtons({ toggleBottomTools, bottomBlock }: DevtoolsButtonsProp label="Network" hasErrors={resourceMarkedCountNow > 0} /> - {showExceptions ? + {showExceptions ? ( toggleBottomTools(EXCEPTIONS)} @@ -195,7 +254,7 @@ function DevtoolsButtons({ toggleBottomTools, bottomBlock }: DevtoolsButtonsProp hasErrors={showExceptions} label="Exceptions" /> - : null} + ) : null} @@ -234,8 +293,18 @@ export default connect( disabledRedux: isEnterprise && !permissions.includes('DEV_TOOLS'), fullscreen: state.getIn(['components', 'player', 'fullscreen']), bottomBlock: state.getIn(['components', 'player', 'bottomBlock']), - showStorageRedux: !state.getIn(['components', 'player', 'hiddenHints', 'storage']), - showStackRedux: !state.getIn(['components', 'player', 'hiddenHints', 'stack']), + showStorageRedux: !state.getIn([ + 'components', + 'player', + 'hiddenHints', + 'storage', + ]), + showStackRedux: !state.getIn([ + 'components', + 'player', + 'hiddenHints', + 'stack', + ]), session: state.getIn(['sessions', 'current']), totalAssistSessions: state.getIn(['liveSearch', 'total']), skipInterval: state.getIn(['components', 'player', 'skipInterval']), diff --git a/frontend/app/components/Session_/Player/Controls/Controls.tsx b/frontend/app/components/Session_/Player/Controls/Controls.tsx index ab5b0d172..a4a0e1efe 100644 --- a/frontend/app/components/Session_/Player/Controls/Controls.tsx +++ b/frontend/app/components/Session_/Player/Controls/Controls.tsx @@ -1,5 +1,15 @@ -import { useStore } from 'App/mstore'; -import { session as sessionRoute, withSiteId } from 'App/routes'; +import { STORAGE_TYPES, StorageType, selectStorageType } from "Player"; +import { Switch } from "antd"; +import cn from "classnames"; +import { observer } from "mobx-react-lite"; +import React from "react"; +import { connect } from "react-redux"; + +import { PlayerContext } from "App/components/Session/playerContext"; +import { useStore } from "App/mstore"; +import { FullScreenButton, PlayButton, PlayingState } from "App/player-ui"; +import { session as sessionRoute, withSiteId } from "App/routes"; +import useShortcuts from "Components/Session/Player/ReplayPlayer/useShortcuts"; import { LaunchConsoleShortcut, LaunchEventsShortcut, @@ -8,16 +18,8 @@ import { LaunchStateShortcut, LaunchXRaShortcut, } from 'Components/Session_/Player/Controls/components/KeyboardHelp'; -import React from 'react'; -import cn from 'classnames'; -import { connect } from 'react-redux'; -import { selectStorageType, STORAGE_TYPES, StorageType } from 'Player'; -import { PlayButton, PlayingState, FullScreenButton } from 'App/player-ui'; -import { Switch } from 'antd' import { CONSOLE, - fullscreenOff, - fullscreenOn, GRAPHQL, INSPECTOR, NETWORK, @@ -26,21 +28,19 @@ import { PROFILER, STACKEVENTS, STORAGE, - toggleBottomBlock, changeSkipInterval, + fullscreenOff, + fullscreenOn, + toggleBottomBlock, } from 'Duck/components/player'; -import { PlayerContext } from 'App/components/Session/playerContext'; -import { observer } from 'mobx-react-lite'; -import { fetchSessions } from 'Duck/liveSearch'; -import { Icon } from 'UI'; +import { fetchSessions } from "Duck/liveSearch"; +import { Icon } from "UI"; -import Timeline from './Timeline'; -import ControlButton from './ControlButton'; -import PlayerControls from './components/PlayerControls'; +import ControlButton from "./ControlButton"; +import Timeline from "./Timeline"; +import PlayerControls from "./components/PlayerControls"; +import styles from "./controls.module.css"; -import styles from './controls.module.css'; -import CreateNote from 'Components/Session_/Player/Controls/components/CreateNote'; -import useShortcuts from 'Components/Session/Player/ReplayPlayer/useShortcuts'; export const SKIP_INTERVALS = { 2: 2e3, @@ -49,25 +49,25 @@ export const SKIP_INTERVALS = { 15: 15e3, 20: 2e4, 30: 3e4, - 60: 6e4, + 60: 6e4 }; function getStorageName(type: any) { switch (type) { case STORAGE_TYPES.REDUX: - return 'Redux'; + return "Redux"; case STORAGE_TYPES.MOBX: - return 'Mobx'; + return "Mobx"; case STORAGE_TYPES.VUEX: - return 'Vuex'; + return "Vuex"; case STORAGE_TYPES.NGRX: - return 'NgRx'; + return "NgRx"; case STORAGE_TYPES.ZUSTAND: - return 'Zustand'; + return "Zustand"; case STORAGE_TYPES.NONE: - return 'State'; + return "State"; default: - return 'State'; + return "State"; } } @@ -82,7 +82,7 @@ function Controls(props: any) { speed, messagesLoading, markedTargets, - inspectorMode, + inspectorMode } = store.get(); const { @@ -97,7 +97,7 @@ function Controls(props: any) { previousSessionId, nextSessionId, siteId, - setActiveTab, + setActiveTab } = props; const disabled = disabledRedux || messagesLoading || inspectorMode || markedTargets; @@ -118,7 +118,7 @@ function Controls(props: any) { toggleBottomBlock, openNextSession: nextHandler, openPrevSession: prevHandler, - setActiveTab, + setActiveTab }); const forthTenSeconds = () => { @@ -137,16 +137,16 @@ function Controls(props: any) { }; const state = completed - ? PlayingState.Completed - : playing - ? PlayingState.Playing - : PlayingState.Paused; + ? PlayingState.Completed + : playing + ? PlayingState.Playing + : PlayingState.Paused; return (
{!fullscreen && ( -
+
-
+
@@ -179,7 +179,7 @@ function Controls(props: any) {
@@ -216,8 +216,8 @@ const DevtoolsButtons = observer( const exceptionsList = tabStates[currentTab]?.exceptionsList || []; const storageType = store.get().tabStates[currentTab] - ? selectStorageType(store.get().tabStates[currentTab]) - : StorageType.NONE; + ? selectStorageType(store.get().tabStates[currentTab]) + : StorageType.NONE; const profilesCount = profilesList.length; const graphqlCount = graphqlList.length; const showGraphql = graphqlCount > 0; @@ -228,29 +228,34 @@ const DevtoolsButtons = observer( const showSummary = () => { player.pause(); if (bottomBlock !== OVERVIEW) { - toggleBottomTools(OVERVIEW) + toggleBottomTools(OVERVIEW); } aiSummaryStore.setToggleSummary(!aiSummaryStore.toggleSummary); - // showModal(, { right: true, width: 330 }); }; return ( <> - {isSaas ? : null} + {isSaas ? ( + + ) : null} +
Get a quick overview on the issues in this session.
} - label={'X-Ray'} + label={"X-Ray"} onClick={() => toggleBottomTools(OVERVIEW)} active={bottomBlock === OVERVIEW && !inspectorMode} /> +
Launch Console
@@ -264,7 +269,7 @@ const DevtoolsButtons = observer( +
Launch Network
@@ -278,7 +283,7 @@ const DevtoolsButtons = observer( +
Launch Performance
@@ -301,7 +306,7 @@ const DevtoolsButtons = observer( {showStorage && ( +
Launch State
@@ -314,7 +319,7 @@ const DevtoolsButtons = observer( )} +
Launch Events
@@ -342,7 +347,7 @@ export function SummaryButton({ onClick, withToggle, onToggle, - toggleValue, + toggleValue }: { onClick?: () => void, withToggle?: boolean, @@ -360,64 +365,65 @@ export function SummaryButton({ > {withToggle ? ( ) : null} - -
Summary AI
+ +
Summary AI
); } const gradientButton = { - border: 'double 1px transparent', - borderRadius: '60px', + border: "double 1px transparent", + borderRadius: "60px", background: - 'linear-gradient(#f6f6f6, #f6f6f6), linear-gradient(to right, #394EFF 0%, #3EAAAF 100%)', - backgroundOrigin: 'border-box', - backgroundClip: 'content-box, border-box', - cursor: 'pointer', + "linear-gradient(#f6f6f6, #f6f6f6), linear-gradient(to right, #394EFF 0%, #3EAAAF 100%)", + backgroundOrigin: "border-box", + backgroundClip: "content-box, border-box", + cursor: "pointer" }; const onHoverFillStyle = { - width: '100%', - height: '100%', - display: 'flex', - borderRadius: '60px', + width: "100%", + height: "100%", + display: "flex", + borderRadius: "60px", gap: 2, - alignItems: 'center', - padding: '2px 8px', - background: 'linear-gradient(156deg, #E3E6FF 0%, #E4F3F4 69.48%)', + alignItems: "center", + padding: "2px 8px", + background: "linear-gradient(156deg, #E3E6FF 0%, #E4F3F4 69.48%)" }; const fillStyle = { - width: '100%', - height: '100%', - display: 'flex', - borderRadius: '60px', + width: "100%", + height: "100%", + display: "flex", + borderRadius: "60px", gap: 2, - alignItems: 'center', - padding: '2px 8px', + alignItems: "center", + padding: "2px 8px" }; const ControlPlayer = observer(Controls); export default connect( (state: any) => { - const permissions = state.getIn(['user', 'account', 'permissions']) || []; - const isEnterprise = state.getIn(['user', 'account', 'edition']) === 'ee'; + const permissions = state.getIn(["user", "account", "permissions"]) || []; + const isEnterprise = state.getIn(["user", "account", "edition"]) === "ee"; return { - disabledRedux: isEnterprise && !permissions.includes('DEV_TOOLS'), - fullscreen: state.getIn(['components', 'player', 'fullscreen']), - bottomBlock: state.getIn(['components', 'player', 'bottomBlock']), - showStorageRedux: !state.getIn(['components', 'player', 'hiddenHints', 'storage']), - showStackRedux: !state.getIn(['components', 'player', 'hiddenHints', 'stack']), - session: state.getIn(['sessions', 'current']), - totalAssistSessions: state.getIn(['liveSearch', 'total']), - skipInterval: state.getIn(['components', 'player', 'skipInterval']), - previousSessionId: state.getIn(['sessions', 'previousId']), - nextSessionId: state.getIn(['sessions', 'nextId']), - siteId: state.getIn(['site', 'siteId']), + disabledRedux: isEnterprise && !permissions.includes("DEV_TOOLS"), + fullscreen: state.getIn(["components", "player", "fullscreen"]), + bottomBlock: state.getIn(["components", "player", "bottomBlock"]), + showStorageRedux: !state.getIn(["components", "player", "hiddenHints", "storage"]), + showStackRedux: !state.getIn(["components", "player", "hiddenHints", "stack"]), + session: state.getIn(["sessions", "current"]), + totalAssistSessions: state.getIn(["liveSearch", "total"]), + skipInterval: state.getIn(["components", "player", "skipInterval"]), + previousSessionId: state.getIn(["sessions", "previousId"]), + nextSessionId: state.getIn(["sessions", "nextId"]), + siteId: state.getIn(["site", "siteId"]) }; }, { @@ -425,7 +431,7 @@ export default connect( fullscreenOff, toggleBottomBlock, fetchSessions, - changeSkipInterval, + changeSkipInterval } )(ControlPlayer); diff --git a/frontend/app/duck/components/player.ts b/frontend/app/duck/components/player.ts index 0d8b3d0bd..417729aae 100644 --- a/frontend/app/duck/components/player.ts +++ b/frontend/app/duck/components/player.ts @@ -1,4 +1,4 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; interface PlayerState { fullscreen: boolean; @@ -12,8 +12,8 @@ interface PlayerState { enabled: boolean; startTs: number; endTs: number; - } - zoomTab: 'overview' | 'journey' | 'issues' | 'errors', + }; + zoomTab: 'overview' | 'journey' | 'issues' | 'errors'; } const initialState: PlayerState = { @@ -39,8 +39,15 @@ export const playerSlice = createSlice({ toggleFullscreen: (state, action: PayloadAction) => { state.fullscreen = action.payload !== undefined ? action.payload : !state.fullscreen; }, + fullscreenOff: (state) => { + state.fullscreen = false; + }, + fullscreenOn: (state) => { + state.fullscreen = true; + }, toggleBottomBlock: (state, action: PayloadAction) => { - state.bottomBlock = state.bottomBlock !== action.payload && action.payload !== 0 ? action.payload : 0; + state.bottomBlock = + state.bottomBlock !== action.payload && action.payload !== 0 ? action.payload : 0; }, closeBottomBlock: (state) => { state.bottomBlock = 0; @@ -66,13 +73,26 @@ export const playerSlice = createSlice({ }, setZoomTab: (state, action: PayloadAction<'overview' | 'journey' | 'issues' | 'errors'>) => { state.zoomTab = action.payload; - } + }, }, }); -interface ToggleZoomPayload { enabled: boolean, range?: [number, number]} +interface ToggleZoomPayload { + enabled: boolean; + range?: [number, number]; +} -export const { toggleFullscreen, toggleBottomBlock, changeSkipInterval, hideHint, toggleZoom, setZoomTab, closeBottomBlock } = playerSlice.actions; +export const { + toggleFullscreen, + toggleBottomBlock, + changeSkipInterval, + hideHint, + toggleZoom, + setZoomTab, + closeBottomBlock, + fullscreenOff, + fullscreenOn, +} = playerSlice.actions; export default playerSlice.reducer;