Compare commits
4 commits
main
...
revert_upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e8fa7614d | ||
|
|
269c931111 | ||
|
|
27a5c0716b | ||
|
|
cff96eba92 |
10 changed files with 30 additions and 133 deletions
|
|
@ -16,14 +16,12 @@ import { IFRAME } from 'App/constants/storageKeys';
|
|||
import stl from './playerBlockHeader.module.css';
|
||||
import UserCard from './EventsBlock/UserCard';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Switch } from 'antd';
|
||||
|
||||
const SESSIONS_ROUTE = sessionsRoute();
|
||||
|
||||
function PlayerBlockHeader(props: any) {
|
||||
const { t } = useTranslation();
|
||||
const [hideBack, setHideBack] = React.useState(false);
|
||||
const { uiPlayerStore } = useStore();
|
||||
const { player, store } = React.useContext(PlayerContext);
|
||||
const { uxtestingStore, customFieldStore, projectsStore, sessionStore } =
|
||||
useStore();
|
||||
|
|
@ -125,25 +123,9 @@ function PlayerBlockHeader(props: any) {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
{uiPlayerStore.showSearchEventsSwitchButton ? (
|
||||
<div className="px-2 relative flex items-center border-r border-r-gray-lighter">
|
||||
<Switch
|
||||
checked={uiPlayerStore.showOnlySearchEvents}
|
||||
onChange={uiPlayerStore.setShowOnlySearchEvents}
|
||||
style={{
|
||||
background: uiPlayerStore.showOnlySearchEvents
|
||||
? '#f0a930'
|
||||
: 'rgba(0, 0, 0, 0.25)',
|
||||
}}
|
||||
/>
|
||||
<span className="ml-2 whitespace-nowrap">
|
||||
{t('Search Events Only')}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div
|
||||
className="px-2 relative"
|
||||
className="px-2 relative border-l border-l-gray-lighter"
|
||||
style={{ minWidth: activeTab === 'EXPORT' ? '360px' : '270px' }}
|
||||
>
|
||||
<Tabs
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@ const UXTTABS = {
|
|||
|
||||
let playerInst: IPlayerContext['player'] | undefined;
|
||||
|
||||
const isDefaultEventsFilterSearch = (filters: FilterItem[]) => {
|
||||
return filters.length === 1 && filters[0].key === 'location' && filters[0].value[0] === '';
|
||||
}
|
||||
|
||||
function WebPlayer(props: any) {
|
||||
const {
|
||||
notesStore,
|
||||
|
|
@ -42,7 +38,6 @@ function WebPlayer(props: any) {
|
|||
uxtestingStore,
|
||||
uiPlayerStore,
|
||||
integrationsStore,
|
||||
searchStore,
|
||||
} = useStore();
|
||||
const devTools = sessionStore.devTools
|
||||
const session = sessionStore.current;
|
||||
|
|
@ -62,17 +57,6 @@ function WebPlayer(props: any) {
|
|||
const [fullView, setFullView] = useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (searchStore.instance.filters?.length && !isDefaultEventsFilterSearch(searchStore.instance.filters)) {
|
||||
uiPlayerStore.setSearchEventsSwitchButton(true);
|
||||
uiPlayerStore.setShowOnlySearchEvents(true);
|
||||
} else {
|
||||
uiPlayerStore.setSearchEventsSwitchButton(false);
|
||||
uiPlayerStore.setShowOnlySearchEvents(false);
|
||||
}
|
||||
}, [searchStore.instance.filters]);
|
||||
|
||||
React.useEffect(() => {
|
||||
openedAt.current = Date.now();
|
||||
const handleActivation = () => {
|
||||
if (!document.hidden) {
|
||||
setWindowActive(true);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ function EventGroupWrapper(props) {
|
|||
isLastInGroup,
|
||||
isSelected,
|
||||
isCurrent,
|
||||
isSearched,
|
||||
isEditing,
|
||||
showSelection,
|
||||
isFirst,
|
||||
|
|
@ -100,7 +99,7 @@ function EventGroupWrapper(props) {
|
|||
);
|
||||
};
|
||||
|
||||
const shadowColor = isSearched ? '#F0A930' : props.isPrev
|
||||
const shadowColor = props.isPrev
|
||||
? '#A7BFFF'
|
||||
: props.isCurrent
|
||||
? '#394EFF'
|
||||
|
|
@ -128,7 +127,7 @@ function EventGroupWrapper(props) {
|
|||
width: 10,
|
||||
height: 10,
|
||||
transform: 'rotate(45deg) translate(0, -50%)',
|
||||
background: isSearched ? '#F0A930' : '#394EFF',
|
||||
background: '#394EFF',
|
||||
zIndex: 99,
|
||||
borderRadius: '.15rem',
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { mergeEventLists, sortEvents } from 'Types/session';
|
|||
import { TYPES } from 'Types/session/event';
|
||||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { VList, VListHandle } from 'virtua';
|
||||
import { Button } from 'antd';
|
||||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
|
|
@ -47,7 +47,6 @@ function EventsBlock(props: IProps) {
|
|||
const zoomStartTs = uiPlayerStore.timelineZoom.startTs;
|
||||
const zoomEndTs = uiPlayerStore.timelineZoom.endTs;
|
||||
const { store, player } = React.useContext(PlayerContext);
|
||||
const [currentTimeEventIndex, setCurrentTimeEventIndex] = React.useState(0);
|
||||
|
||||
const {
|
||||
time,
|
||||
|
|
@ -95,8 +94,8 @@ function EventsBlock(props: IProps) {
|
|||
? 'time' in e
|
||||
? e.time >= zoomStartTs && e.time <= zoomEndTs
|
||||
: false
|
||||
: true
|
||||
).filter((e: any) => !e.noteId && e.type !== 'TABCHANGE' && uiPlayerStore.showOnlySearchEvents ? e.isHighlighted : true);
|
||||
: true,
|
||||
);
|
||||
}, [
|
||||
filteredLength,
|
||||
notesWithEvtsLength,
|
||||
|
|
@ -104,7 +103,6 @@ function EventsBlock(props: IProps) {
|
|||
zoomEnabled,
|
||||
zoomStartTs,
|
||||
zoomEndTs,
|
||||
uiPlayerStore.showOnlySearchEvents
|
||||
]);
|
||||
const findLastFitting = React.useCallback(
|
||||
(time: number) => {
|
||||
|
|
@ -129,9 +127,7 @@ function EventsBlock(props: IProps) {
|
|||
[usedEvents, time, endTime],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentTimeEventIndex(findLastFitting(time));
|
||||
}, [])
|
||||
const currentTimeEventIndex = findLastFitting(time);
|
||||
|
||||
const write = ({
|
||||
target: { value },
|
||||
|
|
@ -187,7 +183,6 @@ function EventsBlock(props: IProps) {
|
|||
const isTabChange = 'type' in event && event.type === 'TABCHANGE';
|
||||
const isCurrent = index === currentTimeEventIndex;
|
||||
const isPrev = index < currentTimeEventIndex;
|
||||
const isSearched = event.isHighlighted
|
||||
|
||||
return (
|
||||
<EventGroupWrapper
|
||||
|
|
@ -199,7 +194,6 @@ function EventsBlock(props: IProps) {
|
|||
isLastEvent={isLastEvent}
|
||||
isLastInGroup={isLastInGroup}
|
||||
isCurrent={isCurrent}
|
||||
isSearched={isSearched}
|
||||
showSelection={!playing}
|
||||
isNote={isNote}
|
||||
isTabChange={isTabChange}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
MobilePlayerContext,
|
||||
} from 'Components/Session/playerContext';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import stl from './timeline.module.css';
|
||||
import { getTimelinePosition } from './getTimelinePosition';
|
||||
import { useStore } from '@/mstore';
|
||||
|
||||
|
|
@ -15,14 +16,8 @@ function EventsList() {
|
|||
const { tabStates } = store.get();
|
||||
const scale = 100 / endTime;
|
||||
const events = React.useMemo(
|
||||
() => Object.values(tabStates)[0]?.eventList.filter((e) => {
|
||||
if (uiPlayerStore.showOnlySearchEvents) {
|
||||
return e.time && (e as any).isHighlighted
|
||||
} else {
|
||||
return e.time
|
||||
}
|
||||
}) || [],
|
||||
[eventCount, uiPlayerStore.showOnlySearchEvents],
|
||||
() => Object.values(tabStates)[0]?.eventList.filter((e) => e.time) || [],
|
||||
[eventCount],
|
||||
);
|
||||
React.useEffect(() => {
|
||||
const hasDuplicates = events.some(
|
||||
|
|
@ -39,7 +34,7 @@ function EventsList() {
|
|||
<div
|
||||
/* @ts-ignore TODO */
|
||||
key={`${e.key}_${e.time}`}
|
||||
className={`absolute w-[2px] h-[10px] z-[3] pointer-events-none ${e.isHighlighted ? 'bg-[#f0a930]' : 'bg-[#394eff]'}`}
|
||||
className={stl.event}
|
||||
style={{ left: `${getTimelinePosition(e.time, scale)}%` }}
|
||||
/>
|
||||
))}
|
||||
|
|
@ -59,7 +54,7 @@ function MobileEventsList() {
|
|||
<div
|
||||
/* @ts-ignore TODO */
|
||||
key={`${e.key}_${e.time}`}
|
||||
className={`absolute w-[2px] h-[10px] z-[3] pointer-events-none ${e.isHighlighted ? 'bg-[#f0a930]' : 'bg-[#394eff]'}`}
|
||||
className={stl.event}
|
||||
style={{ left: `${getTimelinePosition(e.time, scale)}%` }}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
import FilterItem from '@/mstore/types/filterItem';
|
||||
|
||||
export const checkEventWithFilters = (event: Event, filters: FilterItem[]) => {
|
||||
let result = false;
|
||||
filters.forEach((filter) => {
|
||||
if (filter.key.toUpperCase() === event.type.toUpperCase()) {
|
||||
if (filter.operator) {
|
||||
const operator = operators[filter.operator];
|
||||
if (operator) {
|
||||
result = !!operator(event.label, filter.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return result
|
||||
};
|
||||
|
||||
const operators = {
|
||||
is: (val: string, target: string[]) => target.some((t) => val.includes(t)),
|
||||
isAny: () => true,
|
||||
isNot: (val: string, target: string[]) =>
|
||||
!target.some((t) => val.includes(t)),
|
||||
contains: (val: string, target: string[]) =>
|
||||
target.some((t) => val.includes(t)),
|
||||
notContains: (val: string, target: string[]) =>
|
||||
!target.some((t) => val.includes(t)),
|
||||
startsWith: (val: string, target: string[]) =>
|
||||
target.some((t) => val.startsWith(t)),
|
||||
endsWith: (val: string, target: string[]) =>
|
||||
target.some((t) => val.endsWith(t)),
|
||||
greaterThan: (val: number, target: number) => val > target,
|
||||
greaterOrEqual: (val: number, target: number) => val >= target,
|
||||
lessOrEqual: (val: number, target: number) => val <= target,
|
||||
lessThan: (val: number, target: number) => val < target,
|
||||
on: (val: string, target: string[]) => target.some((t) => val.includes(t)),
|
||||
notOn: (val: string, target: string[]) =>
|
||||
!target.some((t) => val.includes(t)),
|
||||
onAny: () => true,
|
||||
selectorIs: (val: string, target: string[]) => target.some((t) => val.includes(t)),
|
||||
selectorIsAny: () => true,
|
||||
selectorIsNot: (val: string, target: string[]) =>
|
||||
!target.some((t) => val.includes(t)),
|
||||
selectorContains: (val: string, target: string[]) =>
|
||||
target.some((t) => val.includes(t)),
|
||||
selectorNotContains: (val: string, target: string[]) =>
|
||||
!target.some((t) => val.includes(t)),
|
||||
selectorStartsWith: (val: string, target: string[]) =>
|
||||
target.some((t) => val.startsWith(t)),
|
||||
selectorEndsWith: (val: string, target: string[]) =>
|
||||
target.some((t) => val.endsWith(t)),
|
||||
};
|
||||
|
|
@ -49,6 +49,23 @@
|
|||
z-index: 2;
|
||||
}
|
||||
|
||||
.event {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 10px;
|
||||
background: $main;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
/* top: 0; */
|
||||
/* bottom: 0; */
|
||||
/* &:hover {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: -6px;
|
||||
z-index: 1;
|
||||
};*/
|
||||
}
|
||||
|
||||
/* .event.click, .event.input {
|
||||
background: $green;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import { LAST_7_DAYS } from 'Types/app/period';
|
|||
import { filterMap } from 'App/mstore/searchStore';
|
||||
import { getDateRangeFromValue } from 'App/dateRange';
|
||||
import { searchStore, searchStoreLive } from './index';
|
||||
import { checkEventWithFilters } from '@/components/Session_/Player/Controls/checkEventWithFilters';
|
||||
const range = getDateRangeFromValue(LAST_7_DAYS);
|
||||
|
||||
const defaultDateFilters = {
|
||||
|
|
@ -341,14 +340,7 @@ export default class SessionStore {
|
|||
const eventsData: Record<string, any[]> = {};
|
||||
try {
|
||||
const evData = await sessionService.getSessionEvents(sessionId);
|
||||
|
||||
Object.assign(eventsData, {
|
||||
...evData,
|
||||
events: evData.events.map((e) => ({
|
||||
...e,
|
||||
isHighlighted: checkEventWithFilters(e, searchStore.instance.filters)
|
||||
}))
|
||||
});
|
||||
Object.assign(eventsData, evData);
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch events', e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ export const blockValues = [
|
|||
|
||||
export default class UiPlayerStore {
|
||||
fullscreen = false;
|
||||
showOnlySearchEvents = false;
|
||||
showSearchEventsSwitchButton = false;
|
||||
|
||||
bottomBlock = 0;
|
||||
|
||||
|
|
@ -147,12 +145,4 @@ export default class UiPlayerStore {
|
|||
setZoomTab = (tab: 'overview' | 'journey' | 'issues' | 'errors') => {
|
||||
this.zoomTab = tab;
|
||||
};
|
||||
|
||||
setShowOnlySearchEvents = (show: boolean) => {
|
||||
this.showOnlySearchEvents = show;
|
||||
};
|
||||
|
||||
setSearchEventsSwitchButton = (show: boolean) => {
|
||||
this.showSearchEventsSwitchButton = show;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ interface IEvent {
|
|||
path: string;
|
||||
label: string;
|
||||
};
|
||||
isHighlighted?: boolean;
|
||||
}
|
||||
|
||||
interface ConsoleEvent extends IEvent {
|
||||
|
|
@ -119,8 +118,6 @@ class Event {
|
|||
|
||||
messageId: IEvent['messageId'];
|
||||
|
||||
isHighlighted: IEvent['isHighlighted'];
|
||||
|
||||
constructor(event: IEvent) {
|
||||
Object.assign(this, {
|
||||
time: event.time,
|
||||
|
|
@ -128,7 +125,6 @@ class Event {
|
|||
key: event.key,
|
||||
tabId: event.tabId,
|
||||
messageId: event.messageId,
|
||||
isHighlighted: event.isHighlighted,
|
||||
target: {
|
||||
path: event.target?.path || event.targetPath,
|
||||
label: event.target?.label,
|
||||
|
|
@ -190,7 +186,6 @@ export class Click extends Event {
|
|||
this.count = evt.count;
|
||||
this.hesitation = evt.hesitation;
|
||||
this.selector = evt.selector;
|
||||
this.isHighlighted = evt.isHighlighted;
|
||||
if (isClickRage) {
|
||||
this.type = CLICKRAGE;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue