diff --git a/frontend/app/components/Alerts/Notifications/Notifications.tsx b/frontend/app/components/Alerts/Notifications/Notifications.tsx
index 05bcea06b..2bc78384f 100644
--- a/frontend/app/components/Alerts/Notifications/Notifications.tsx
+++ b/frontend/app/components/Alerts/Notifications/Notifications.tsx
@@ -1,34 +1,27 @@
import React, { useEffect } from 'react';
import stl from './notifications.module.css';
-import { connect } from 'react-redux';
import { Icon, Tooltip } from 'UI';
-import { fetchList, setViewed, clearAll } from 'Duck/notifications';
-import { setLastRead } from 'Duck/announcements';
import { useModal } from 'App/components/Modal';
import AlertTriggersModal from 'Shared/AlertTriggersModal';
import { useStore } from 'App/mstore';
-import { useObserver } from 'mobx-react-lite';
+import { observer } from 'mobx-react-lite';
const AUTOREFRESH_INTERVAL = 5 * 60 * 1000;
-interface Props {
- notifications: any;
- fetchList: any;
-}
-function Notifications(props: Props) {
+function Notifications() {
const { showModal } = useModal();
const { notificationStore } = useStore();
- const count = useObserver(() => notificationStore.notificationsCount);
+ const count = notificationStore.notificationsCount;
useEffect(() => {
const interval = setInterval(() => {
- notificationStore.fetchNotificationsCount();
+ void notificationStore.fetchNotificationsCount();
}, AUTOREFRESH_INTERVAL);
return () => clearInterval(interval);
}, []);
- return useObserver(() => (
+ return (
- ));
+ );
}
-export default connect(
- (state: any) => ({
- notifications: state.getIn(['notifications', 'list']),
- }),
- { fetchList, setLastRead, setViewed, clearAll }
-)(Notifications);
+export default observer(Notifications)
\ No newline at end of file
diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx
index b804ca439..71820c502 100644
--- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx
+++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx
@@ -9,7 +9,6 @@ import {
init,
edit,
remove,
- setAlertMetricId,
setActiveWidget,
updateActiveState,
} from 'Duck/customMetrics';
@@ -181,7 +180,6 @@ export default connect(
{
remove,
setShowAlerts,
- setAlertMetricId,
edit,
setActiveWidget,
updateActiveState,
diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx
index ccb269cbd..bcfd27406 100644
--- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx
+++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx
@@ -1,14 +1,5 @@
-import React, { useEffect, useState } from 'react';
+import React, { useState } from 'react';
import FilterList from 'Shared/Filters/FilterList';
-import {
- edit,
- updateSeries,
- addSeriesFilterFilter,
- removeSeriesFilterFilter,
- editSeriesFilterFilter,
- editSeriesFilter,
-} from 'Duck/customMetrics';
-import { connect } from 'react-redux';
import { Button, Icon } from 'UI';
import FilterSelection from 'Shared/Filters/FilterSelection';
import SeriesName from './SeriesName';
@@ -18,21 +9,21 @@ import { observer } from 'mobx-react-lite';
interface Props {
seriesIndex: number;
series: any;
- edit: typeof edit;
- updateSeries: typeof updateSeries;
onRemoveSeries: (seriesIndex: any) => void;
- canDelete?: boolean;
- addSeriesFilterFilter: typeof addSeriesFilterFilter;
- editSeriesFilterFilter: typeof editSeriesFilterFilter;
- editSeriesFilter: typeof editSeriesFilter;
- removeSeriesFilterFilter: typeof removeSeriesFilterFilter;
+ canDelete?: boolean;
hideHeader?: boolean;
emptyMessage?: any;
observeChanges?: () => void;
}
function FilterSeries(props: Props) {
- const { observeChanges = () => {}, canDelete, hideHeader = false, emptyMessage = 'Add user event or filter to define the series by clicking Add Step.' } = props;
+ const {
+ observeChanges = () => {
+ },
+ canDelete,
+ hideHeader = false,
+ emptyMessage = 'Add user event or filter to define the series by clicking Add Step.'
+ } = props;
const [expanded, setExpanded] = useState(true)
const { series, seriesIndex } = props;
@@ -46,7 +37,7 @@ function FilterSeries(props: Props) {
observeChanges()
}
- const onChangeEventsOrder = (e, { name, value }: any) => {
+ const onChangeEventsOrder = (e: any, { name, value }: any) => {
series.filter.updateKey(name, value)
observeChanges()
}
@@ -60,11 +51,11 @@ function FilterSeries(props: Props) {
- series.update('name', name) } />
+ series.update('name', name)} />
-
+
-
+
@@ -73,17 +64,17 @@ function FilterSeries(props: Props) {
- { expanded && (
+ {expanded && (
<>
- { series.filter.filters.length > 0 ? (
+ {series.filter.filters.length > 0 ? (
- ): (
+ ) : (
{emptyMessage}
)}
@@ -103,11 +94,4 @@ function FilterSeries(props: Props) {
);
}
-export default connect(null, {
- edit,
- updateSeries,
- addSeriesFilterFilter,
- editSeriesFilterFilter,
- editSeriesFilter,
- removeSeriesFilterFilter,
-})(observer(FilterSeries));
\ No newline at end of file
+export default observer(FilterSeries);
\ No newline at end of file
diff --git a/frontend/app/components/Session/RightBlock.tsx b/frontend/app/components/Session/RightBlock.tsx
index 66f92a93c..9e4302648 100644
--- a/frontend/app/components/Session/RightBlock.tsx
+++ b/frontend/app/components/Session/RightBlock.tsx
@@ -1,33 +1,30 @@
import React from 'react'
import EventsBlock from '../Session_/EventsBlock';
import PageInsightsPanel from '../Session_/PageInsightsPanel/PageInsightsPanel'
-import { PlayerContext } from 'App/components/Session/playerContext';
-import { observer } from 'mobx-react-lite';
import cn from 'classnames';
import stl from './rightblock.module.css';
function RightBlock(props: any) {
const { activeTab } = props;
- const { player, store } = React.useContext(PlayerContext)
- const { eventListNow, playing } = store.get()
- const currentTimeEventIndex = eventListNow.length > 0 ? eventListNow.length - 1 : 0
-
- const EventsBlockConnected = () =>
- const renderActiveTab = (tab: string) => {
- switch(tab) {
- case props.tabs.EVENTS:
- return
- case props.tabs.HEATMAPS:
- return
- }
+ if (activeTab === props.tabs.EVENTS) {
+ return (
+
+
+
+ )
}
- return (
-
- {renderActiveTab(activeTab)}
-
- )
+ if (activeTab === props.tabs.HEATMAPS) {
+ return (
+
+ )
+ }
+ return null
}
-export default observer(RightBlock)
+export default RightBlock
diff --git a/frontend/app/components/Session_/EventsBlock/Event.js b/frontend/app/components/Session_/EventsBlock/Event.js
index bfae9fe5d..e8f985aa0 100644
--- a/frontend/app/components/Session_/EventsBlock/Event.js
+++ b/frontend/app/components/Session_/EventsBlock/Event.js
@@ -147,14 +147,6 @@ export default class Event extends React.PureComponent {
}
- {/*
-
-
*/}
{ this.renderBody() }
diff --git a/frontend/app/components/Session_/EventsBlock/EventSearch/EventSearch.js b/frontend/app/components/Session_/EventsBlock/EventSearch/EventSearch.js
index 3c3396e72..965e9726d 100644
--- a/frontend/app/components/Session_/EventsBlock/EventSearch/EventSearch.js
+++ b/frontend/app/components/Session_/EventsBlock/EventSearch/EventSearch.js
@@ -5,16 +5,10 @@ import { PlayerContext } from 'App/components/Session/playerContext';
function EventSearch(props) {
const { player } = React.useContext(PlayerContext)
- const { onChange, clearSearch, value, header, setActiveTab } = props;
+ const { onChange, value, header, setActiveTab } = props;
const toggleEvents = () => player.toggleEvents()
- useEffect(() => {
- return () => {
- clearSearch()
- }
- }, [])
-
return (
diff --git a/frontend/app/components/Session_/EventsBlock/EventsBlock.js b/frontend/app/components/Session_/EventsBlock/EventsBlock.js
deleted file mode 100644
index b3d978347..000000000
--- a/frontend/app/components/Session_/EventsBlock/EventsBlock.js
+++ /dev/null
@@ -1,249 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import cn from 'classnames';
-import { Icon } from 'UI';
-import { List, AutoSizer, CellMeasurer, CellMeasurerCache } from "react-virtualized";
-import { TYPES } from 'Types/session/event';
-import { setSelected } from 'Duck/events';
-import { setEventFilter, filterOutNote } from 'Duck/sessions';
-import { show as showTargetDefiner } from 'Duck/components/targetDefiner';
-import EventGroupWrapper from './EventGroupWrapper';
-import styles from './eventsBlock.module.css';
-import EventSearch from './EventSearch/EventSearch';
-
-@connect(state => ({
- session: state.getIn([ 'sessions', 'current' ]),
- filteredEvents: state.getIn([ 'sessions', 'filteredEvents' ]),
- eventsIndex: state.getIn([ 'sessions', 'eventsIndex' ]),
- selectedEvents: state.getIn([ 'events', 'selected' ]),
- targetDefinerDisplayed: state.getIn([ 'components', 'targetDefiner', 'isDisplayed' ]),
- testsAvaliable: false,
-}), {
- showTargetDefiner,
- setSelected,
- setEventFilter,
- filterOutNote
-})
-export default class EventsBlock extends React.Component {
- state = {
- editingEvent: null,
- mouseOver: false,
- query: ''
- }
-
- scroller = React.createRef();
- cache = new CellMeasurerCache({
- fixedWidth: true,
- defaultHeight: 300
- });
-
- write = ({ target: { value, name } }) => {
- const { filter } = this.state;
- this.setState({ query: value })
- this.props.setEventFilter({ query: value, filter })
-
- setTimeout(() => {
- if (!this.scroller.current) return;
-
- this.scroller.current.scrollToRow(0);
- }, 100)
- }
-
- clearSearch = () => {
- const { filter } = this.state;
- this.setState({ query: '' })
- this.props.setEventFilter({ query: '', filter })
- if (this.scroller.current) {
- this.scroller.current.forceUpdateGrid();
- }
-
- setTimeout(() => {
- if (!this.scroller.current) return;
-
- this.scroller.current.scrollToRow(0);
- }, 100)
- }
-
- onSetEventFilter = (e, { name, value }) => {
- const { query } = this.state;
- this.setState({ filter: value })
- this.props.setEventFilter({ filter: value, query });
- }
-
- componentDidUpdate(prevProps) {
- if (prevProps.targetDefinerDisplayed && !this.props.targetDefinerDisplayed) {
- this.setState({ editingEvent: null });
- }
- if (prevProps.session !== this.props.session) { // Doesn't happen
- this.cache = new CellMeasurerCache({
- fixedWidth: true,
- defaultHeight: 300
- });
- }
- if (prevProps.currentTimeEventIndex !== this.props.currentTimeEventIndex &&
- this.scroller.current !== null) {
- this.scroller.current.forceUpdateGrid();
- if (!this.state.mouseOver) {
- this.scroller.current.scrollToRow(this.props.currentTimeEventIndex);
- }
- }
- }
-
- onCheckboxClick(e, event) {
- e.stopPropagation();
- const {
- session: { events },
- selectedEvents,
- } = this.props;
-
- this.props.player.pause();
-
- let newSelectedSet;
- const wasSelected = selectedEvents.contains(event);
- if (wasSelected) {
- newSelectedSet = selectedEvents.remove(event);
- } else {
- newSelectedSet = selectedEvents.add(event);
- }
-
- let selectNextLoad = false;
- events.reverse().forEach((sessEvent) => {
- if (sessEvent.type === TYPES.LOCATION) {
- if (selectNextLoad) {
- newSelectedSet = newSelectedSet.add(sessEvent);
- }
- selectNextLoad = false;
- } else if (newSelectedSet.contains(sessEvent)) {
- selectNextLoad = true;
- }
- });
- this.props.setSelected(newSelectedSet);
- }
-
- onEventClick = (e, event) => this.props.player.jump(event.time)
-
- onMouseOver = () => this.setState({ mouseOver: true })
- onMouseLeave = () => this.setState({ mouseOver: false })
-
- get eventsList() {
- const { session: { notesWithEvents }, filteredEvents } = this.props
- const usedEvents = filteredEvents || notesWithEvents
-
- return usedEvents
- }
-
- renderGroup = ({ index, key, style, parent }) => {
- const {
- selectedEvents,
- currentTimeEventIndex,
- testsAvaliable,
- playing,
- eventsIndex,
- filterOutNote,
- } = this.props;
-
- const { query } = this.state;
- const _events = this.eventsList
- const isLastEvent = index === _events.size - 1;
- const isLastInGroup = isLastEvent || _events.get(index + 1).type === TYPES.LOCATION;
- const event = _events.get(index);
- const isNote = !!event.noteId
- const isSelected = selectedEvents.includes(event);
- const isCurrent = index === currentTimeEventIndex;
- const isEditing = this.state.editingEvent === event;
-
- const heightBug = index === 0 && event.type === TYPES.LOCATION && event.referrer ? { top: 2 } : {}
- return (
-
- {({measure, registerChild}) => (
-
-
-
- )}
-
- );
- }
-
- render() {
- const { query } = this.state;
- const {
- session: {
- events,
- },
- setActiveTab,
- } = this.props;
-
- const _events = this.eventsList
-
- const isEmptySearch = query && (_events.size === 0 || !_events)
- return (
- <>
-
-
- User Steps { events.size }
- }
- />
-
-
-
- {isEmptySearch && (
-
-
- No Matching Results
-
- )}
-
- {({ height }) => (
-
- )}
-
-
- >
- );
- }
-}
diff --git a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx
new file mode 100644
index 000000000..0f0405cd5
--- /dev/null
+++ b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx
@@ -0,0 +1,187 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import cn from 'classnames';
+import { Icon } from 'UI';
+import { List, AutoSizer, CellMeasurer } from "react-virtualized";
+import { TYPES } from 'Types/session/event';
+import { setEventFilter, filterOutNote } from 'Duck/sessions';
+import { show as showTargetDefiner } from 'Duck/components/targetDefiner';
+import EventGroupWrapper from './EventGroupWrapper';
+import styles from './eventsBlock.module.css';
+import EventSearch from './EventSearch/EventSearch';
+import { PlayerContext } from 'App/components/Session/playerContext';
+import { observer } from 'mobx-react-lite';
+import { RootStore } from 'App/duck'
+import { List as ImmList } from 'immutable'
+import useCellMeasurerCache from 'Components/shared/DevTools/useCellMeasurerCache'
+
+interface IProps {
+ setEventFilter: (filter: { query: string }) => void
+ filteredEvents: ImmList
>
+ setActiveTab: (tab?: string) => void
+ query: string
+ session: Record
+ filterOutNote: (id: string) => void
+ eventsIndex: number[]
+}
+
+function EventsBlock(props: IProps) {
+ const [mouseOver, setMouseOver] = React.useState(true)
+ const scroller = React.useRef(null)
+ const cache = useCellMeasurerCache(undefined, {
+ fixedWidth: true,
+ defaultHeight: 300
+ });
+
+ const { store, player } = React.useContext(PlayerContext)
+
+ const { eventListNow, playing } = store.get()
+
+ const { session: { events, notesWithEvents }, filteredEvents,
+ eventsIndex,
+ filterOutNote,
+ query,
+ setActiveTab,
+ } = props
+ const currentTimeEventIndex = eventListNow.length > 0 ? eventListNow.length - 1 : 0
+ const usedEvents = filteredEvents || notesWithEvents
+
+ const write = ({ target: { value } }: React.ChangeEvent) => {
+ props.setEventFilter({ query: value })
+
+ setTimeout(() => {
+ if (!scroller.current) return;
+
+ scroller.current.scrollToRow(0);
+ }, 100)
+ }
+
+ const clearSearch = () => {
+ props.setEventFilter({ query: '' })
+ if (scroller.current) {
+ scroller.current.forceUpdateGrid();
+ }
+
+ setTimeout(() => {
+ if (!scroller.current) return;
+
+ scroller.current.scrollToRow(0);
+ }, 100)
+ }
+
+ React.useEffect(() => {
+ return () => {
+ clearSearch()
+ }
+ }, [])
+ React.useEffect(() => {
+ if (scroller.current) {
+ scroller.current.forceUpdateGrid();
+ if (!mouseOver) {
+ scroller.current.scrollToRow(currentTimeEventIndex);
+ }
+ }
+ }, [currentTimeEventIndex])
+
+ const onEventClick = (_: React.MouseEvent, event: any) => player.jump(event.time)
+ const onMouseOver = () => setMouseOver(true)
+ const onMouseLeave = () => setMouseOver(false)
+
+ const renderGroup = ({ index, key, style, parent }: { index: number; key: string; style: any; parent: any }) => {
+ const isLastEvent = index === usedEvents.size - 1;
+ const isLastInGroup = isLastEvent || usedEvents.get(index + 1)?.type === TYPES.LOCATION;
+ const event = usedEvents.get(index);
+ const isNote = !!event?.noteId
+ const isCurrent = index === currentTimeEventIndex;
+
+ const heightBug = index === 0 && event?.type === TYPES.LOCATION && event.referrer ? { top: 2 } : {}
+ return (
+
+ {({measure, registerChild}) => (
+
+
+
+ )}
+
+ );
+ }
+
+ const isEmptySearch = query && (usedEvents.size === 0 || !usedEvents)
+ return (
+ <>
+
+
+ User Steps { events.size }
+ }
+ />
+
+
+
+ {isEmptySearch && (
+
+
+ No Matching Results
+
+ )}
+
+ {({ height }) => (
+
+ )}
+
+
+ >
+ );
+}
+
+export default connect((state: RootStore) => ({
+ session: state.getIn([ 'sessions', 'current' ]),
+ filteredEvents: state.getIn([ 'sessions', 'filteredEvents' ]),
+ query: state.getIn(['sessions', 'eventsQuery']),
+ eventsIndex: state.getIn([ 'sessions', 'eventsIndex' ]),
+ targetDefinerDisplayed: state.getIn([ 'components', 'targetDefiner', 'isDisplayed' ]),
+}), {
+ showTargetDefiner,
+ setEventFilter,
+ filterOutNote
+})(observer(EventsBlock))
diff --git a/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx b/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx
index e1ba5ccba..b43f70ed9 100644
--- a/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx
+++ b/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx
@@ -13,7 +13,6 @@ const JUMP_OFFSET = 1000;
interface Props {
filters: any;
fetchInsights: (filters: Record
) => void;
- urls: [];
insights: any;
events: Array;
urlOptions: Array;
diff --git a/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx b/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx
deleted file mode 100644
index 8f8aca480..000000000
--- a/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import React, { useState } from 'react';
-import FilterList from 'Shared/Filters/FilterList';
-import {
- edit,
- updateSeries,
- addSeriesFilterFilter,
- removeSeriesFilterFilter,
- editSeriesFilterFilter,
- editSeriesFilter,
-} from 'Duck/customMetrics';
-import { connect } from 'react-redux';
-import { IconButton, Icon } from 'UI';
-import FilterSelection from '../../Filters/FilterSelection';
-import SeriesName from './SeriesName';
-import cn from 'classnames';
-
-interface Props {
- seriesIndex: number;
- series: any;
- edit: typeof edit;
- updateSeries: typeof updateSeries;
- onRemoveSeries: (seriesIndex) => void;
- canDelete?: boolean;
- addSeriesFilterFilter: typeof addSeriesFilterFilter;
- editSeriesFilterFilter: typeof editSeriesFilterFilter;
- editSeriesFilter: typeof editSeriesFilter;
- removeSeriesFilterFilter: typeof removeSeriesFilterFilter;
- hideHeader?: boolean;
- emptyMessage?: any;
-}
-
-function FilterSeries(props: Props) {
- const { canDelete, hideHeader = false, emptyMessage = 'Add user event or filter to define the series by clicking Add Step.' } = props;
- const [expanded, setExpanded] = useState(true)
- const { series, seriesIndex } = props;
-
- const onAddFilter = (filter) => {
- filter.value = [""]
- if (filter.hasOwnProperty('filters') && Array.isArray(filter.filters)) {
- filter.filters = filter.filters.map(i => ({ ...i, value: [""] }))
- }
- props.addSeriesFilterFilter(seriesIndex, filter);
- }
-
- const onUpdateFilter = (filterIndex, filter) => {
- props.editSeriesFilterFilter(seriesIndex, filterIndex, filter);
- }
-
- const onChangeEventsOrder = (e, { name, value }) => {
- props.editSeriesFilter(seriesIndex, { eventsOrder: value });
- }
-
- const onRemoveFilter = (filterIndex) => {
- props.removeSeriesFilterFilter(seriesIndex, filterIndex);
- }
-
- return (
-
-
-
- props.updateSeries(seriesIndex, { name }) } />
-
-
-
-
-
-
-
-
setExpanded(!expanded)} className="ml-3">
-
-
-
-
-
- { expanded && (
- <>
-
- { series.filter.filters.size > 0 ? (
-
- ): (
-
{emptyMessage}
- )}
-
-
- >
- )}
-
- );
-}
-
-export default connect(null, {
- edit,
- updateSeries,
- addSeriesFilterFilter,
- editSeriesFilterFilter,
- editSeriesFilter,
- removeSeriesFilterFilter,
-})(FilterSeries);
\ No newline at end of file
diff --git a/frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/SeriesName.tsx b/frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/SeriesName.tsx
deleted file mode 100644
index d6a69c73d..000000000
--- a/frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/SeriesName.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React, { useState, useRef, useEffect } from 'react';
-import { Icon } from 'UI';
-
-interface Props {
- name: string;
- onUpdate: (name) => void;
- seriesIndex?: number;
-}
-function SeriesName(props: Props) {
- const { seriesIndex = 1 } = props;
- const [editing, setEditing] = useState(false)
- const [name, setName] = useState(props.name)
- const ref = useRef(null)
-
- const write = ({ target: { value, name } }) => {
- setName(value)
- }
-
- const onBlur = () => {
- setEditing(false)
- props.onUpdate(name)
- }
-
- useEffect(() => {
- if (editing) {
- ref.current.focus()
- }
- }, [editing])
-
- useEffect(() => {
- setName(props.name)
- }, [props.name])
-
- // const { name } = props;
- return (
-
- { editing ? (
-
setEditing(true)}
- />
- ) : (
-
{name && name.trim() === '' ? 'Series ' + (seriesIndex + 1) : name }
- )}
-
-
setEditing(true)}>
-
- );
-}
-
-export default SeriesName;
\ No newline at end of file
diff --git a/frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/index.ts b/frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/index.ts
deleted file mode 100644
index 90e63cdb6..000000000
--- a/frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './SeriesName';
\ No newline at end of file
diff --git a/frontend/app/components/shared/CustomMetrics/FilterSeries/index.ts b/frontend/app/components/shared/CustomMetrics/FilterSeries/index.ts
deleted file mode 100644
index 5882e382a..000000000
--- a/frontend/app/components/shared/CustomMetrics/FilterSeries/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FilterSeries'
\ No newline at end of file
diff --git a/frontend/app/components/shared/DevTools/useCellMeasurerCache.ts b/frontend/app/components/shared/DevTools/useCellMeasurerCache.ts
index 2c94f7856..692f2629f 100644
--- a/frontend/app/components/shared/DevTools/useCellMeasurerCache.ts
+++ b/frontend/app/components/shared/DevTools/useCellMeasurerCache.ts
@@ -1,12 +1,12 @@
import { useMemo } from 'react'
-import { CellMeasurerCache } from 'react-virtualized';
+import { CellMeasurerCache, CellMeasurerCacheParams } from 'react-virtualized';
import useLatestRef from 'App/hooks/useLatestRef'
-
-export default function useCellMeasurerCache(itemList: any[]) {
- const filteredListRef = useLatestRef(itemList)
+export default function useCellMeasurerCache(itemList?: any[], options?: CellMeasurerCacheParams) {
+ const filteredListRef = itemList ? useLatestRef(itemList) : undefined
return useMemo(() => new CellMeasurerCache({
fixedWidth: true,
- keyMapper: (index) => filteredListRef.current[index],
+ keyMapper: filteredListRef ? (index) => filteredListRef.current[index] : undefined,
+ ...options
}), [])
}
\ No newline at end of file
diff --git a/frontend/app/duck/ReducerModule.js.dev b/frontend/app/duck/ReducerModule.js.dev
deleted file mode 100644
index c80c65a37..000000000
--- a/frontend/app/duck/ReducerModule.js.dev
+++ /dev/null
@@ -1,55 +0,0 @@
-
-redux -> other storage ::<< Entities + Lists + relations <|> methods:: crud. request declaration -> request realisation with middleware -< (uses) MODEL
-
-
-
-!request declaration
-
-
-
-action/request formatter => ReducerModule Fabrique =>
-
-
-class ReducerModule {
- _ns = "common"
- _switch = {}
- _n = 0
-
- constructor(namespace) {
- this._ns = namespace
- }
-
- /**
- Action: state => newState | { reduce: state, action => newState, creator: () => {objects to action} }
- */
- actions(actns): this {
- Object.keys(actns).map(key => {
- const type = `${this._namespace}/${key.toUpperCase()}`;
- this._switch[ type ] = actns[ key ];
- });
- return this;
- }
-
- requests(reqsts): this {
- Object.keys(reqsts).map(key => {
- const type = `${this._namespace}/${key.toUpperCase()}`;
- this._switch[ type ] = actns[ key ];
- });
- return this;
- }
-
- get actionTypes() {
-
- }
-
- get actionCreators() {
-
- }
-
- get reducer() {
- return (state, action = {}) => {
- const reduce = this._switch[ action.type ];
- return reduce ? reduce(state, action) : state;
- }
- }
-}
\ No newline at end of file
diff --git a/frontend/app/duck/customMetrics.js b/frontend/app/duck/customMetrics.js
index e6713acb4..82ce78277 100644
--- a/frontend/app/duck/customMetrics.js
+++ b/frontend/app/duck/customMetrics.js
@@ -1,8 +1,8 @@
import { List, Map } from 'immutable';
import CustomMetric, { FilterSeries } from 'Types/customMetric'
-import { createFetch, fetchListType, fetchType, saveType, removeType, editType, createRemove, createEdit } from './funcTools/crud';
+import { fetchListType, fetchType, saveType, removeType, editType, createRemove, createEdit } from './funcTools/crud';
import { createRequestReducer, ROOT_KEY } from './funcTools/request';
-import { array, request, success, failure, createListUpdater, mergeReducers } from './funcTools/tools';
+import { array, success, createListUpdater, mergeReducers } from './funcTools/tools';
import Filter from 'Types/filter';
import Session from 'Types/session';
@@ -28,11 +28,6 @@ const INIT = `${name}/INIT`;
const SET_ACTIVE_WIDGET = `${name}/SET_ACTIVE_WIDGET`;
const REMOVE = removeType(name);
const UPDATE_SERIES = `${name}/UPDATE_SERIES`;
-const SET_ALERT_METRIC_ID = `${name}/SET_ALERT_METRIC_ID`;
-
-function chartWrapper(chart = []) {
- return chart.map(point => ({ ...point, count: Math.max(point.count, 0) }));
-}
const updateItemInList = createListUpdater(idKey);
const updateInstance = (state, instance) => state.getIn([ "instance", idKey ]) === instance[ idKey ]
@@ -117,12 +112,6 @@ export default mergeReducers(
export const edit = createEdit(name);
export const remove = createRemove(name);
-export const updateSeries = (index, series) => ({
- type: UPDATE_SERIES,
- index,
- series,
-});
-
export function fetch(id) {
return {
id,
@@ -147,34 +136,6 @@ export function fetchList() {
};
}
-export function setAlertMetricId(id) {
- return {
- type: SET_ALERT_METRIC_ID,
- id,
- };
-}
-
-export const addSeries = (series = null) => (dispatch, getState) => {
- const instance = getState().getIn([ 'customMetrics', 'instance' ]);
- const seriesIndex = instance.series.size;
- const newSeries = series || {
- name: `Series ${seriesIndex + 1}`,
- filter: new Filter({ filters: [], eventsOrder: 'then' }),
- };
-
- dispatch({
- type: ADD_SERIES,
- series: newSeries,
- });
-}
-
-export const removeSeries = (index) => (dispatch, getState) => {
- dispatch({
- type: REMOVE_SERIES,
- index,
- });
-}
-
export const init = (instance = null, forceNull = false) => (dispatch, getState) => {
dispatch({
type: INIT,
diff --git a/frontend/app/duck/environments.js b/frontend/app/duck/environments.js
deleted file mode 100644
index 8356c4281..000000000
--- a/frontend/app/duck/environments.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import Environment from 'Types/environment';
-import crudDuckGenerator from './tools/crudDuck';
-
-const crudDuck = crudDuckGenerator('environment', Environment);
-export const { fetchList, fetch, init, edit, save, remove } = crudDuck.actions;
-
-export default crudDuck.reducer;
diff --git a/frontend/app/duck/events.js b/frontend/app/duck/events.js
deleted file mode 100644
index 000bd24b7..000000000
--- a/frontend/app/duck/events.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import { List, Map, Set } from 'immutable';
-import withRequestState, { RequestTypes } from 'Duck/requestStateCreator';
-import Event from 'Types/filter/event';
-import CustomFilter from 'Types/filter/customFilter';
-import { KEYS } from 'Types/filter/customFilter';
-import logger from 'App/logger';
-import { countries } from 'App/constants';
-import { getRE } from 'App/utils';
-
-const FETCH_LIST = new RequestTypes('events/FETCH_LIST');
-const TOGGLE_SELECT = 'events/TOGGLE_SELECT';
-const SET_SELECTED = 'events/SET_SELECTED';
-
-const countryOptions = Object.keys(countries).map(c => ({filterKey: KEYS.USER_COUNTRY, label: KEYS.USER_COUNTRY, type: KEYS.USER_COUNTRY, value: c, actualValue: countries[c], isFilter: true }));
-
-const initialState = Map({
- list: List(),
- store: Set(),
-
- // replace?
- selected: Set(),
-});
-
-const filterKeys = ['METADATA', KEYS.USERID, KEYS.USER_COUNTRY, KEYS.USER_BROWSER, KEYS.USER_OS, KEYS.USER_DEVICE, KEYS.REFERRER]
-
-const reducer = (state = initialState, action = {}) => {
- switch (action.type) {
- case FETCH_LIST.SUCCESS: {
- const regCountry = getRE(action.params.q, 'i');
- const countryOptionsFiltered = List(countryOptions).filter(({ actualValue }) => regCountry.test(actualValue)).take(5);
-
- const eventList = List(action.data).concat(countryOptionsFiltered).map(item => (
- filterKeys.includes(item.type) ?
- CustomFilter({...item, isFilter: true }) :
- Event({...item, key: item.type, filterKey: item.type, label: item.type}) )
- );
-
- return state
- .set('list', eventList)
- .update('store', store => store.concat(eventList));
- }
- // TODO: use ids. or make a set-hoc?
- case TOGGLE_SELECT: {
- const { event, flag } = action;
- const shouldBeInSet = typeof flag === 'boolean'
- ? flag
- : !state.get('selected').contains(event);
- return state.update('selected', set => (shouldBeInSet
- ? set.add(event)
- : set.remove(event)));
- }
- case SET_SELECTED:
- return state.set('selected', Set(action.events));
- }
- return state;
-};
-
-export default withRequestState(FETCH_LIST, reducer);
-
-export function fetchList(params) {
- return {
- types: FETCH_LIST.toArray(),
- call: client => client.get('/events/search', params),
- params,
- };
-}
-
-export function toggleSelect(event, flag) {
- return {
- type: TOGGLE_SELECT,
- event,
- flag,
- };
-}
-
-export function setSelected(events) {
- return {
- type: SET_SELECTED,
- events,
- };
-}
diff --git a/frontend/app/duck/index.ts b/frontend/app/duck/index.ts
index fd4b0a655..d33de09a0 100644
--- a/frontend/app/duck/index.ts
+++ b/frontend/app/duck/index.ts
@@ -1,3 +1,4 @@
+// @ts-ignore
import { combineReducers } from 'redux-immutable';
import jwt from './jwt';
@@ -8,12 +9,8 @@ import target from './target';
import targetCustom from './targetCustom';
import filters from './filters';
import funnelFilters from './funnelFilters';
-import events from './events';
-import environments from './environments';
-import variables from './variables';
import templates from './templates';
import alerts from './alerts';
-import notifications from './notifications';
import dashboard from './dashboard';
import components from './components';
import sources from './sources';
@@ -43,12 +40,8 @@ const rootReducer = combineReducers({
filters,
funnelFilters,
- events,
- environments,
- variables,
templates,
alerts,
- notifications,
dashboard,
components,
members,
diff --git a/frontend/app/duck/notifications.js b/frontend/app/duck/notifications.js
deleted file mode 100644
index 129349792..000000000
--- a/frontend/app/duck/notifications.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { List, Map } from 'immutable';
-import Notification from 'Types/notification';
-import { mergeReducers, success, array, request, createListUpdater } from './funcTools/tools';
-import { createRequestReducer } from './funcTools/request';
-import {
- createCRUDReducer,
- getCRUDRequestTypes,
- createFetchList,
-} from './funcTools/crud';
-
-const name = 'notification';
-const idKey = 'notificationId';
-const SET_VIEWED = 'notifications/SET_VIEWED';
-const CLEAR_ALL = 'notifications/CLEAR_ALL';
-const SET_VIEWED_SUCCESS = success(SET_VIEWED);
-const CLEAR_ALL_SUCCESS = success(CLEAR_ALL);
-
-const listUpdater = createListUpdater(idKey);
-
-const initialState = Map({
- list: List(),
-});
-
-const reducer = (state = initialState, action = {}) => {
- switch (action.type) {
- case SET_VIEWED_SUCCESS:
- if (!action.data) return state;
- const item = state.get('list').find(item => item[ idKey ] === action.id)
- return listUpdater(state, Notification({...item.toJS(), createdAt: item.createdAt.ts, viewed: true }));
- case CLEAR_ALL_SUCCESS:
- if (!action.data) return state;
- return state.update('list', list => list.map(l => Notification({...l.toJS(), createdAt: l.createdAt.ts, viewed: true })))
- }
- return state;
-};
-
-export const fetchList = createFetchList(name);
-
-export default mergeReducers(
- reducer,
- createCRUDReducer(name, Notification, idKey),
- createRequestReducer({
- setViewed: SET_VIEWED,
- clearAll: CLEAR_ALL,
- ...getCRUDRequestTypes(name),
- }),
-);
-
-export function setViewed(id) {
- return {
- types: array(SET_VIEWED),
- call: client => client.get(`/notifications/${ id }/view`),
- id,
- };
-}
-
-export function clearAll(params) {
- return {
- types: array(CLEAR_ALL),
- call: client => client.post('/notifications/view', params),
- };
-}
-
diff --git a/frontend/app/duck/sessions.js b/frontend/app/duck/sessions.js
index 8afb6d073..b78d8fad4 100644
--- a/frontend/app/duck/sessions.js
+++ b/frontend/app/duck/sessions.js
@@ -60,6 +60,7 @@ const initialState = Map({
eventsIndex: [],
sourcemapUploaded: true,
filteredEvents: null,
+ eventsQuery: '',
showChatWindow: false,
liveSessions: List(),
visitedEvents: List(),
@@ -110,14 +111,17 @@ const reducer = (state = initialState, action = {}) => {
case SET_EVENT_QUERY: {
const events = state.get('current').events;
const query = action.filter.query;
- // const filter = action.filter.filter;
const searchRe = getRE(query, 'i');
- let filteredEvents = query ? events.filter((e) => searchRe.test(e.url) || searchRe.test(e.value) || searchRe.test(e.label)) : null;
- // if (filter) {
- // filteredEvents = filteredEvents ? filteredEvents.filter(e => e.type === filter) : events.filter(e => e.type === filter);
- // }
- return state.set('filteredEvents', filteredEvents);
+ const filteredEvents = query ? events.filter(
+ (e) => searchRe.test(e.url)
+ || searchRe.test(e.value)
+ || searchRe.test(e.label)
+ || searchRe.test(e.type)
+ || (e.type === 'LOCATION' && searchRe.test('visited'))
+ ) : null;
+
+ return state.set('filteredEvents', filteredEvents).set('eventsQuery', query);
}
case FETCH.SUCCESS: {
// TODO: more common.. or TEMP
diff --git a/frontend/app/duck/user.js b/frontend/app/duck/user.js
index 5b39d34db..f97283290 100644
--- a/frontend/app/duck/user.js
+++ b/frontend/app/duck/user.js
@@ -56,7 +56,6 @@ const reducer = (state = initialState, action = {}) => {
return state.set('passwordErrors', List(action.errors))
case DELETE:
deleteCookie('jwt', '/', '.openreplay.com')
- console.log('called')
return initialState;
case PUT_CLIENT.REQUEST:
return state.mergeIn([ 'account' ], action.params);
diff --git a/frontend/app/duck/variables.js b/frontend/app/duck/variables.js
deleted file mode 100644
index 21a0131c4..000000000
--- a/frontend/app/duck/variables.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import Variable from 'Types/variable';
-import crudDuckGenerator from './tools/crudDuck';
-
-const crudDuck = crudDuckGenerator('variable', Variable);
-export const {
- fetchList, fetch, init, edit, save, remove,
-} = crudDuck.actions;
-
-export default crudDuck.reducer;
diff --git a/frontend/app/mstore/userStore.ts b/frontend/app/mstore/userStore.ts
index 8e8913de6..b46f776a3 100644
--- a/frontend/app/mstore/userStore.ts
+++ b/frontend/app/mstore/userStore.ts
@@ -44,7 +44,7 @@ export default class UserStore {
}
initUser(user?: any ): Promise {
- return new Promise((resolve, reject) => {
+ return new Promise((resolve) => {
if (user) {
this.instance = new User().fromJson(user.toJson());
} else {
@@ -54,7 +54,7 @@ export default class UserStore {
})
}
- updateKey(key: string, value: any) {
+ updateKey(key: keyof this, value: any) {
this[key] = value
if (key === 'searchQuery') {
diff --git a/frontend/app/types/address.js b/frontend/app/types/address.js
deleted file mode 100644
index 8d8e2ccf2..000000000
--- a/frontend/app/types/address.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Record from 'Types/Record';
-
-export default Record({
- line1: '',
- postal_code: '',
- city: '',
- state: '',
- country: '',
-}, {
- methods: {
- validate() {
- return true;
- },
- toData() {
- const js = this.toJS();
- delete js.key;
- return js;
- },
- },
-});
diff --git a/frontend/app/types/appTest.js b/frontend/app/types/appTest.js
deleted file mode 100644
index 248b759b7..000000000
--- a/frontend/app/types/appTest.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import { Record, List, Set } from 'immutable';
-import { validateName } from 'App/validate';
-import { DateTime } from 'luxon';
-import Run from './run';
-import Step from './step';
-
-class Test extends Record({
- testId: undefined,
- name: 'Unnamed Test',
- steps: List(),
- stepsCount: undefined,
- framework: 'selenium',
- sessionId: undefined,
- generated: false,
- tags: Set(),
- runHistory: List(),
- editedAt: undefined,
- seqId: undefined,
- seqChange: false,
- uptime: 0,
-}) {
- // ???TODO
- // idKey = "testId"
-
- exists() {
- return this.testId !== undefined;
- }
-
- validate() {
- if (this.steps.size === 0) return false;
-
- return validateName(this.name, {
- empty: false,
- admissibleChars: ':-',
- });
- }
-
- isComplete() {
- return this.stepsCount === this.steps.size;
- }
-
- // not the best code
- toData() {
- const js = this
- .update('steps', steps => steps.map(step => step.toData()))
- .toJS();
-
- if (js.seqChange) {
- const { testId, seqId } = js;
- return { testId, seqId };
- }
-
- delete js.stepsCount;
- delete js.seqChange;
-
- return js;
- }
- // not the best code
-}
-
-const fromJS = (test = {}) => {
- if (test instanceof Test) return test;
-
- const stepsLength = test.steps && test.steps.length; //
- const editedAt = test.editedAt ? DateTime.fromMillis(test.editedAt) : undefined;
-
- const lastRun = Run(test.lastRun);
- const runHistory = List(test.runHistory) // TODO: GOOD ENDPOINTS
- .map(run => {
- if (typeof run === 'string') {
- return run === lastRun.runId
- ? lastRun
- : Run({ runId: run })
- }
- return Run(run);
- });
-
- return new Test({ ...test, editedAt, uptime: parseInt(test.passed / test.count * 100) || 0 })
- .set('stepsCount', typeof test.stepsCount === 'number'
- ? test.stepsCount
- : stepsLength) //
- .set('runHistory', runHistory)
- .set('steps', List(test.steps).map(Step))
- .set('tags', test.tags && Set(test.tags.map(t => t.toLowerCase())));
-};
-
-export default fromJS;
diff --git a/frontend/app/types/member.ts b/frontend/app/types/member.ts
index d3914eac9..0a88d51ba 100644
--- a/frontend/app/types/member.ts
+++ b/frontend/app/types/member.ts
@@ -16,6 +16,20 @@ export interface IMember {
invitationLink: string
}
+export interface IMemberApiRes {
+ userId: string
+ name: string
+ email: string
+ createdAt: string
+ admin: boolean
+ superAdmin: boolean
+ joined: boolean
+ expiredInvitation: boolean
+ roleId: string
+ roleName: string
+ invitationLink: string
+}
+
export default Record({
id: undefined,
name: '',
@@ -42,9 +56,9 @@ export default Record({
return js;
},
},
- fromJS: ({ createdAt, ...rest }) => ({
+ fromJS: ({ createdAt, ...rest }: IMemberApiRes) => ({
...rest,
- createdAt: createdAt && DateTime.fromISO(createdAt || 0),
+ createdAt: createdAt && DateTime.fromISO(createdAt || '0'),
id: rest.userId,
}),
});