From 63857a2f01f522ce56616474c16eaa550c3857fb Mon Sep 17 00:00:00 2001 From: sylenien Date: Tue, 27 Dec 2022 16:41:00 +0100 Subject: [PATCH 01/11] change(ui): remove old reducers, rewrite eventsblock component --- .../Alerts/Notifications/Notifications.tsx | 26 +- .../CustomMetricWidget/CustomMetricWidget.tsx | 2 - .../components/FilterSeries/FilterSeries.tsx | 50 ++-- .../app/components/Session/RightBlock.tsx | 37 ++- .../components/Session_/EventsBlock/Event.js | 8 - .../EventsBlock/EventSearch/EventSearch.js | 8 +- .../Session_/EventsBlock/EventsBlock.js | 249 ------------------ .../Session_/EventsBlock/EventsBlock.tsx | 187 +++++++++++++ .../PageInsightsPanel/PageInsightsPanel.tsx | 1 - .../FilterSeries/FilterSeries.tsx | 112 -------- .../FilterSeries/SeriesName/SeriesName.tsx | 57 ---- .../FilterSeries/SeriesName/index.ts | 1 - .../CustomMetrics/FilterSeries/index.ts | 1 - .../shared/DevTools/useCellMeasurerCache.ts | 10 +- frontend/app/duck/ReducerModule.js.dev | 55 ---- frontend/app/duck/customMetrics.js | 43 +-- frontend/app/duck/environments.js | 7 - frontend/app/duck/events.js | 81 ------ frontend/app/duck/index.ts | 9 +- frontend/app/duck/notifications.js | 63 ----- frontend/app/duck/sessions.js | 16 +- frontend/app/duck/user.js | 1 - frontend/app/duck/variables.js | 9 - frontend/app/mstore/userStore.ts | 4 +- frontend/app/types/address.js | 20 -- frontend/app/types/appTest.js | 87 ------ frontend/app/types/member.ts | 18 +- 27 files changed, 265 insertions(+), 897 deletions(-) delete mode 100644 frontend/app/components/Session_/EventsBlock/EventsBlock.js create mode 100644 frontend/app/components/Session_/EventsBlock/EventsBlock.tsx delete mode 100644 frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx delete mode 100644 frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/SeriesName.tsx delete mode 100644 frontend/app/components/shared/CustomMetrics/FilterSeries/SeriesName/index.ts delete mode 100644 frontend/app/components/shared/CustomMetrics/FilterSeries/index.ts delete mode 100644 frontend/app/duck/ReducerModule.js.dev delete mode 100644 frontend/app/duck/environments.js delete mode 100644 frontend/app/duck/events.js delete mode 100644 frontend/app/duck/notifications.js delete mode 100644 frontend/app/duck/variables.js delete mode 100644 frontend/app/types/address.js delete mode 100644 frontend/app/types/appTest.js 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, }), }); From 8e6eb8ac1bb2251598288fa955bb22e832c2a03d Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 28 Dec 2022 11:55:04 +0100 Subject: [PATCH 02/11] change(ui): remove config(report) reducer, add mobx store --- frontend/app/components/Client/Client.js | 3 - .../Client/Notifications/Notifications.js | 50 --------- .../Client/Notifications/Notifications.tsx | 39 +++++++ frontend/app/duck/config.js | 61 ----------- frontend/app/duck/index.ts | 6 -- frontend/app/duck/member.js | 8 -- frontend/app/duck/target.js | 33 ------ frontend/app/duck/watchdogs.js | 101 ------------------ frontend/app/mstore/index.tsx | 5 + .../app/mstore/weeklyReportConfigStore.ts | 32 ++++++ frontend/app/services/BaseService.ts | 1 + frontend/app/services/ConfigService.ts | 17 +++ frontend/app/services/index.ts | 2 + 13 files changed, 96 insertions(+), 262 deletions(-) delete mode 100644 frontend/app/components/Client/Notifications/Notifications.js create mode 100644 frontend/app/components/Client/Notifications/Notifications.tsx delete mode 100644 frontend/app/duck/config.js delete mode 100644 frontend/app/duck/target.js delete mode 100644 frontend/app/duck/watchdogs.js create mode 100644 frontend/app/mstore/weeklyReportConfigStore.ts create mode 100644 frontend/app/services/ConfigService.ts diff --git a/frontend/app/components/Client/Client.js b/frontend/app/components/Client/Client.js index b2a6d8f7f..ab16c6b40 100644 --- a/frontend/app/components/Client/Client.js +++ b/frontend/app/components/Client/Client.js @@ -1,9 +1,7 @@ import React from 'react'; -import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { Switch, Route, Redirect } from 'react-router'; import { CLIENT_TABS, client as clientRoute } from 'App/routes'; -import { fetchList as fetchMemberList } from 'Duck/member'; import ProfileSettings from './ProfileSettings'; import Integrations from './Integrations'; @@ -18,7 +16,6 @@ import PreferencesMenu from './PreferencesMenu'; import Notifications from './Notifications'; import Roles from './Roles'; -@connect(null, { fetchMemberList, }) @withRouter export default class Client extends React.PureComponent { constructor(props){ diff --git a/frontend/app/components/Client/Notifications/Notifications.js b/frontend/app/components/Client/Notifications/Notifications.js deleted file mode 100644 index 88855dd45..000000000 --- a/frontend/app/components/Client/Notifications/Notifications.js +++ /dev/null @@ -1,50 +0,0 @@ -import React, { useEffect } from 'react'; -import cn from 'classnames'; -import stl from './notifications.module.css'; -import { Checkbox, Toggler } from 'UI'; -import { connect } from 'react-redux'; -import { withRequest } from 'HOCs'; -import { fetch as fetchConfig, edit as editConfig, save as saveConfig } from 'Duck/config'; -import withPageTitle from 'HOCs/withPageTitle'; - -function Notifications(props) { - const { config } = props; - - useEffect(() => { - props.fetchConfig(); - }, []); - - const onChange = () => { - const _config = { weeklyReport: !config.weeklyReport }; - props.editConfig(_config); - props.saveConfig(_config); - }; - - return ( -
-
{

{'Notifications'}

}
-
-
Weekly project summary
-
Receive wekly report for each project on email.
- - {/* */} - {/* */} -
-
- ); -} - -export default connect( - (state) => ({ - config: state.getIn(['config', 'options']), - }), - { fetchConfig, editConfig, saveConfig } -)(withPageTitle('Notifications - OpenReplay Preferences')(Notifications)); diff --git a/frontend/app/components/Client/Notifications/Notifications.tsx b/frontend/app/components/Client/Notifications/Notifications.tsx new file mode 100644 index 000000000..4a5d9a542 --- /dev/null +++ b/frontend/app/components/Client/Notifications/Notifications.tsx @@ -0,0 +1,39 @@ +import React, { useEffect } from 'react'; +import cn from 'classnames'; +import stl from './notifications.module.css'; +import { Toggler } from 'UI'; +import { useStore } from "App/mstore"; +import { observer } from 'mobx-react-lite' +import withPageTitle from 'HOCs/withPageTitle'; + +function Notifications() { + const { weeklyReportStore } = useStore() + + + useEffect(() => { + void weeklyReportStore.fetchReport() + }, []); + + const onChange = () => { + const newValue = !weeklyReportStore.weeklyReport + void weeklyReportStore.fetchEditReport(newValue) + }; + + return ( +
+
{

{'Notifications'}

}
+
+
Weekly project summary
+
Receive weekly report for each project on email.
+ +
+
+ ); +} + +export default withPageTitle('Notifications - OpenReplay Preferences')(observer(Notifications)) \ No newline at end of file diff --git a/frontend/app/duck/config.js b/frontend/app/duck/config.js deleted file mode 100644 index a445e3f50..000000000 --- a/frontend/app/duck/config.js +++ /dev/null @@ -1,61 +0,0 @@ -import { Map } from 'immutable'; -import { saveType, fetchType, editType } from './funcTools/crud/types'; -import { mergeReducers, success, array } from './funcTools/tools'; -import { createRequestReducer } from './funcTools/request'; - -const name = 'config' - -const FETCH = fetchType(name); -const SAVE = saveType(name); -const EDIT = editType(name); - -const FETCH_SUCCESS = success(FETCH); -const SAVE_SUCCESS = success(SAVE); - -const initialState = Map({ - options: { - weeklyReport: false - }, -}); - -const reducer = (state = initialState, action = {}) => { - switch(action.type) { - case FETCH_SUCCESS: - return state.set('options', action.data) - case SAVE_SUCCESS: - return state - case EDIT: - return state.set('options', action.config) - default: - return state; - } -} - -export const fetch = () => { - return { - types: array(FETCH), - call: client => client.get(`/config/weekly_report`), - } -} - -export const save = (config) => { - return { - types: array(SAVE), - call: client => client.post(`/config/weekly_report`, config), - } -} - -export const edit = (config) => { - return { - type: EDIT, - config - } -} - -export default mergeReducers( - reducer, - createRequestReducer({ - fetchRequest: FETCH, - saveRequest: SAVE, - }), -) \ No newline at end of file diff --git a/frontend/app/duck/index.ts b/frontend/app/duck/index.ts index d33de09a0..1c62c36ff 100644 --- a/frontend/app/duck/index.ts +++ b/frontend/app/duck/index.ts @@ -5,7 +5,6 @@ import jwt from './jwt'; import user from './user'; import sessions from './sessions'; import assignments from './assignments'; -import target from './target'; import targetCustom from './targetCustom'; import filters from './filters'; import funnelFilters from './funnelFilters'; @@ -19,12 +18,10 @@ import site from './site'; import customFields from './customField'; import webhooks from './webhook'; import integrations from './integrations'; -import watchdogs from './watchdogs'; import rehydrate from './rehydrate'; import announcements from './announcements'; import errors from './errors'; import funnels from './funnels'; -import config from './config'; import roles from './roles'; import customMetrics from './customMetrics'; import search from './search'; @@ -35,7 +32,6 @@ const rootReducer = combineReducers({ user, sessions, assignments, - target, targetCustom, filters, funnelFilters, @@ -48,12 +44,10 @@ const rootReducer = combineReducers({ site, customFields, webhooks, - watchdogs, rehydrate, announcements, errors, funnels, - config, roles, customMetrics, search, diff --git a/frontend/app/duck/member.js b/frontend/app/duck/member.js index 31cccb395..290b53f3a 100644 --- a/frontend/app/duck/member.js +++ b/frontend/app/duck/member.js @@ -37,12 +37,4 @@ export function save(instance) { }; } -export function generateInviteLink(instance) { - return { - types: GENERATE_LINK.toArray(), - call: client => client.get(`/client/members/${ instance.id }/reset`), - id: instance.id - }; -} - export default reduceDucks(crudDuck, { initialState, reducer }).reducer; diff --git a/frontend/app/duck/target.js b/frontend/app/duck/target.js deleted file mode 100644 index b1f0e337b..000000000 --- a/frontend/app/duck/target.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Map } from 'immutable'; -import Target from 'Types/target'; -import { RequestTypes } from 'Duck/requestStateCreator'; -import crudDuckGenerator from 'Duck/tools/crudDuck'; -import { reduceDucks } from 'Duck/tools'; - -const FETCH_DEFINED = new RequestTypes('targets/FETCH_DEFINED'); - -const initialState = Map({ - definedPercent: 0, -}); - -const reducer = (state = initialState, action = {}) => { - switch (action.type) { - case FETCH_DEFINED.SUCCESS: - return state.set( - 'definedPercent', - Math.round((action.data.labeled / action.data.total) * 100), - ); - } - return state; -}; - -const crudDuck = crudDuckGenerator('target', Target); -export const { fetchList, init, edit, save, remove } = crudDuck.actions; -export default reduceDucks(crudDuck, { initialState, reducer }).reducer; - -export function fetchDefinedTargetsCount() { - return { - types: FETCH_DEFINED.toArray(), - call: client => client.get('/targets/count'), - }; -} diff --git a/frontend/app/duck/watchdogs.js b/frontend/app/duck/watchdogs.js deleted file mode 100644 index 87966264a..000000000 --- a/frontend/app/duck/watchdogs.js +++ /dev/null @@ -1,101 +0,0 @@ -import { List, Map } from 'immutable'; -import Watchdog from 'Types/watchdog'; -import { mergeReducers, success, array, request } from './funcTools/tools'; -import { createRequestReducer } from './funcTools/request'; -import { - createCRUDReducer, - getCRUDRequestTypes, - createFetchList, - createInit, - createEdit, - createRemove, - createSave, -} from './funcTools/crud'; - -const name = 'issue_type'; -const idKey = 'id'; -const SET_ACTIVE_TAB = 'watchdogs/SET_ACTIVE_TAB'; -const FETCH_WATCHDOG_STATUS = 'watchdogs/FETCH_WATCHDOG_STATUS'; -const FETCH_WATCHDOG_STATUS_SUCCESS = success(FETCH_WATCHDOG_STATUS); -const FETCH_RULES = 'watchdogs/FETCH_RULES'; -const FETCH_RULES_SUCCESS = success(FETCH_RULES); -const SAVE_CAPTURE_RATE = 'watchdogs/SAVE_CAPTURE_RATE'; -const EDIT_CAPTURE_RATE = 'watchdogs/SAVE_CAPTURE_RATE'; - -const initialState = Map({ - activeTab: Map(), - instance: Watchdog(), - list: List(), - rules: List(), - captureRate: Map() -}); - -const reducer = (state = initialState, action = {}) => { - switch (action.type) { - case SET_ACTIVE_TAB: - return state.set('activeTab', action.instance); - case FETCH_RULES_SUCCESS: - return state.set('rules', action.data); - case FETCH_WATCHDOG_STATUS_SUCCESS: - case success(SAVE_CAPTURE_RATE): - return state.set('captureRate', Map(action.data)); - case request(SAVE_CAPTURE_RATE): - return state.mergeIn(['captureRate'], action.params); - case EDIT_CAPTURE_RATE: - return state.mergeIn(['captureRate'], {rate: action.rate}); - } - return state; -}; - - -export const fetchList = createFetchList(name); -export const init = createInit(name); -export const edit = createEdit(name); -export const save = createSave(name); -export const remove = createRemove(name); - -export function setActiveTab(instance) { - return { - type: SET_ACTIVE_TAB, - instance, - }; -} - -export const fetchRules = () => { - return { - types: array(FETCH_RULES), - call: client => client.get(`/watchdogs/rules`), - }; -} - -export default mergeReducers( - reducer, - createCRUDReducer(name, Watchdog, idKey), - createRequestReducer({ - fetchWatchdogStatus: FETCH_WATCHDOG_STATUS, - savingCaptureRate: SAVE_CAPTURE_RATE, - ...getCRUDRequestTypes(name), - }), -); - -export const saveCaptureRate = (params) => { - return { - params, - types: array(SAVE_CAPTURE_RATE), - call: client => client.post(`/sample_rate`, params), - } -} - -export const editCaptureRate = rate => { - return { - type: EDIT_CAPTURE_RATE, - rate - } -} - -export const fetchWatchdogStatus = () => { - return { - types: array(FETCH_WATCHDOG_STATUS), - call: client => client.get('/sample_rate'), - }; -} diff --git a/frontend/app/mstore/index.tsx b/frontend/app/mstore/index.tsx index a4fdbe884..707fb175a 100644 --- a/frontend/app/mstore/index.tsx +++ b/frontend/app/mstore/index.tsx @@ -15,6 +15,7 @@ import { errorService, notesService, recordingsService, + configService, } from 'App/services'; import SettingsStore from './settingsStore'; import AuditStore from './auditStore'; @@ -25,6 +26,7 @@ import NotesStore from './notesStore'; import BugReportStore from './bugReportStore' import RecordingsStore from './recordingsStore' import AssistMultiviewStore from './assistMultiviewStore'; +import WeeklyReportStore from './weeklyReportConfigStore' export class RootStore { dashboardStore: DashboardStore; @@ -41,6 +43,7 @@ export class RootStore { bugReportStore: BugReportStore; recordingsStore: RecordingsStore; assistMultiviewStore: AssistMultiviewStore; + weeklyReportStore: WeeklyReportStore constructor() { this.dashboardStore = new DashboardStore(); @@ -57,6 +60,7 @@ export class RootStore { this.bugReportStore = new BugReportStore(); this.recordingsStore = new RecordingsStore(); this.assistMultiviewStore = new AssistMultiviewStore(); + this.weeklyReportStore = new WeeklyReportStore(); } initClient() { @@ -70,6 +74,7 @@ export class RootStore { errorService.initClient(client); notesService.initClient(client) recordingsService.initClient(client); + configService.initClient(client); } } diff --git a/frontend/app/mstore/weeklyReportConfigStore.ts b/frontend/app/mstore/weeklyReportConfigStore.ts new file mode 100644 index 000000000..7b0eec8a6 --- /dev/null +++ b/frontend/app/mstore/weeklyReportConfigStore.ts @@ -0,0 +1,32 @@ +import { makeAutoObservable }from "mobx" +import { configService } from "App/services"; + +export default class weeklyReportConfigStore { + public weeklyReport = false + + constructor() { + makeAutoObservable(this) + } + + setReport(value: boolean) { + this.weeklyReport = value + } + + async fetchReport() { + try { + const { weeklyReport } = await configService.fetchWeeklyReport() + return this.setReport(weeklyReport) + } catch (e) { + console.error(e) + } + } + + async fetchEditReport(value: boolean) { + try { + const { weeklyReport } = await configService.editWeeklyReport({ weeklyReport: value }) + return this.setReport(weeklyReport) + } catch (e) { + console.error(e) + } + } +} \ No newline at end of file diff --git a/frontend/app/services/BaseService.ts b/frontend/app/services/BaseService.ts index 2af1897f8..5cca28d4e 100644 --- a/frontend/app/services/BaseService.ts +++ b/frontend/app/services/BaseService.ts @@ -1,4 +1,5 @@ import APIClient from 'App/api_client'; + export default class BaseService { client: APIClient; diff --git a/frontend/app/services/ConfigService.ts b/frontend/app/services/ConfigService.ts new file mode 100644 index 000000000..6afda4858 --- /dev/null +++ b/frontend/app/services/ConfigService.ts @@ -0,0 +1,17 @@ +import BaseService from './BaseService'; + +export interface WeeklyReport { + weeklyReport: boolean +} + +export default class ConfigService extends BaseService { + async fetchWeeklyReport(): Promise { + return this.client.get('/config/weekly_report') + .then(r => r.json()).then(j => j.data) + } + + async editWeeklyReport(config: WeeklyReport): Promise { + return this.client.post('/config/weekly_report', config) + .then(r => r.json()).then(j => j.data) + } +} \ No newline at end of file diff --git a/frontend/app/services/index.ts b/frontend/app/services/index.ts index 2bcf5981e..5033c4ed3 100644 --- a/frontend/app/services/index.ts +++ b/frontend/app/services/index.ts @@ -7,6 +7,7 @@ import AuditService from './AuditService'; import ErrorService from "./ErrorService"; import NotesService from "./NotesService"; import RecordingsService from "./RecordingsService"; +import ConfigService from './ConfigService' export const dashboardService = new DashboardService(); export const metricService = new MetricService(); @@ -17,3 +18,4 @@ export const auditService = new AuditService(); export const errorService = new ErrorService(); export const notesService = new NotesService(); export const recordingsService = new RecordingsService(); +export const configService = new ConfigService(); \ No newline at end of file From 9feb0bb91fff6e967e02c0123b9a23b91fc67988 Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 28 Dec 2022 11:59:10 +0100 Subject: [PATCH 03/11] change(ui): small ref for code style --- .../Dashboard/components/FilterSeries/FilterSeries.tsx | 2 +- frontend/app/components/Session_/EventsBlock/EventsBlock.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index bcfd27406..2cf04078f 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -37,7 +37,7 @@ function FilterSeries(props: Props) { observeChanges() } - const onChangeEventsOrder = (e: any, { name, value }: any) => { + const onChangeEventsOrder = (_: any, { name, value }: any) => { series.filter.updateKey(name, value) observeChanges() } diff --git a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx index 0f0405cd5..daa68d85d 100644 --- a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx +++ b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx @@ -83,11 +83,11 @@ function EventsBlock(props: IProps) { } }, [currentTimeEventIndex]) - const onEventClick = (_: React.MouseEvent, event: any) => player.jump(event.time) + const onEventClick = (_: React.MouseEvent, event: { time: number }) => 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 renderGroup = ({ index, key, style, parent }: { index: number; key: string; style: React.CSSProperties; parent: any }) => { const isLastEvent = index === usedEvents.size - 1; const isLastInGroup = isLastEvent || usedEvents.get(index + 1)?.type === TYPES.LOCATION; const event = usedEvents.get(index); From 3dc3d736ac223e90f23c717b2aa35233215d765c Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 28 Dec 2022 14:10:59 +0100 Subject: [PATCH 04/11] change(ui): remove old announcements components and reducer --- frontend/app/Router.js | 2 - .../components/Announcements/Announcements.js | 99 ------------------- .../Announcements/ListItem/ListItem.js | 31 ------ .../Announcements/ListItem/index.js | 1 - .../ListItem/listItem.module.css | 5 - .../Announcements/announcements.module.css | 39 -------- .../app/components/Announcements/index.js | 1 - .../Session_/EventsBlock/EventsBlock.tsx | 2 +- .../AnnouncementModal/AnnouncementModal.tsx | 55 ----------- .../AnnouncementModal/ListItem/ListItem.tsx | 31 ------ .../AnnouncementModal/ListItem/index.ts | 1 - .../ListItem/listItem.module.css | 5 - .../shared/AnnouncementModal/index.ts | 1 - .../DevTools/ConsolePanel/ConsolePanel.tsx | 2 +- .../StackEventPanel/StackEventPanel.tsx | 2 +- frontend/app/duck/announcements.js | 45 --------- frontend/app/duck/index.ts | 2 - frontend/app/duck/member.js | 2 +- .../useCellMeasurerCache.ts | 0 19 files changed, 4 insertions(+), 322 deletions(-) delete mode 100644 frontend/app/components/Announcements/Announcements.js delete mode 100644 frontend/app/components/Announcements/ListItem/ListItem.js delete mode 100644 frontend/app/components/Announcements/ListItem/index.js delete mode 100644 frontend/app/components/Announcements/ListItem/listItem.module.css delete mode 100644 frontend/app/components/Announcements/announcements.module.css delete mode 100644 frontend/app/components/Announcements/index.js delete mode 100644 frontend/app/components/shared/AnnouncementModal/AnnouncementModal.tsx delete mode 100644 frontend/app/components/shared/AnnouncementModal/ListItem/ListItem.tsx delete mode 100644 frontend/app/components/shared/AnnouncementModal/ListItem/index.ts delete mode 100644 frontend/app/components/shared/AnnouncementModal/ListItem/listItem.module.css delete mode 100644 frontend/app/components/shared/AnnouncementModal/index.ts delete mode 100644 frontend/app/duck/announcements.js rename frontend/app/{components/shared/DevTools => hooks}/useCellMeasurerCache.ts (100%) diff --git a/frontend/app/Router.js b/frontend/app/Router.js index e99ee2546..b8832dbd4 100644 --- a/frontend/app/Router.js +++ b/frontend/app/Router.js @@ -8,7 +8,6 @@ import { fetchUserInfo } from 'Duck/user'; import withSiteIdUpdater from 'HOCs/withSiteIdUpdater'; import Header from 'Components/Header/Header'; import { fetchList as fetchSiteList } from 'Duck/site'; -import { fetchList as fetchAnnouncements } from 'Duck/announcements'; import { fetchList as fetchAlerts } from 'Duck/alerts'; import { withStore } from 'App/mstore'; @@ -115,7 +114,6 @@ const MULTIVIEW_INDEX_PATH = routes.multiviewIndex(); fetchTenants, setSessionPath, fetchSiteList, - fetchAnnouncements, fetchAlerts, } ) diff --git a/frontend/app/components/Announcements/Announcements.js b/frontend/app/components/Announcements/Announcements.js deleted file mode 100644 index 55306e643..000000000 --- a/frontend/app/components/Announcements/Announcements.js +++ /dev/null @@ -1,99 +0,0 @@ -import React from 'react'; -import stl from './announcements.module.css'; -import ListItem from './ListItem'; -import { connect } from 'react-redux'; -import { SlideModal, Icon, NoContent, Tooltip } from 'UI'; -import { fetchList, setLastRead } from 'Duck/announcements'; -import withToggle from 'Components/hocs/withToggle'; -import { withRouter } from 'react-router-dom'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; - -@withToggle('visible', 'toggleVisisble') -@withRouter -class Announcements extends React.Component { - - navigateToUrl = url => { - if (url) { - if (url.startsWith(window.env.ORIGIN || window.location.origin)) { - const { history } = this.props; - var path = new URL(url).pathname - if (path.includes('/metrics')) { - const { siteId, sites } = this.props; - const activeSite = sites.find(s => s.id == siteId); - history.push(`/${activeSite.id + path}`); - } else { - history.push(path) - } - } else { - window.open(url, "_blank") - } - this.toggleModal() - } - } - - toggleModal = () => { - if (!this.props.visible) { - const { setLastRead, fetchList } = this.props; - fetchList().then(() => { setTimeout(() => { setLastRead() }, 5000); }); - } - this.props.toggleVisisble(!this.props.visible); - } - - render() { - const { announcements, visible, loading } = this.props; - const unReadNotificationsCount = announcements.filter(({viewed}) => !viewed).size - - return ( -
- -
-
- { unReadNotificationsCount } -
- -
-
- - - - -
No announcements to show.
-
- } - size="small" - show={ !loading && announcements.size === 0 } - > - { - announcements.map(item => ( - - )) - } - -
- } - /> -
- ); - } -} - -export default connect(state => ({ - announcements: state.getIn(['announcements', 'list']), - loading: state.getIn(['announcements', 'fetchList', 'loading']), - siteId: state.getIn([ 'site', 'siteId' ]), - sites: state.getIn([ 'site', 'list' ]), -}), { fetchList, setLastRead })(Announcements); \ No newline at end of file diff --git a/frontend/app/components/Announcements/ListItem/ListItem.js b/frontend/app/components/Announcements/ListItem/ListItem.js deleted file mode 100644 index dd777c719..000000000 --- a/frontend/app/components/Announcements/ListItem/ListItem.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { Button, Label } from 'UI'; -import stl from './listItem.module.css'; - -const ListItem = ({ announcement, onButtonClick }) => { - return ( -
-
-
{announcement.createdAt && announcement.createdAt.toFormat('LLL dd, yyyy')}
- -
- {announcement.imageUrl && - - } -
-

{announcement.title}

-
{announcement.description}
- {announcement.buttonUrl && - - } -
-
- ) -} - -export default ListItem diff --git a/frontend/app/components/Announcements/ListItem/index.js b/frontend/app/components/Announcements/ListItem/index.js deleted file mode 100644 index 741aed270..000000000 --- a/frontend/app/components/Announcements/ListItem/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ListItem'; diff --git a/frontend/app/components/Announcements/ListItem/listItem.module.css b/frontend/app/components/Announcements/ListItem/listItem.module.css deleted file mode 100644 index 5bc3a44c8..000000000 --- a/frontend/app/components/Announcements/ListItem/listItem.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.wrapper { - background-color: white; - margin-bottom: 20px; - padding: 15px; -} \ No newline at end of file diff --git a/frontend/app/components/Announcements/announcements.module.css b/frontend/app/components/Announcements/announcements.module.css deleted file mode 100644 index 5a3704af2..000000000 --- a/frontend/app/components/Announcements/announcements.module.css +++ /dev/null @@ -1,39 +0,0 @@ -.wrapper { - position: relative; -} - -.button { - position: relative; - cursor: pointer; - display: flex; - align-items: center; - padding: 0 15px; - height: 50px; - transition: all 0.3s; - - &:hover { - background-color: $gray-lightest; - transition: all 0.2s; - } - - &[data-active=true] { - background-color: $gray-lightest; - } -} - -.counter { - position: absolute; - top: 8px; - left: 24px; - background-color: #CC0000; - color: white; - font-size: 9px; - font-weight: 300; - min-width: 16px; - height: 16px; - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - padding: 3px; -} diff --git a/frontend/app/components/Announcements/index.js b/frontend/app/components/Announcements/index.js deleted file mode 100644 index faeffcfcd..000000000 --- a/frontend/app/components/Announcements/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Announcements'; \ No newline at end of file diff --git a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx index daa68d85d..8df9be6ff 100644 --- a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx +++ b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx @@ -13,7 +13,7 @@ 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' +import useCellMeasurerCache from 'App/hooks/useCellMeasurerCache' interface IProps { setEventFilter: (filter: { query: string }) => void diff --git a/frontend/app/components/shared/AnnouncementModal/AnnouncementModal.tsx b/frontend/app/components/shared/AnnouncementModal/AnnouncementModal.tsx deleted file mode 100644 index 5f69de976..000000000 --- a/frontend/app/components/shared/AnnouncementModal/AnnouncementModal.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import { Button, NoContent } from 'UI'; -import { connect } from 'react-redux'; -import { fetchList, setLastRead } from 'Duck/announcements'; -import cn from 'classnames'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; -import ListItem from './ListItem' - -interface Props { - unReadNotificationsCount: number; - setLastRead: Function; - list: any; -} -function AnnouncementModal(props: Props) { - const { list, unReadNotificationsCount } = props; - - // const onClear = (notification: any) => { - // console.log('onClear', notification); - // props.setViewed(notification.notificationId) - // } - - return ( -
-
-
Announcements
-
- -
- - -
- } - subtext="There are no alerts to show." - // show={ !loading && unReadNotificationsCount === 0 } - size="small" - > - {list.map((item: any, i: any) => ( -
- {/* onClear(item)} loading={false} /> */} -
- ))} - -
- - ); -} - -export default connect((state: any) => ({ - list: state.getIn(['announcements', 'list']), -}), { - fetchList, - setLastRead, -})(AnnouncementModal); \ No newline at end of file diff --git a/frontend/app/components/shared/AnnouncementModal/ListItem/ListItem.tsx b/frontend/app/components/shared/AnnouncementModal/ListItem/ListItem.tsx deleted file mode 100644 index dd777c719..000000000 --- a/frontend/app/components/shared/AnnouncementModal/ListItem/ListItem.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { Button, Label } from 'UI'; -import stl from './listItem.module.css'; - -const ListItem = ({ announcement, onButtonClick }) => { - return ( -
-
-
{announcement.createdAt && announcement.createdAt.toFormat('LLL dd, yyyy')}
- -
- {announcement.imageUrl && - - } -
-

{announcement.title}

-
{announcement.description}
- {announcement.buttonUrl && - - } -
-
- ) -} - -export default ListItem diff --git a/frontend/app/components/shared/AnnouncementModal/ListItem/index.ts b/frontend/app/components/shared/AnnouncementModal/ListItem/index.ts deleted file mode 100644 index 741aed270..000000000 --- a/frontend/app/components/shared/AnnouncementModal/ListItem/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ListItem'; diff --git a/frontend/app/components/shared/AnnouncementModal/ListItem/listItem.module.css b/frontend/app/components/shared/AnnouncementModal/ListItem/listItem.module.css deleted file mode 100644 index 5bc3a44c8..000000000 --- a/frontend/app/components/shared/AnnouncementModal/ListItem/listItem.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.wrapper { - background-color: white; - margin-bottom: 20px; - padding: 15px; -} \ No newline at end of file diff --git a/frontend/app/components/shared/AnnouncementModal/index.ts b/frontend/app/components/shared/AnnouncementModal/index.ts deleted file mode 100644 index b9af0fc52..000000000 --- a/frontend/app/components/shared/AnnouncementModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './AnnouncementModal'; \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx b/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx index 4719914ba..1c7e9c425 100644 --- a/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx +++ b/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx @@ -12,7 +12,7 @@ import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorD import { useModal } from 'App/components/Modal'; import useAutoscroll, { getLastItemTime } from '../useAutoscroll'; import { useRegExListFilterMemo, useTabListFilterMemo } from '../useListFilter' -import useCellMeasurerCache from '../useCellMeasurerCache' +import useCellMeasurerCache from 'App/hooks/useCellMeasurerCache' const ALL = 'ALL'; const INFO = 'INFO'; diff --git a/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx b/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx index 366750b51..b97e82e97 100644 --- a/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx +++ b/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx @@ -12,7 +12,7 @@ import StackEventRow from 'Shared/DevTools/StackEventRow'; import StackEventModal from '../StackEventModal'; import useAutoscroll, { getLastItemTime } from '../useAutoscroll'; import { useRegExListFilterMemo, useTabListFilterMemo } from '../useListFilter' -import useCellMeasurerCache from '../useCellMeasurerCache' +import useCellMeasurerCache from 'App/hooks/useCellMeasurerCache' const INDEX_KEY = 'stackEvent'; const ALL = 'ALL'; diff --git a/frontend/app/duck/announcements.js b/frontend/app/duck/announcements.js deleted file mode 100644 index 3a7612ee7..000000000 --- a/frontend/app/duck/announcements.js +++ /dev/null @@ -1,45 +0,0 @@ -import { List, Map } from 'immutable'; -import Announcement from 'Types/announcement'; -import { RequestTypes } from './requestStateCreator'; - -import { mergeReducers } from './funcTools/tools'; -import { createRequestReducer } from './funcTools/request'; -import { - createCRUDReducer, - getCRUDRequestTypes, - createFetchList -} from './funcTools/crud'; - -const name = 'announcement'; -const idKey = 'id'; - -const SET_LAST_READ = new RequestTypes('announcement/SET_LAST_READ'); - -const initialState = Map({ - list: List() -}); - -const reducer = (state = initialState, action = {}) => { - switch (action.type) { - case SET_LAST_READ.SUCCESS: - return state.update('list', (list) => list.map(i => ({...i.toJS(), viewed: true }))); - } - return state; -}; - -export function setLastRead() { - return { - types: SET_LAST_READ.toArray(), - call: client => client.get(`/announcements/view`), - }; -} - -export const fetchList = createFetchList(name); - -export default mergeReducers( - reducer, - createCRUDReducer(name, Announcement, idKey), - createRequestReducer({ - ...getCRUDRequestTypes(name), - }), -); \ No newline at end of file diff --git a/frontend/app/duck/index.ts b/frontend/app/duck/index.ts index 1c62c36ff..96e150920 100644 --- a/frontend/app/duck/index.ts +++ b/frontend/app/duck/index.ts @@ -19,7 +19,6 @@ import customFields from './customField'; import webhooks from './webhook'; import integrations from './integrations'; import rehydrate from './rehydrate'; -import announcements from './announcements'; import errors from './errors'; import funnels from './funnels'; import roles from './roles'; @@ -45,7 +44,6 @@ const rootReducer = combineReducers({ customFields, webhooks, rehydrate, - announcements, errors, funnels, roles, diff --git a/frontend/app/duck/member.js b/frontend/app/duck/member.js index 290b53f3a..ce12c1659 100644 --- a/frontend/app/duck/member.js +++ b/frontend/app/duck/member.js @@ -1,7 +1,7 @@ import { Map } from 'immutable'; import Member from 'Types/member'; import crudDuckGenerator from './tools/crudDuck'; -import withRequestState, { RequestTypes } from 'Duck/requestStateCreator'; +import { RequestTypes } from 'Duck/requestStateCreator'; import { reduceDucks } from 'Duck/tools'; const GENERATE_LINK = new RequestTypes('member/GENERATE_LINK'); diff --git a/frontend/app/components/shared/DevTools/useCellMeasurerCache.ts b/frontend/app/hooks/useCellMeasurerCache.ts similarity index 100% rename from frontend/app/components/shared/DevTools/useCellMeasurerCache.ts rename to frontend/app/hooks/useCellMeasurerCache.ts From 22cdb4f4e7b367e8e73cd2a24fe9caf8b388ce36 Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 28 Dec 2022 14:41:04 +0100 Subject: [PATCH 05/11] change(ui): remove bugfinder components and store --- frontend/.storybook/config.DEPRECATED.js | 2 - frontend/app/Router.js | 6 +- frontend/app/api_client.js | 1 - .../BugFinder/AutoComplete/AutoComplete.js | 199 ------------------ .../BugFinder/AutoComplete/DropdownItem.js | 10 - .../AutoComplete/autoComplete.module.css | 64 ------ .../AutoComplete/dropdownItem.module.css | 11 - .../BugFinder/AutoComplete/index.js | 1 - .../app/components/BugFinder/BugFinder.js | 131 ------------ .../app/components/BugFinder/DateRange.js | 31 --- .../BugFinder/FilterSelectionButton.js | 14 -- .../BugFinder/Filters/SortDropdown.js | 37 ---- .../app/components/BugFinder/Filters/index.js | 1 - .../BugFinder/Filters/sortDropdown.module.css | 23 -- frontend/app/components/BugFinder/Insights.js | 21 -- .../app/components/BugFinder/ListHeader.js | 10 - .../BugFinder/SessionList/SessionList.js | 150 ------------- .../SessionList/SessionListFooter.js | 29 --- .../SessionList/SessionListHeader.js | 78 ------- .../components/BugFinder/SessionList/index.js | 1 - .../SessionList/sessionList.module.css | 12 -- .../SessionList/sessionListFooter.module.css | 18 -- .../BugFinder/SessionsMenu/SessionsMenu.js | 72 ------- .../BugFinder/SessionsMenu/index.js | 1 - .../SessionsMenu/sessionMenu.module.css | 29 --- .../components/BugFinder/TabItem/TabItem.js | 27 --- .../app/components/BugFinder/TabItem/index.js | 1 - .../BugFinder/TabItem/tabItem.module.css | 23 -- .../components/BugFinder/bugFinder.module.css | 44 ---- .../components/BugFinder/bugFinder.stories.js | 70 ------ .../filterSelectionButton.module.css | 24 --- frontend/app/components/BugFinder/index.js | 1 - .../components/BugFinder/insights.module.css | 18 -- .../BugFinder/listHeader.module.css | 7 - frontend/app/components/Errors/List/List.js | 3 +- .../shared/SessionStack/SessionStack.js | 42 ---- .../components/shared/SessionStack/index.js | 1 - .../SessionStack/sessionStack.module.css | 18 -- frontend/app/types/filter/savedFilter.js | 1 - frontend/app/types/session/session.ts | 2 - frontend/app/types/ts/search.ts | 1 - 41 files changed, 4 insertions(+), 1231 deletions(-) delete mode 100644 frontend/app/components/BugFinder/AutoComplete/AutoComplete.js delete mode 100644 frontend/app/components/BugFinder/AutoComplete/DropdownItem.js delete mode 100644 frontend/app/components/BugFinder/AutoComplete/autoComplete.module.css delete mode 100644 frontend/app/components/BugFinder/AutoComplete/dropdownItem.module.css delete mode 100644 frontend/app/components/BugFinder/AutoComplete/index.js delete mode 100644 frontend/app/components/BugFinder/BugFinder.js delete mode 100644 frontend/app/components/BugFinder/DateRange.js delete mode 100644 frontend/app/components/BugFinder/FilterSelectionButton.js delete mode 100644 frontend/app/components/BugFinder/Filters/SortDropdown.js delete mode 100644 frontend/app/components/BugFinder/Filters/index.js delete mode 100644 frontend/app/components/BugFinder/Filters/sortDropdown.module.css delete mode 100644 frontend/app/components/BugFinder/Insights.js delete mode 100644 frontend/app/components/BugFinder/ListHeader.js delete mode 100644 frontend/app/components/BugFinder/SessionList/SessionList.js delete mode 100644 frontend/app/components/BugFinder/SessionList/SessionListFooter.js delete mode 100644 frontend/app/components/BugFinder/SessionList/SessionListHeader.js delete mode 100644 frontend/app/components/BugFinder/SessionList/index.js delete mode 100644 frontend/app/components/BugFinder/SessionList/sessionList.module.css delete mode 100644 frontend/app/components/BugFinder/SessionList/sessionListFooter.module.css delete mode 100644 frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js delete mode 100644 frontend/app/components/BugFinder/SessionsMenu/index.js delete mode 100644 frontend/app/components/BugFinder/SessionsMenu/sessionMenu.module.css delete mode 100644 frontend/app/components/BugFinder/TabItem/TabItem.js delete mode 100644 frontend/app/components/BugFinder/TabItem/index.js delete mode 100644 frontend/app/components/BugFinder/TabItem/tabItem.module.css delete mode 100644 frontend/app/components/BugFinder/bugFinder.module.css delete mode 100644 frontend/app/components/BugFinder/bugFinder.stories.js delete mode 100644 frontend/app/components/BugFinder/filterSelectionButton.module.css delete mode 100644 frontend/app/components/BugFinder/index.js delete mode 100644 frontend/app/components/BugFinder/insights.module.css delete mode 100644 frontend/app/components/BugFinder/listHeader.module.css delete mode 100644 frontend/app/components/shared/SessionStack/SessionStack.js delete mode 100644 frontend/app/components/shared/SessionStack/index.js delete mode 100644 frontend/app/components/shared/SessionStack/sessionStack.module.css diff --git a/frontend/.storybook/config.DEPRECATED.js b/frontend/.storybook/config.DEPRECATED.js index fad172b6f..ba3f6eb05 100644 --- a/frontend/.storybook/config.DEPRECATED.js +++ b/frontend/.storybook/config.DEPRECATED.js @@ -11,14 +11,12 @@ const withProvider = (story) => ( // const req = require.context('../app/components/ui', true, /\.stories\.js$/); // const issues = require.context('../app/components/Session/Issues', true, /\.stories\.js$/); -// const bugFinder = require.context('../app/components/BugFinder', true, /\.stories\.js$/); addDecorator(withProvider); addDecorator(story => {story()}); // function loadStories() { // req.keys().forEach(filename => req(filename)); -// bugFinder.keys().forEach(filename => bugFinder(filename)); // } // configure(loadStories, module); diff --git a/frontend/app/Router.js b/frontend/app/Router.js index b8832dbd4..955cfa0b3 100644 --- a/frontend/app/Router.js +++ b/frontend/app/Router.js @@ -29,7 +29,7 @@ const LiveSessionPure = lazy(() => import('Components/Session/LiveSession')); const OnboardingPure = lazy(() => import('Components/Onboarding/Onboarding')); const ClientPure = lazy(() => import('Components/Client/Client')); const AssistPure = lazy(() => import('Components/Assist')); -const BugFinderPure = lazy(() => import('Components/Overview')); +const SessionsOverviewPure = lazy(() => import('Components/Overview')); const DashboardPure = lazy(() => import('Components/Dashboard/NewDashboard')); const ErrorsPure = lazy(() => import('Components/Errors/Errors')); const FunnelDetailsPure = lazy(() => import('Components/Funnels/FunnelDetails')); @@ -37,7 +37,7 @@ const FunnelIssueDetails = lazy(() => import('Components/Funnels/FunnelIssueDeta const FunnelPagePure = lazy(() => import('Components/Funnels/FunnelPage')); const MultiviewPure = lazy(() => import('Components/Session_/Multiview/Multiview.tsx')); -const BugFinder = withSiteIdUpdater(BugFinderPure); +const SessionsOverview = withSiteIdUpdater(SessionsOverviewPure); const Dashboard = withSiteIdUpdater(DashboardPure); const Session = withSiteIdUpdater(SessionPure); const LiveSession = withSiteIdUpdater(LiveSessionPure); @@ -235,7 +235,7 @@ class Router extends React.Component { - + } /> diff --git a/frontend/app/api_client.js b/frontend/app/api_client.js index b60c0dbb7..421074036 100644 --- a/frontend/app/api_client.js +++ b/frontend/app/api_client.js @@ -88,7 +88,6 @@ export default class APIClient { if ( path !== '/targets_temp' && !path.includes('/metadata/session_search') && - !path.includes('/watchdogs/rules') && !path.includes('/assist/credentials') && !!this.siteId && siteIdRequiredPaths.some(sidPath => path.startsWith(sidPath)) diff --git a/frontend/app/components/BugFinder/AutoComplete/AutoComplete.js b/frontend/app/components/BugFinder/AutoComplete/AutoComplete.js deleted file mode 100644 index 59ed9d9e9..000000000 --- a/frontend/app/components/BugFinder/AutoComplete/AutoComplete.js +++ /dev/null @@ -1,199 +0,0 @@ -import React from 'react'; -import APIClient from 'App/api_client'; -import cn from 'classnames'; -import { Input, Icon } from 'UI'; -import { debounce } from 'App/utils'; -import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; -import EventSearchInput from 'Shared/EventSearchInput'; -import stl from './autoComplete.module.css'; -import FilterItem from '../CustomFilters/FilterItem'; - -const TYPE_TO_SEARCH_MSG = "Start typing to search..."; -const NO_RESULTS_MSG = "No results found."; -const SOME_ERROR_MSG = "Some error occured."; -const defaultValueToText = value => value; -const defaultOptionMapping = (values, valueToText) => values.map(value => ({ text: valueToText(value), value })); - -const hiddenStyle = { - whiteSpace: 'pre-wrap', - opacity: 0, position: 'fixed', left: '-3000px' -}; - -let pasted = false; -let changed = false; - -class AutoComplete extends React.PureComponent { - static defaultProps = { - method: 'GET', - params: {}, - } - - state = { - values: [], - noResultsMessage: TYPE_TO_SEARCH_MSG, - ddOpen: false, - query: this.props.value, - loading: false, - error: false - } - - componentWillReceiveProps(newProps) { - if (this.props.value !== newProps.value) { - this.setState({ query: newProps.value}); - } - } - - onClickOutside = () => { - this.setState({ ddOpen: false }); - } - - requestValues = (q) => { - const { params, endpoint, method } = this.props; - this.setState({ - loading: true, - error: false, - }); - return new APIClient()[ method.toLowerCase() ](endpoint, { ...params, q }) - .then(response => response.json()) - .then(({ errors, data }) => { - if (errors) { - this.setError(); - } else { - this.setState({ - ddOpen: true, - values: data, - loading: false, - noResultsMessage: NO_RESULTS_MSG, - }); - } - }) - .catch(this.setError); - } - - debouncedRequestValues = debounce(this.requestValues, 1000) - - setError = () => this.setState({ - loading: false, - error: true, - noResultsMessage: SOME_ERROR_MSG, - }) - - - onInputChange = ({ target: { value } }) => { - changed = true; - this.setState({ query: value, updated: true }) - const _value = value ? value.trim() : undefined; - if (_value !== '' && _value !== ' ') { - this.debouncedRequestValues(_value) - } - } - - onBlur = ({ target: { value } }) => { - // to avoid sending unnecessary request on focus in/out without changing - if (!changed && !pasted) return; - - value = pasted ? this.hiddenInput.value : value; - const { onSelect, name } = this.props; - if (value !== this.props.value) { - const _value = value ? value.trim() : undefined; - onSelect(null, {name, value: _value}); - } - - changed = false; - pasted = false; - } - - onItemClick = (e, item) => { - e.stopPropagation(); - e.preventDefault(); - const { onSelect, name } = this.props; - - this.setState({ query: item.value, ddOpen: false}) - onSelect(e, {name, ...item.toJS()}); - } - - render() { - const { ddOpen, query, loading, values } = this.state; - const { - optionMapping = defaultOptionMapping, - valueToText = defaultValueToText, - placeholder = 'Type to search...', - headerText = '', - fullWidth = false, - onRemoveValue = () => {}, - onAddValue = () => {}, - showCloseButton = false, - } = this.props; - - const options = optionMapping(values, valueToText) - - return ( - - {/* */} -
- this.setState({ddOpen: true})} - onChange={ this.onInputChange } - onBlur={ this.onBlur } - value={ query } - autoFocus={ true } - type="text" - placeholder={ placeholder } - onPaste={(e) => { - const text = e.clipboardData.getData('Text'); - this.hiddenInput.value = text; - pasted = true; // to use only the hidden input - } } - autocomplete="do-not-autofill-bad-chrome" - /> -
- { showCloseButton ? : or} -
-
- - {showCloseButton &&
or
} - {/* this.setState({ddOpen: true})} - value={ query } - // icon="search" - label={{ basic: true, content:
test
}} - labelPosition='right' - loading={ loading } - autoFocus={ true } - type="search" - placeholder={ placeholder } - onPaste={(e) => { - const text = e.clipboardData.getData('Text'); - this.hiddenInput.value = text; - pasted = true; // to use only the hidden input - } } - /> */} - - { ddOpen && options.length > 0 && -
- { headerText && headerText } - { - options.map(item => ( - this.onItemClick(e, item) } - /> - )) - } -
- } -
- ); - } -} - -export default AutoComplete; diff --git a/frontend/app/components/BugFinder/AutoComplete/DropdownItem.js b/frontend/app/components/BugFinder/AutoComplete/DropdownItem.js deleted file mode 100644 index dc2b97304..000000000 --- a/frontend/app/components/BugFinder/AutoComplete/DropdownItem.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import stl from './dropdownItem.module.css'; - -const DropdownItem = ({ value, onSelect }) => { - return ( -
{ value }
- ); -}; - -export default DropdownItem; diff --git a/frontend/app/components/BugFinder/AutoComplete/autoComplete.module.css b/frontend/app/components/BugFinder/AutoComplete/autoComplete.module.css deleted file mode 100644 index 09a9a6571..000000000 --- a/frontend/app/components/BugFinder/AutoComplete/autoComplete.module.css +++ /dev/null @@ -1,64 +0,0 @@ -.menu { - border-radius: 0 0 3px 3px; - box-shadow: 0 2px 10px 0 $gray-light; - padding: 20px; - background-color: white; - max-height: 350px; - overflow-y: auto; - position: absolute; - top: 28px; - left: 0; - width: 500px; - z-index: 99; -} - -.searchInput { - & input { - font-size: 13px !important; - padding: 5px !important; - color: $gray-darkest !important; - font-size: 14px !important; - background-color: rgba(255, 255, 255, 0.8) !important; - - & .label { - padding: 0px !important; - display: flex; - align-items: center; - justify-content: center; - } - } - height: 28px !important; - width: 280px; - color: $gray-darkest !important; -} - -.fullWidth { - width: 100% !important; -} - -.inputWrapper { - border: solid thin $gray-light !important; - border-radius: 3px; - border-radius: 3px; - display: flex; - align-items: center; - & input { - height: 28px; - font-size: 13px !important; - padding: 0 5px !important; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - } - - & .right { - height: 28px; - display: flex; - align-items: center; - padding: 0 5px; - background-color: $gray-lightest; - border-left: solid thin $gray-light !important; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - cursor: pointer; - } -} \ No newline at end of file diff --git a/frontend/app/components/BugFinder/AutoComplete/dropdownItem.module.css b/frontend/app/components/BugFinder/AutoComplete/dropdownItem.module.css deleted file mode 100644 index f5646a470..000000000 --- a/frontend/app/components/BugFinder/AutoComplete/dropdownItem.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.wrapper { - padding: 8px; - border-bottom: solid thin rgba(0, 0, 0, 0.05); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - cursor: pointer; - &:hover { - background-color: $active-blue; - } -} \ No newline at end of file diff --git a/frontend/app/components/BugFinder/AutoComplete/index.js b/frontend/app/components/BugFinder/AutoComplete/index.js deleted file mode 100644 index fa63241a4..000000000 --- a/frontend/app/components/BugFinder/AutoComplete/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './AutoComplete'; \ No newline at end of file diff --git a/frontend/app/components/BugFinder/BugFinder.js b/frontend/app/components/BugFinder/BugFinder.js deleted file mode 100644 index 2c31a3ca8..000000000 --- a/frontend/app/components/BugFinder/BugFinder.js +++ /dev/null @@ -1,131 +0,0 @@ -import React from 'react'; -import cn from 'classnames'; -import { connect } from 'react-redux'; -import withPageTitle from 'HOCs/withPageTitle'; -import { fetchFavoriteList as fetchFavoriteSessionList } from 'Duck/sessions'; -import { applyFilter, clearEvents, addAttribute } from 'Duck/filters'; -import { KEYS } from 'Types/filter/customFilter'; -import SessionList from './SessionList'; -import stl from './bugFinder.module.css'; -import withLocationHandlers from 'HOCs/withLocationHandlers'; -import { fetch as fetchFilterVariables } from 'Duck/sources'; -import { fetchSources } from 'Duck/customField'; -import { setActiveTab } from 'Duck/search'; -import SessionsMenu from './SessionsMenu/SessionsMenu'; -import NoSessionsMessage from 'Shared/NoSessionsMessage'; -import SessionSearch from 'Shared/SessionSearch'; -import MainSearchBar from 'Shared/MainSearchBar'; -import { clearSearch, fetchSessions, addFilterByKeyAndValue } from 'Duck/search'; -import { FilterKey } from 'Types/filter/filterType'; - -const weakEqual = (val1, val2) => { - if (!!val1 === false && !!val2 === false) return true; - if (!val1 !== !val2) return false; - return `${val1}` === `${val2}`; -}; - -const allowedQueryKeys = [ - 'userOs', - 'userId', - 'userBrowser', - 'userDevice', - 'userCountry', - 'startDate', - 'endDate', - 'minDuration', - 'maxDuration', - 'referrer', - 'sort', - 'order', -]; - -@withLocationHandlers() -@connect( - (state) => ({ - filter: state.getIn(['filters', 'appliedFilter']), - variables: state.getIn(['customFields', 'list']), - sources: state.getIn(['customFields', 'sources']), - filterValues: state.get('filterValues'), - favoriteList: state.getIn(['sessions', 'favoriteList']), - currentProjectId: state.getIn(['site', 'siteId']), - sites: state.getIn(['site', 'list']), - watchdogs: state.getIn(['watchdogs', 'list']), - activeFlow: state.getIn(['filters', 'activeFlow']), - sessions: state.getIn(['sessions', 'list']), - }), - { - fetchFavoriteSessionList, - applyFilter, - addAttribute, - fetchFilterVariables, - fetchSources, - clearEvents, - setActiveTab, - clearSearch, - fetchSessions, - addFilterByKeyAndValue, - } -) -@withPageTitle('Sessions - OpenReplay') -export default class BugFinder extends React.PureComponent { - state = { showRehydratePanel: false }; - constructor(props) { - super(props); - - // TODO should cache the response - // props.fetchSources().then(() => { - // defaultFilters[6] = { - // category: 'Collaboration', - // type: 'CUSTOM', - // keys: this.props.sources.filter(({type}) => type === 'collaborationTool').map(({ label, key }) => ({ type: 'CUSTOM', source: key, label: label, key, icon: 'integrations/' + key, isFilter: false })).toJS() - // }; - // defaultFilters[7] = { - // category: 'Logging Tools', - // type: 'ERROR', - // keys: this.props.sources.filter(({type}) => type === 'logTool').map(({ label, key }) => ({ type: 'ERROR', source: key, label: label, key, icon: 'integrations/' + key, isFilter: false })).toJS() - // }; - // }); - // if (props.sessions.size === 0) { - // props.fetchSessions(); - // } - - const queryFilter = this.props.query.all(allowedQueryKeys); - if (queryFilter.hasOwnProperty('userId')) { - props.addFilterByKeyAndValue(FilterKey.USERID, queryFilter.userId); - } else { - if (props.sessions.size === 0) { - props.fetchSessions(); - } - } - } - - toggleRehydratePanel = () => { - this.setState({ showRehydratePanel: !this.state.showRehydratePanel }); - }; - - setActiveTab = (tab) => { - this.props.setActiveTab(tab); - }; - - render() { - const { showRehydratePanel } = this.state; - - return ( -
-
-
- -
-
- -
- - -
- -
-
-
- ); - } -} diff --git a/frontend/app/components/BugFinder/DateRange.js b/frontend/app/components/BugFinder/DateRange.js deleted file mode 100644 index 9a6e77f12..000000000 --- a/frontend/app/components/BugFinder/DateRange.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { applyFilter } from 'Duck/search'; -import { fetchList as fetchFunnelsList } from 'Duck/funnels'; -import DateRangeDropdown from 'Shared/DateRangeDropdown'; - -@connect(state => ({ - filter: state.getIn([ 'search', 'instance' ]), -}), { - applyFilter, fetchFunnelsList -}) -export default class DateRange extends React.PureComponent { - onDateChange = (e) => { - // this.props.fetchFunnelsList(e.rangeValue) - this.props.applyFilter(e) - } - render() { - const { filter: { rangeValue, startDate, endDate }, className } = this.props; - - return ( - - ); - } -} \ No newline at end of file diff --git a/frontend/app/components/BugFinder/FilterSelectionButton.js b/frontend/app/components/BugFinder/FilterSelectionButton.js deleted file mode 100644 index 9854b29a3..000000000 --- a/frontend/app/components/BugFinder/FilterSelectionButton.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { Icon } from 'UI'; -import stl from './filterSelectionButton.module.css'; - -const FilterSelectionButton = ({ label }) => { - return ( -
- { label } - -
- ); -}; - -export default FilterSelectionButton; diff --git a/frontend/app/components/BugFinder/Filters/SortDropdown.js b/frontend/app/components/BugFinder/Filters/SortDropdown.js deleted file mode 100644 index 398902ec5..000000000 --- a/frontend/app/components/BugFinder/Filters/SortDropdown.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import Select from 'Shared/Select'; -import { Icon } from 'UI'; -import { sort } from 'Duck/sessions'; -import { applyFilter } from 'Duck/search'; -import stl from './sortDropdown.module.css'; - -@connect(null, { sort, applyFilter }) -export default class SortDropdown extends React.PureComponent { - state = { value: null } - sort = ({ value }) => { - value = value.value - this.setState({ value: value }) - const [ sort, order ] = value.split('-'); - const sign = order === 'desc' ? -1 : 1; - this.props.applyFilter({ order, sort }); - - this.props.sort(sort, sign) - setTimeout(() => this.props.sort(sort, sign), 3000); //AAA - } - - render() { - const { options } = this.props; - return ( -