Object.values(tabStates)[0]?.eventList.filter((e) => e.time) || [],
- [eventCount],
+ () => Object.values(tabStates)[0]?.eventList.filter((e) => {
+ if (uiPlayerStore.showOnlySearchEvents) {
+ return e.time && (e as any).isHighlighted
+ } else {
+ return e.time
+ }
+ }) || [],
+ [eventCount, uiPlayerStore.showOnlySearchEvents],
);
-
React.useEffect(() => {
const hasDuplicates = events.some(
(e, i) =>
@@ -33,7 +39,7 @@ function EventsList() {
))}
@@ -53,7 +59,7 @@ function MobileEventsList() {
))}
diff --git a/frontend/app/components/Session_/Player/Controls/checkEventWithFilters.ts b/frontend/app/components/Session_/Player/Controls/checkEventWithFilters.ts
new file mode 100644
index 000000000..fb39264fb
--- /dev/null
+++ b/frontend/app/components/Session_/Player/Controls/checkEventWithFilters.ts
@@ -0,0 +1,51 @@
+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)),
+};
diff --git a/frontend/app/components/Session_/Player/Controls/timeline.module.css b/frontend/app/components/Session_/Player/Controls/timeline.module.css
index 4830dac96..a067d6b8e 100644
--- a/frontend/app/components/Session_/Player/Controls/timeline.module.css
+++ b/frontend/app/components/Session_/Player/Controls/timeline.module.css
@@ -49,24 +49,6 @@
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;
}
diff --git a/frontend/app/mstore/sessionStore.ts b/frontend/app/mstore/sessionStore.ts
index e6c51c8e2..cc754fb6b 100644
--- a/frontend/app/mstore/sessionStore.ts
+++ b/frontend/app/mstore/sessionStore.ts
@@ -15,9 +15,8 @@ import { loadFile } from 'App/player/web/network/loadFiles';
import { LAST_7_DAYS } from 'Types/app/period';
import { filterMap } from 'App/mstore/searchStore';
import { getDateRangeFromValue } from 'App/dateRange';
-import { clean as cleanParams } from '../api_client';
import { searchStore, searchStoreLive } from './index';
-
+import { checkEventWithFilters } from '@/components/Session_/Player/Controls/checkEventWithFilters';
const range = getDateRangeFromValue(LAST_7_DAYS);
const defaultDateFilters = {
@@ -342,7 +341,14 @@ export default class SessionStore {
const eventsData: Record
= {};
try {
const evData = await sessionService.getSessionEvents(sessionId);
- Object.assign(eventsData, evData);
+
+ Object.assign(eventsData, {
+ ...evData,
+ events: evData.events.map((e) => ({
+ ...e,
+ isHighlighted: checkEventWithFilters(e, searchStore.instance.filters)
+ }))
+ });
} catch (e) {
console.error('Failed to fetch events', e);
}
diff --git a/frontend/app/mstore/uiPlayerStore.ts b/frontend/app/mstore/uiPlayerStore.ts
index 3f9466b08..172b85b38 100644
--- a/frontend/app/mstore/uiPlayerStore.ts
+++ b/frontend/app/mstore/uiPlayerStore.ts
@@ -53,6 +53,8 @@ export const blockValues = [
export default class UiPlayerStore {
fullscreen = false;
+ showOnlySearchEvents = false;
+ showSearchEventsSwitchButton = false;
bottomBlock = 0;
@@ -145,4 +147,12 @@ 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;
+ };
}
diff --git a/frontend/app/types/session/event.ts b/frontend/app/types/session/event.ts
index 982d3ca2b..2eeb568c4 100644
--- a/frontend/app/types/session/event.ts
+++ b/frontend/app/types/session/event.ts
@@ -51,6 +51,7 @@ interface IEvent {
path: string;
label: string;
};
+ isHighlighted?: boolean;
}
interface ConsoleEvent extends IEvent {
@@ -118,6 +119,8 @@ class Event {
messageId: IEvent['messageId'];
+ isHighlighted: IEvent['isHighlighted'];
+
constructor(event: IEvent) {
Object.assign(this, {
time: event.time,
@@ -125,6 +128,7 @@ 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,
@@ -178,12 +182,15 @@ export class Click extends Event {
selector: string;
+ isHighlighted: boolean | undefined = false;
+
constructor(evt: ClickEvent, isClickRage?: boolean) {
super(evt);
this.targetContent = evt.targetContent;
this.count = evt.count;
this.hesitation = evt.hesitation;
this.selector = evt.selector;
+ this.isHighlighted = evt.isHighlighted;
if (isClickRage) {
this.type = CLICKRAGE;
}