From d008b65ac09e5d4d51ff883eea5b92b2b27e614d Mon Sep 17 00:00:00 2001 From: Delirium Date: Mon, 15 Apr 2024 15:37:15 +0200 Subject: [PATCH] feat ui: remake cobrowse subtabs (#2086) --- frontend/app/PrivateRoutes.tsx | 8 -- .../app/components/Assist/AssistRouter.tsx | 24 +---- .../AssistSearchField/AssistSearchField.tsx | 91 ++++++++++++------- .../Assist/RecordingsList/Recordings.tsx | 6 +- .../Assist/RecordingsList/RecordingsList.tsx | 2 +- .../components/AssistStats/AssistStats.tsx | 35 ++++--- .../AssistStats/components/Table.tsx | 17 ++-- .../app/components/Client/Modules/index.ts | 2 +- .../app/components/Modal/ModalOverlay.tsx | 2 +- .../LiveSessionList/LiveSessionList.tsx | 2 +- .../SelectDateRange/SelectDateRange.tsx | 1 + frontend/app/layout/SideMenu.tsx | 5 +- frontend/app/layout/data.ts | 8 +- 13 files changed, 92 insertions(+), 111 deletions(-) diff --git a/frontend/app/PrivateRoutes.tsx b/frontend/app/PrivateRoutes.tsx index d65ac2689..d8456da80 100644 --- a/frontend/app/PrivateRoutes.tsx +++ b/frontend/app/PrivateRoutes.tsx @@ -23,7 +23,6 @@ const components: any = { FunnelIssueDetails: lazy(() => import('Components/Funnels/FunnelIssueDetails')), FunnelPagePure: lazy(() => import('Components/Funnels/FunnelPage')), MultiviewPure: lazy(() => import('Components/Session_/Multiview/Multiview')), - AssistStatsPure: lazy(() => import('Components/AssistStats')), UsabilityTestingPure: lazy(() => import('Components/UsabilityTesting/UsabilityTesting')), UsabilityTestEditPure: lazy(() => import('Components/UsabilityTesting/TestEdit')), UsabilityTestOverviewPure: lazy(() => import('Components/UsabilityTesting/TestOverview')), @@ -41,7 +40,6 @@ const enhancedComponents: any = { FunnelsDetails: withSiteIdUpdater(components.FunnelDetailsPure), FunnelIssue: withSiteIdUpdater(components.FunnelIssueDetails), Multiview: withSiteIdUpdater(components.MultiviewPure), - AssistStats: withSiteIdUpdater(components.AssistStatsPure), UsabilityTesting: withSiteIdUpdater(components.UsabilityTestingPure), UsabilityTestEdit: withSiteIdUpdater(components.UsabilityTestEditPure), UsabilityTestOverview: withSiteIdUpdater(components.UsabilityTestOverviewPure), @@ -192,12 +190,6 @@ function PrivateRoutes(props: Props) { path={withSiteId(RECORDINGS_PATH, siteIdList)} component={enhancedComponents.Assist} /> - - - - - - - - - - + ); } diff --git a/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx b/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx index f24a37a7c..e948681e2 100644 --- a/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx +++ b/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx @@ -1,43 +1,68 @@ import React from 'react'; -import { Button } from 'UI'; -import SessionSearchField from 'Shared/SessionSearchField'; import { connect } from 'react-redux'; -import { edit as editFilter, addFilterByKeyAndValue, clearSearch, fetchFilterSearch } from 'Duck/liveSearch'; + +import { + addFilterByKeyAndValue, + clearSearch, + edit as editFilter, + fetchFilterSearch, +} from 'Duck/liveSearch'; +import { Button } from 'UI'; +import { useModal } from 'App/components/Modal'; +import SessionSearchField from 'Shared/SessionSearchField'; + +import AssistStats from '../../AssistStats'; +import Recordings from '../RecordingsList/Recordings' interface Props { - appliedFilter: any; - fetchFilterSearch: any; - addFilterByKeyAndValue: any; - clearSearch: any; + appliedFilter: any; + fetchFilterSearch: any; + addFilterByKeyAndValue: any; + clearSearch: any; } function AssistSearchField(props: Props) { - const hasEvents = props.appliedFilter.filters.filter((i: any) => i.isEvent).size > 0; - const hasFilters = props.appliedFilter.filters.filter((i: any) => !i.isEvent).size > 0; - return ( -
-
- -
- -
- ); + const hasEvents = + props.appliedFilter.filters.filter((i: any) => i.isEvent).size > 0; + const hasFilters = + props.appliedFilter.filters.filter((i: any) => !i.isEvent).size > 0; + const { showModal, hideModal } = useModal(); + + const showStats = () => { + showModal(, { right: true, width: 960 }) + } + const showRecords = () => { + showModal(, { right: true, width: 960 }) + } + return ( +
+
+ +
+ + + +
+ ); } export default connect( - (state: any) => ({ - appliedFilter: state.getIn(['liveSearch', 'instance']), - }), - { - fetchFilterSearch, - editFilter, - addFilterByKeyAndValue, - clearSearch, - } + (state: any) => ({ + appliedFilter: state.getIn(['liveSearch', 'instance']), + isEnterprise: + state.getIn(['user', 'account', 'edition']) === 'ee' || + state.getIn(['user', 'authDetails', 'edition']) === 'ee' + }), + { + fetchFilterSearch, + editFilter, + addFilterByKeyAndValue, + clearSearch, + } )(AssistSearchField); diff --git a/frontend/app/components/Assist/RecordingsList/Recordings.tsx b/frontend/app/components/Assist/RecordingsList/Recordings.tsx index 8650da09a..4da82724d 100644 --- a/frontend/app/components/Assist/RecordingsList/Recordings.tsx +++ b/frontend/app/components/Assist/RecordingsList/Recordings.tsx @@ -6,12 +6,10 @@ import RecordingsList from './RecordingsList'; import { useStore } from 'App/mstore'; import { connect } from 'react-redux'; import SelectDateRange from 'Shared/SelectDateRange/SelectDateRange'; -import Period from 'Types/app/period'; import { observer } from 'mobx-react-lite'; interface Props { userId: string; - filter: any; } function Recordings(props: Props) { @@ -28,10 +26,10 @@ function Recordings(props: Props) { }; return ( -
+
- +
diff --git a/frontend/app/components/Assist/RecordingsList/RecordingsList.tsx b/frontend/app/components/Assist/RecordingsList/RecordingsList.tsx index f0b78fb71..7c67c156f 100644 --- a/frontend/app/components/Assist/RecordingsList/RecordingsList.tsx +++ b/frontend/app/components/Assist/RecordingsList/RecordingsList.tsx @@ -29,7 +29,7 @@ function RecordingsList() {
{recordsSearch !== '' ? 'No matching results' - : 'No recordings available'} + : 'No videos have been recorded in your co-browsing sessions.'}
} diff --git a/frontend/app/components/AssistStats/AssistStats.tsx b/frontend/app/components/AssistStats/AssistStats.tsx index 18e3ef789..48bfd2051 100644 --- a/frontend/app/components/AssistStats/AssistStats.tsx +++ b/frontend/app/components/AssistStats/AssistStats.tsx @@ -14,7 +14,6 @@ import Period, { LAST_24_HOURS } from 'Types/app/period'; import SelectDateRange from 'Shared/SelectDateRange/SelectDateRange'; import TeamMembers from 'Components/AssistStats/components/TeamMembers'; import { durationFromMsFormatted, formatTimeOrDate } from 'App/date' -import withPageTitle from 'HOCs/withPageTitle'; import { exportCSVFile } from 'App/utils'; import { assistStatsService } from 'App/services'; @@ -206,11 +205,11 @@ function AssistStats() { }; return ( -
+
- Reports + Co-browsing Reports
@@ -227,8 +226,7 @@ function AssistStats() {
-
-
+
{Object.keys(graphs.currentPeriod).map((i: PeriodKeys) => (
@@ -238,15 +236,15 @@ function AssistStats() {
{graphs.currentPeriod[i] - ? durationFromMsFormatted(graphs.currentPeriod[i]) - : null} + ? durationFromMsFormatted(graphs.currentPeriod[i]) + : null} {graphs.previousPeriod[i] ? (
graphs.previousPeriod[i] - ? 'flex items-center gap-1 text-green' - : 'flex items-center gap-2 text-red' + ? 'flex items-center gap-1 text-green' + : 'flex items-center gap-2 text-red' } >
))} -
-
- -
+
+
+
-
- Date +
+ Date Team Members Live Duration Call Duration - Remote Duration - - {/* SPACER */} + Remote Duration {/* BUTTONS */}
@@ -125,10 +123,10 @@ function StatsTable({ onSort, isLoading, onPageChange, page, sessions, exportCSV function Row({ session }: { session: AssistStatsSession }) { return ( -
- {checkForRecent(getDateFromMill(session.timestamp)!, 'LLL dd, hh:mm a')} +
+ {checkForRecent(getDateFromMill(session.timestamp)!, 'LLL dd, hh:mm a')} -
+
{session.teamMembers.map((member) => (
{member.name}
))} @@ -136,8 +134,7 @@ function Row({ session }: { session: AssistStatsSession }) { {durationFromMsFormatted(session.assistDuration)} {durationFromMsFormatted(session.callDuration)} - {durationFromMsFormatted(session.controlDuration)} - + {durationFromMsFormatted(session.controlDuration)}
{session.recordings?.length > 0 ? ( diff --git a/frontend/app/components/Client/Modules/index.ts b/frontend/app/components/Client/Modules/index.ts index 93a78896c..c5c16be1c 100644 --- a/frontend/app/components/Client/Modules/index.ts +++ b/frontend/app/components/Client/Modules/index.ts @@ -23,7 +23,7 @@ export interface Module { export const modules = [ { - label: 'Cobrowse', + label: 'Co-Browse', description: 'Enable live session replay, remote control, annotations and webRTC call/video.', key: MODULES.ASSIST, icon: 'broadcast' diff --git a/frontend/app/components/Modal/ModalOverlay.tsx b/frontend/app/components/Modal/ModalOverlay.tsx index 0a56646b8..5b2a9edab 100644 --- a/frontend/app/components/Modal/ModalOverlay.tsx +++ b/frontend/app/components/Modal/ModalOverlay.tsx @@ -4,7 +4,7 @@ import cn from 'classnames'; function ModalOverlay({ hideModal, children, left = false, right = false }: any) { return ( -
+
{children}
diff --git a/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx b/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx index 107067b24..22c2cb68f 100644 --- a/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx +++ b/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx @@ -88,7 +88,7 @@ function LiveSessionList(props: Props) {

- Cobrowse + Co-Browse {/* {numberWithCommas(total)} */}

diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index d7754fdce..9d36115ee 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -132,6 +132,7 @@ function SelectDateRange(props: Props) { ) { return false; } + console.log('outside') setIsCustom(false); }} > diff --git a/frontend/app/layout/SideMenu.tsx b/frontend/app/layout/SideMenu.tsx index ecbea406a..e96cdc297 100644 --- a/frontend/app/layout/SideMenu.tsx +++ b/frontend/app/layout/SideMenu.tsx @@ -65,11 +65,10 @@ function SideMenu(props: Props) { if (item.hidden) return item; const isHidden = [ - (item.key === MENU.STATS && modules.includes(MODULES.ASSIST_STATS)), (item.key === MENU.RECOMMENDATIONS && modules.includes(MODULES.RECOMMENDATIONS)), (item.key === MENU.FEATURE_FLAGS && modules.includes(MODULES.FEATURE_FLAGS)), (item.key === MENU.NOTES && modules.includes(MODULES.NOTES)), - (item.key === MENU.LIVE_SESSIONS || item.key === MENU.RECORDINGS || item.key === MENU.STATS) && modules.includes(MODULES.ASSIST), + (item.key === MENU.LIVE_SESSIONS && modules.includes(MODULES.ASSIST)), (item.key === MENU.SESSIONS && modules.includes(MODULES.OFFLINE_RECORDINGS)), (item.key === MENU.ALERTS && modules.includes(MODULES.ALERTS)), (item.isAdmin && !isAdmin), @@ -107,8 +106,6 @@ function SideMenu(props: Props) { [MENU.VAULT]: () => withSiteId(routes.bookmarks(), siteId), [MENU.NOTES]: () => withSiteId(routes.notes(), siteId), [MENU.LIVE_SESSIONS]: () => withSiteId(routes.assist(), siteId), - [MENU.STATS]: () => withSiteId(routes.assistStats(), siteId), - [MENU.RECORDINGS]: () => withSiteId(routes.recordings(), siteId), [MENU.DASHBOARDS]: () => withSiteId(routes.dashboard(), siteId), [MENU.CARDS]: () => withSiteId(routes.metrics(), siteId), [MENU.ALERTS]: () => withSiteId(routes.alerts(), siteId), diff --git a/frontend/app/layout/data.ts b/frontend/app/layout/data.ts index eed5fd5c3..812e0e385 100644 --- a/frontend/app/layout/data.ts +++ b/frontend/app/layout/data.ts @@ -42,8 +42,6 @@ export const enum MENU { BOOKMARKS = 'bookmarks', NOTES = 'notes', LIVE_SESSIONS = 'live-sessions', - RECORDINGS = 'recordings', - STATS = 'assist-stats', DASHBOARDS = 'dashboards', CARDS = 'cards', FUNNELS = 'funnels', @@ -70,12 +68,10 @@ export const categories: Category[] = [ ] }, { - title: 'Assist', + title: '', key: 'assist', items: [ - { label: 'Cobrowse', key: MENU.LIVE_SESSIONS, icon: 'broadcast' }, - { label: 'Recordings', key: MENU.RECORDINGS, icon: 'record-btn', isEnterprise: true }, - { label: 'Reports', key: MENU.STATS, icon: 'file-bar-graph', isEnterprise: true } + { label: 'Co-Browse', key: MENU.LIVE_SESSIONS, icon: 'broadcast' }, ] }, {