diff --git a/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js__ b/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js__
deleted file mode 100644
index 59e172c54..000000000
--- a/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js__
+++ /dev/null
@@ -1,159 +0,0 @@
-import React, { useState, useEffect } from 'react'
-import { Tabs, Loader } from 'UI'
-import FunnelHeader from 'Components/Funnels/FunnelHeader'
-import FunnelGraph from 'Components/Funnels/FunnelGraph'
-import FunnelSessionList from 'Components/Funnels/FunnelSessionList'
-import FunnelOverview from 'Components/Funnels/FunnelOverview'
-import FunnelIssues from 'Components/Funnels/FunnelIssues'
-import { connect } from 'react-redux';
-import {
- fetch, fetchInsights, fetchList, fetchFiltered, fetchIssuesFiltered, fetchSessionsFiltered, fetchIssueTypes, resetFunnel, refresh
-} from 'Duck/funnels';
-import { applyFilter, setFilterOptions, resetFunnelFilters, setInitialFilters } from 'Duck/funnelFilters';
-import { withRouter } from 'react-router';
-import { sessions as sessionsRoute, funnel as funnelRoute, withSiteId } from 'App/routes';
-import FunnelSearch from 'Shared/FunnelSearch';
-import cn from 'classnames';
-import IssuesEmptyMessage from 'Components/Funnels/IssuesEmptyMessage'
-
-const TAB_ISSUES = 'ANALYSIS';
-const TAB_SESSIONS = 'SESSIONS';
-
-const TABS = [ TAB_ISSUES, TAB_SESSIONS ].map(tab => ({
- text: tab,
- disabled: false,
- key: tab,
-}));
-
-const FunnelDetails = (props) => {
- const { insights, funnels, funnel, funnelId, loading, liveFilters, issuesLoading, sessionsLoading, refresh } = props;
- const [activeTab, setActiveTab] = useState(TAB_ISSUES)
- const [showFilters, setShowFilters] = useState(false)
- const [mounted, setMounted] = useState(false);
- const onTabClick = activeTab => setActiveTab(activeTab)
-
- useEffect(() => {
- if (funnels.size === 0) {
- props.fetchList();
- }
- props.fetchIssueTypes()
-
- props.fetch(funnelId).then(() => {
- setMounted(true);
- }).then(() => {
- props.refresh(funnelId);
- })
-
- }, []);
-
- // useEffect(() => {
- // if (funnel && funnel.filter && liveFilters.events.size === 0) {
- // props.setInitialFilters();
- // }
- // }, [funnel])
-
- const onBack = () => {
- props.history.push(sessionsRoute());
- }
-
- const redirect = funnelId => {
- const { siteId, history } = props;
- props.resetFunnel();
- props.resetFunnelFilters();
-
- history.push(withSiteId(funnelRoute(parseInt(funnelId)), siteId));
- }
-
- const renderActiveTab = (tab, hasNoStages) => {
- switch(tab) {
- case TAB_ISSUES:
- return !hasNoStages &&
- case TAB_SESSIONS:
- return
- }
- }
-
- const hasNoStages = !loading && insights.stages.length <= 1;
- const showEmptyMessage = hasNoStages && activeTab === TAB_ISSUES && !loading;
-
- return (
-
-
setShowFilters(!showFilters)}
- showFilters={showFilters}
- />
-
- {showFilters && (
-
- )
- }
-
-
-
-
- setShowFilters(true)} show={showEmptyMessage}>
-
-
-
-
- { renderActiveTab(activeTab, hasNoStages) }
-
-
-
-
-
-
- )
-}
-
-export default connect((state, props) => {
- const insightsLoading = state.getIn(['funnels', 'fetchInsights', 'loading']);
- const issuesLoading = state.getIn(['funnels', 'fetchIssuesRequest', 'loading']);
- const funnelLoading = state.getIn(['funnels', 'fetchRequest', 'loading']);
- const sessionsLoading = state.getIn(['funnels', 'fetchSessionsRequest', 'loading']);
- return {
- funnels: state.getIn(['funnels', 'list']),
- funnel: state.getIn(['funnels', 'instance']),
- insights: state.getIn(['funnels', 'insights']),
- loading: funnelLoading || (insightsLoading && (issuesLoading || sessionsLoading)),
- issuesLoading,
- sessionsLoading,
- funnelId: props.match.params.funnelId,
- activeStages: state.getIn(['funnels', 'activeStages']),
- funnelFilters: state.getIn(['funnels', 'funnelFilters']),
- siteId: state.getIn([ 'site', 'siteId' ]),
- liveFilters: state.getIn(['funnelFilters', 'appliedFilter']),
- }
-}, {
- fetch,
- fetchInsights,
- fetchFiltered,
- fetchIssuesFiltered,
- fetchList,
- applyFilter,
- setFilterOptions,
- fetchIssuesFiltered,
- fetchSessionsFiltered,
- fetchIssueTypes,
- resetFunnel,
- resetFunnelFilters,
- setInitialFilters,
- refresh,
-})(withRouter((FunnelDetails)))
diff --git a/frontend/app/components/Funnels/FunnelGraph/FunnelGraph.js b/frontend/app/components/Funnels/FunnelGraph/FunnelGraph.js
deleted file mode 100644
index 221a59e8f..000000000
--- a/frontend/app/components/Funnels/FunnelGraph/FunnelGraph.js
+++ /dev/null
@@ -1,303 +0,0 @@
-import React, { useState } from 'react';
-import { Icon, Tooltip as AppTooltip } from 'UI';
-import { numberCompact } from 'App/utils';
-import {
- BarChart,
- Bar,
- Cell,
- XAxis,
- YAxis,
- CartesianGrid,
- Tooltip,
- LabelList,
-
-} from 'recharts';
-import { connect } from 'react-redux';
-import { setActiveStages } from 'Duck/funnels';
-import { Styles } from '../../Dashboard/Widgets/common';
-import { numberWithCommas } from 'App/utils';
-import { truncate } from 'App/utils';
-
-const MIN_BAR_HEIGHT = 20;
-
-function CustomTick(props) {
- const { x, y, payload } = props;
- return (
-
-
- {payload.value}
-
-
- );
-}
-
-function FunnelGraph(props) {
- const { data, activeStages, funnelId, liveFilters } = props;
- const [activeIndex, setActiveIndex] = useState(activeStages);
-
- const renderPercentage = (props) => {
- const { x, y, width, height, value } = props;
- const radius = 10;
- const _x = x + width / 2 + 45;
-
- return (
-
-
-
- {numberCompact(value)}
-
-
- );
- };
-
- const renderCustomizedLabel = (props) => {
- const { x, y, width, height, value, textColor = '#fff' } = props;
- const radius = 10;
-
- if (value === 0) return;
-
- return (
-
-
- {numberCompact(value)}
-
-
- );
- };
-
- const handleClick = (data, index) => {
- if (activeStages.length === 1 && activeStages.includes(index)) {
- // selecting the same bar
- props.setActiveStages([], null);
- return;
- }
-
- if (activeStages.length === 2) {
- // already having two bars
- return;
- }
-
- // new selection
- const arr = activeStages.concat([index]);
- props.setActiveStages(arr.sort(), arr.length === 2 && liveFilters, funnelId);
- };
-
- const resetActiveSatges = () => {
- props.setActiveStages([], liveFilters, funnelId, true);
- };
-
- const renderDropLabel = ({ x, y, width, value }) => {
- if (value === 0) return;
- return (
-
- {value}
-
- );
- };
-
- const renderMainLabel = ({ x, y, width, value }) => {
- return (
-
- {numberWithCommas(value)}
-
- );
- };
-
- const CustomBar = (props) => {
- const { fill, x, y, width, height, sessionsCount, index, dropDueToIssues } = props;
- const yp = sessionsCount < MIN_BAR_HEIGHT ? MIN_BAR_HEIGHT - 1 : dropDueToIssues;
- const tmp = (height <= 20 ? 20 : height) - (TEMP[index].height > 20 ? 0 : TEMP[index].height);
- return (
-
- );
- };
- const MainBar = (props) => {
- const {
- fill,
- x,
- y,
- width,
- height,
- sessionsCount,
- index,
- dropDueToIssues,
- hasSelection = false,
- } = props;
- const yp = sessionsCount < MIN_BAR_HEIGHT ? MIN_BAR_HEIGHT - 1 : dropDueToIssues;
-
- TEMP[index] = { height, y };
-
- return (
-
- );
- };
-
- const renderDropPct = (props) => {
- // TODO
- const { fill, x, y, width, height, value, totalBars } = props;
- const barW = x + 730 / totalBars / 2;
-
- return (
-
- );
- };
-
- const CustomTooltip = (props) => {
- const { payload } = props;
- if (payload.length === 0) return null;
- const { value, headerText } = payload[0].payload;
-
- // const value = payload[0].payload.value;
- if (!value) return null;
- return (
-
-
{headerText}
- {value.map((i) => (
-
{truncate(i, 30)}
- ))}
-
- );
- };
- // const CustomTooltip = ({ active, payload, msg = '' }) => {
- // return (
- //
- // );
- // };
-
- const TEMP = {};
-
- return (
-
- {activeStages.length === 2 && (
-
- )}
-
-
- {/* {activeStages.length < 2 && 0 ? 'Select one more event.' : 'Select any two events to analyze in depth.'} />} />} */}
-
-
- }
- cursor="pointer"
- minPointSize={MIN_BAR_HEIGHT}
- background={false}
- >
-
- {data.map((entry, index) => {
- const selected =
- activeStages.includes(index) || (index > activeStages[0] && index < activeStages[1]);
- const opacity = activeStages.length > 0 && !selected ? 0.4 : 1;
- return (
- |
- );
- })}
-
-
- }
- minPointSize={MIN_BAR_HEIGHT}
- >
-
- {data.map((entry, index) => {
- const selected =
- activeStages.includes(index) || (index > activeStages[0] && index < activeStages[1]);
- const opacity = activeStages.length > 0 && !selected ? 0.4 : 1;
- return (
- |
- );
- })}
-
-
- }
- xAxisId={0}
- />
- {/* '"' + val + '"'}
- /> */}
- Styles.tickFormatter(val)}
- />
-
-
- );
-}
-
-export default connect(
- (state) => ({
- activeStages: state.getIn(['funnels', 'activeStages']).toJS(),
- liveFilters: state.getIn(['funnelFilters', 'appliedFilter']),
- }),
- { setActiveStages }
-)(FunnelGraph);
diff --git a/frontend/app/components/Funnels/FunnelGraph/index.js b/frontend/app/components/Funnels/FunnelGraph/index.js
deleted file mode 100644
index 990d34099..000000000
--- a/frontend/app/components/Funnels/FunnelGraph/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FunnelGraph'
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelHeader/FunnelDropdown.js b/frontend/app/components/Funnels/FunnelHeader/FunnelDropdown.js
deleted file mode 100644
index a5b3bf445..000000000
--- a/frontend/app/components/Funnels/FunnelHeader/FunnelDropdown.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react'
-import { connect } from 'react-redux'
-import { withRouter } from 'react-router'
-import { Dropdown } from 'UI'
-import { funnel as funnelRoute, withSiteId } from 'App/routes';
-
-function FunnelDropdown(props) {
- const { options, funnel } = props;
-
- const writeOption = (e, { name, value }) => {
- const { siteId, history } = props;
- history.push(withSiteId(funnelRoute(parseInt(value)), siteId));
- }
-
- return (
-
-
-
- )
-}
-
-export default connect((state, props) => ({
- funnels: state.getIn(['funnels', 'list']),
- funnel: state.getIn(['funnels', 'instance']),
- siteId: state.getIn([ 'site', 'siteId' ]),
-}), { })(withRouter(FunnelDropdown))
diff --git a/frontend/app/components/Funnels/FunnelHeader/FunnelHeader.js b/frontend/app/components/Funnels/FunnelHeader/FunnelHeader.js
deleted file mode 100644
index 58e64d295..000000000
--- a/frontend/app/components/Funnels/FunnelHeader/FunnelHeader.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import React, { useState } from 'react';
-import { Icon, BackLink, IconButton, Dropdown, Tooltip, TextEllipsis, Button } from 'UI';
-import {
- remove as deleteFunnel,
- fetch,
- fetchInsights,
- fetchIssuesFiltered,
- fetchSessionsFiltered,
-} from 'Duck/funnels';
-import { editFilter, editFunnelFilter, refresh } from 'Duck/funnels';
-import DateRange from 'Shared/DateRange';
-import { connect } from 'react-redux';
-import { confirm } from 'UI';
-import FunnelSaveModal from 'Components/Funnels/FunnelSaveModal';
-import stl from './funnelHeader.module.css';
-
-const Info = ({ label = '', value = '', className = 'mx-4' }) => {
- return (
-
- {label}
- {value}
-
- );
-};
-
-const FunnelHeader = (props) => {
- const {
- funnel,
- insights,
- funnels,
- onBack,
- funnelId,
- showFilters = false,
- funnelFilters,
- renameHandler,
- } = props;
- const [showSaveModal, setShowSaveModal] = useState(false);
-
- const writeOption = (e, { name, value }) => {
- props.redirect(value);
- props.fetch(value).then(() => props.refresh(value));
- };
-
- const deleteFunnel = async (e, funnel) => {
- e.preventDefault();
- e.stopPropagation();
-
- if (
- await confirm({
- header: 'Delete Funnel',
- confirmButton: 'Delete',
- confirmation: `Are you sure you want to permanently delete "${funnel.name}"?`,
- })
- ) {
- props.deleteFunnel(funnel.funnelId).then(props.onBack);
- } else {
- }
- };
-
- const onDateChange = (e) => {
- props.editFunnelFilter(e, funnelId);
- };
-
- const options = funnels.map(({ funnelId, name }) => ({ text: name, value: funnelId })).toJS();
- const selectedFunnel = funnels.filter((i) => i.funnelId === parseInt(funnelId)).first() || {};
- const eventsCount = funnel.filter.filters.filter((i) => i.isEvent).size;
-
- return (
-
-
-
-
setShowSaveModal(false)} />
-
-
-
-
- }
- options={options}
- className={stl.dropdown}
- name="funnel"
- value={parseInt(funnelId)}
- // icon={null}
- onChange={writeOption}
- selectOnBlur={false}
- icon={
-
- }
- />
-
- -
-
-
-
-
-
-
-
- setShowSaveModal(true)} />
-
-
- deleteFunnel(e, funnel)}
- className="ml-2 mr-2"
- />
-
-
-
-
-
-
- );
-};
-
-export default connect(
- (state) => ({
- funnelFilters: state.getIn(['funnels', 'funnelFilters']).toJS(),
- funnel: state.getIn(['funnels', 'instance']),
- }),
- {
- editFilter,
- editFunnelFilter,
- deleteFunnel,
- fetch,
- fetchInsights,
- fetchIssuesFiltered,
- fetchSessionsFiltered,
- refresh,
- }
-)(FunnelHeader);
diff --git a/frontend/app/components/Funnels/FunnelHeader/funnelHeader.module.css b/frontend/app/components/Funnels/FunnelHeader/funnelHeader.module.css
deleted file mode 100644
index 7ab834b76..000000000
--- a/frontend/app/components/Funnels/FunnelHeader/funnelHeader.module.css
+++ /dev/null
@@ -1,30 +0,0 @@
-.dropdown {
- display: flex !important;
- align-items: center;
- padding: 0 20px;
- border-radius: 0;
- border-radius: 0;
- color: $gray-darkest;
- font-weight: 500;
- height: 54px;
- padding-right: 20px;
- border-right: solid thin #eee;
- border-bottom-left-radius: 3px;
- border-top-left-radius: 3px;
- &:hover {
- background-color: $gray-lightest;
- }
-}
-
-.dropdownTrigger {
- padding: 4px 8px;
- border-radius: 3px;
- &:hover {
- background-color: $gray-light;
- }
-}
-
-.dropdownIcon {
- margin-top: 4px;
- margin-left: 6px;
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelHeader/index.js b/frontend/app/components/Funnels/FunnelHeader/index.js
deleted file mode 100644
index a5efa97af..000000000
--- a/frontend/app/components/Funnels/FunnelHeader/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FunnelHeader';
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.js b/frontend/app/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.js
deleted file mode 100644
index 77017e4ac..000000000
--- a/frontend/app/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { useEffect } from 'react'
-import IssueItem from 'Components/Funnels/IssueItem'
-import FunnelSessionList from 'Components/Funnels/FunnelSessionList'
-import { connect } from 'react-redux'
-import { withRouter } from 'react-router'
-import { fetchIssue, setNavRef, resetIssue } from 'Duck/funnels'
-import { funnel as funnelRoute, withSiteId } from 'App/routes'
-import { Loader } from 'UI'
-
-function FunnelIssueDetails(props) {
- const { issue, issueId, funnelId, loading = false } = props;
-
- useEffect(() => {
- props.fetchIssue(funnelId, issueId)
-
- return () => {
- props.resetIssue();
- }
- }, [issueId])
-
- const onBack = () => {
- const { siteId, history } = props;
- history.push(withSiteId(funnelRoute(parseInt(funnelId)), siteId));
- }
-
- return (
-
- )
-}
-
-export default connect((state, props) => ({
- loading: state.getIn(['funnels', 'fetchIssueRequest', 'loading']),
- issue: state.getIn(['funnels', 'issue']),
- issueId: props.match.params.issueId,
- funnelId: props.match.params.funnelId,
- siteId: state.getIn([ 'site', 'siteId' ]),
-}), { fetchIssue, setNavRef, resetIssue })(withRouter(FunnelIssueDetails))
diff --git a/frontend/app/components/Funnels/FunnelIssueDetails/index.js b/frontend/app/components/Funnels/FunnelIssueDetails/index.js
index 3ac32a034..0c66aec5b 100644
--- a/frontend/app/components/Funnels/FunnelIssueDetails/index.js
+++ b/frontend/app/components/Funnels/FunnelIssueDetails/index.js
@@ -1 +1 @@
-export { default } from './FunnelIssueDetails'
\ No newline at end of file
+//export { default } from './FunnelIssueDetails'
diff --git a/frontend/app/components/Funnels/FunnelIssues/FunnelIssues.js b/frontend/app/components/Funnels/FunnelIssues/FunnelIssues.js
deleted file mode 100644
index 3a6070afe..000000000
--- a/frontend/app/components/Funnels/FunnelIssues/FunnelIssues.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import React, { useState } from 'react'
-import { connect } from 'react-redux'
-import { fetchIssues, fetchIssuesFiltered } from 'Duck/funnels'
-import { LoadMoreButton, NoContent } from 'UI'
-import FunnelIssuesHeader from '../FunnelIssuesHeader'
-import IssueItem from '../IssueItem';
-import { funnelIssue as funnelIssueRoute, withSiteId } from 'App/routes'
-import { withRouter } from 'react-router'
-import IssueFilter from '../IssueFilter';
-import SortDropdown from './SortDropdown';
-import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
-
-const PER_PAGE = 10;
-
-function FunnelIssues(props) {
- const {
- funnel, list, loading = false,
- criticalIssuesCount, issueFilters, sort
- } = props;
-
- const [showPages, setShowPages] = useState(1)
-
- const addPage = () => setShowPages(showPages + 1);
-
- const onClick = ({ issueId }) => {
- const { siteId, history } = props;
- history.push(withSiteId(funnelIssueRoute(funnel.funnelId, issueId), siteId));
- }
-
- let filteredList = issueFilters.size > 0 ? list.filter(item => issueFilters.includes(item.type)) : list;
- filteredList = sort.sort ? filteredList.sortBy(i => i[sort.sort]) : filteredList;
- filteredList = sort.order === 'desc' ? filteredList.reverse() : filteredList;
- const displayedCount = Math.min(showPages * PER_PAGE, filteredList.size);
-
- return (
-
-
-
-
-
- No Issues Found!
-
- }
- subtext="Please try changing your search parameters."
- // animatedIcon="no-results"
- show={ !loading && filteredList.size === 0}
- >
- { filteredList.take(displayedCount).map(issue => (
-
- onClick(issue)}
- />
-
- ))}
-
-
-
-
- )
-}
-
-export default connect(state => ({
- list: state.getIn(['funnels', 'issues']),
- criticalIssuesCount: state.getIn(['funnels', 'criticalIssuesCount']),
- loading: state.getIn(['funnels', 'fetchIssuesRequest', 'loading']),
- siteId: state.getIn([ 'site', 'siteId' ]),
- funnel: state.getIn(['funnels', 'instance']),
- activeStages: state.getIn(['funnels', 'activeStages']),
- funnelFilters: state.getIn(['funnels', 'funnelFilters']),
- liveFilters: state.getIn(['funnelFilters', 'appliedFilter']),
- issueFilters: state.getIn(['funnels', 'issueFilters', 'filters']),
- sort: state.getIn(['funnels', 'issueFilters', 'sort']),
-}), { fetchIssues, fetchIssuesFiltered })(withRouter(FunnelIssues))
diff --git a/frontend/app/components/Funnels/FunnelIssues/SortDropdown/SortDropdown.js b/frontend/app/components/Funnels/FunnelIssues/SortDropdown/SortDropdown.js
deleted file mode 100644
index a9d22f2f0..000000000
--- a/frontend/app/components/Funnels/FunnelIssues/SortDropdown/SortDropdown.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import Select from 'Shared/Select'
-import { sort } from 'Duck/sessions';
-import { applyIssueFilter } from 'Duck/funnels';
-
-const sortOptionsMap = {
- 'afectedUsers-desc': 'Affected Users (High)',
- 'afectedUsers-asc': 'Affected Users (Low)',
- 'conversionImpact-desc': 'Conversion Impact (High)',
- 'conversionImpact-asc': 'Conversion Impact (Low)',
- 'lostConversions-desc': 'Lost Conversions (High)',
- 'lostConversions-asc': 'Lost Conversions (Low)',
-};
-
-const sortOptions = Object.entries(sortOptionsMap)
- .map(([ value, label ]) => ({ value, label }));
-
-@connect(state => ({
- sorts: state.getIn(['funnels', 'issueFilters', 'sort'])
-}), { sort, applyIssueFilter })
-export default class SortDropdown extends React.PureComponent {
- state = { value: null }
- sort = ({ value }) => {
- this.setState({ value: value })
- const [ sort, order ] = value.split('-');
- const sign = order === 'desc' ? -1 : 1;
- this.props.applyIssueFilter({ sort: { order, sort } });
-
- this.props.sort(sort, sign)
- setTimeout(() => this.props.sort(sort, sign), 3000); //AAA
- }
-
- render() {
- const { sorts } = this.props;
-
- return (
-
- );
- }
-}
diff --git a/frontend/app/components/Funnels/FunnelIssues/SortDropdown/index.js b/frontend/app/components/Funnels/FunnelIssues/SortDropdown/index.js
deleted file mode 100644
index 9018d24ac..000000000
--- a/frontend/app/components/Funnels/FunnelIssues/SortDropdown/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './SortDropdown';
diff --git a/frontend/app/components/Funnels/FunnelIssues/SortDropdown/sortDropdown.module.css b/frontend/app/components/Funnels/FunnelIssues/SortDropdown/sortDropdown.module.css
deleted file mode 100644
index 87e26bc68..000000000
--- a/frontend/app/components/Funnels/FunnelIssues/SortDropdown/sortDropdown.module.css
+++ /dev/null
@@ -1,23 +0,0 @@
-.dropdown {
- display: flex !important;
- padding: 4px 6px;
- border-radius: 3px;
- color: $gray-darkest;
- font-weight: 500;
- &:hover {
- background-color: $gray-light;
- }
-}
-
-.dropdownTrigger {
- padding: 4px 8px;
- border-radius: 3px;
- &:hover {
- background-color: $gray-light;
- }
-}
-
-.dropdownIcon {
- margin-top: 2px;
- margin-left: 3px;
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelIssues/index.js b/frontend/app/components/Funnels/FunnelIssues/index.js
deleted file mode 100644
index 051a19336..000000000
--- a/frontend/app/components/Funnels/FunnelIssues/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FunnelIssues'
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelIssuesHeader/DateRange.js b/frontend/app/components/Funnels/FunnelIssuesHeader/DateRange.js
deleted file mode 100644
index 4780f8c75..000000000
--- a/frontend/app/components/Funnels/FunnelIssuesHeader/DateRange.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import { applyFilter, fetchList } from 'Duck/filters';
-import { fetchList as fetchFunnelsList } from 'Duck/funnels';
-import DateRangeDropdown from 'Shared/DateRangeDropdown';
-
-@connect(state => ({
- rangeValue: state.getIn([ 'filters', 'appliedFilter', 'rangeValue' ]),
- startDate: state.getIn([ 'filters', 'appliedFilter', 'startDate' ]),
- endDate: state.getIn([ 'filters', 'appliedFilter', 'endDate' ]),
-}), {
- applyFilter, fetchList, fetchFunnelsList
-})
-export default class DateRange extends React.PureComponent {
- render() {
- const { startDate, endDate, rangeValue, className } = this.props;
- return (
-
- );
- }
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelIssuesHeader/FunnelIssuesHeader.js b/frontend/app/components/Funnels/FunnelIssuesHeader/FunnelIssuesHeader.js
index 76688e6f0..a3588eb06 100644
--- a/frontend/app/components/Funnels/FunnelIssuesHeader/FunnelIssuesHeader.js
+++ b/frontend/app/components/Funnels/FunnelIssuesHeader/FunnelIssuesHeader.js
@@ -1,15 +1,15 @@
import React from 'react'
import { connect } from 'react-redux';
-function FunnelIssuesHeader({ criticalIssuesCount, filters }) {
+function FunnelIssuesHeader({ criticalIssuesCount, filters }) {
return (
-
+
Significant issues
-
in this funnel
-
+
in this funnel
+
)
}
diff --git a/frontend/app/components/Funnels/FunnelItem/FunnelItem.js__ b/frontend/app/components/Funnels/FunnelItem/FunnelItem.js__
deleted file mode 100644
index 3cb024a69..000000000
--- a/frontend/app/components/Funnels/FunnelItem/FunnelItem.js__
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react'
-import FunnelGraphSmall from '../FunnelGraphSmall'
-
-function FunnelItem({ funnel, onClick = () => null }) {
- return (
-
-
-
-
-
-
-
{funnel.name}
-
-
{funnel.stepsCount} Steps
-
{funnel.sessionsCount} Sessions
-
-
-
-
-
{funnel.criticalIssuesCount}
-
Critical Issues
-
-
-
-
{funnel.missedConversions}%
-
Missed Conversions
-
-
- )
-}
-
-export default FunnelItem
diff --git a/frontend/app/components/Funnels/FunnelSaveModal/FunnelSaveModal.js b/frontend/app/components/Funnels/FunnelSaveModal/FunnelSaveModal.js
deleted file mode 100644
index e0d43d1d7..000000000
--- a/frontend/app/components/Funnels/FunnelSaveModal/FunnelSaveModal.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import { Button, Modal, Form, Icon, Checkbox, Input } from 'UI';
-import styles from './funnelSaveModal.module.css';
-import { edit, save, fetchList as fetchFunnelsList } from 'Duck/funnels';
-
-@connect(
- (state) => ({
- filter: state.getIn(['search', 'instance']),
- funnel: state.getIn(['funnels', 'instance']),
- loading:
- state.getIn(['funnels', 'saveRequest', 'loading']) ||
- state.getIn(['funnels', 'updateRequest', 'loading']),
- }),
- { edit, save, fetchFunnelsList }
-)
-export default class FunnelSaveModal extends React.PureComponent {
- state = { name: 'Untitled', isPublic: false };
- static getDerivedStateFromProps(props) {
- if (!props.show) {
- return {
- name: props.funnel.name || 'Untitled',
- isPublic: props.funnel.isPublic,
- };
- }
- return null;
- }
-
- onNameChange = ({ target: { value } }) => {
- this.props.edit({ name: value });
- };
-
- onChangeOption = (e, { checked, name }) => this.props.edit({ [name]: checked });
-
- onSave = () => {
- const { funnel, filter } = this.props;
- if (funnel.name && funnel.name.trim() === '') return;
- this.props.save(funnel).then(
- function () {
- this.props.fetchFunnelsList();
- this.props.closeHandler();
- }.bind(this)
- );
- };
-
- render() {
- const { show, closeHandler, loading, funnel } = this.props;
-
- return (
-
-
- {'Save Funnel'}
-
-
-
-
-
-
-
-
-
-
-
-
-
this.props.edit({ isPublic: !funnel.isPublic })}
- >
-
- Team Visible
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
diff --git a/frontend/app/components/Funnels/FunnelSaveModal/funnelSaveModal.module.css b/frontend/app/components/Funnels/FunnelSaveModal/funnelSaveModal.module.css
deleted file mode 100644
index ed2600745..000000000
--- a/frontend/app/components/Funnels/FunnelSaveModal/funnelSaveModal.module.css
+++ /dev/null
@@ -1,15 +0,0 @@
-@import 'mixins.css';
-
-.modalHeader {
- display: flex !important;
- align-items: center;
- justify-content: space-between;
-}
-
-.cancelButton {
- @mixin plainButton;
-}
-
-.applyButton {
- @mixin basicButton;
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelSaveModal/index.js b/frontend/app/components/Funnels/FunnelSaveModal/index.js
deleted file mode 100644
index 1265b5b10..000000000
--- a/frontend/app/components/Funnels/FunnelSaveModal/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FunnelSaveModal'
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelSessionList/FunnelSessionList.js b/frontend/app/components/Funnels/FunnelSessionList/FunnelSessionList.js
deleted file mode 100644
index c7aca3149..000000000
--- a/frontend/app/components/Funnels/FunnelSessionList/FunnelSessionList.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import React, { useState, useEffect } from 'react'
-import { connect } from 'react-redux'
-import SessionItem from 'Shared/SessionItem'
-import { fetchSessions, fetchSessionsFiltered } from 'Duck/funnels'
-import { setFunnelPage } from 'Duck/sessions'
-import { LoadMoreButton, NoContent } from 'UI'
-import FunnelSessionsHeader from '../FunnelSessionsHeader'
-import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
-
-const PER_PAGE = 10;
-
-function FunnelSessionList(props) {
- const { funnelId, issueId, list, sessionsTotal, sessionsSort, inDetails = false } = props;
-
- const [showPages, setShowPages] = useState(1)
- const displayedCount = Math.min(showPages * PER_PAGE, list.size);
-
- const addPage = () => setShowPages(showPages + 1);
-
- useEffect(() => {
- props.setFunnelPage({
- funnelId,
- issueId
- })
- }, [])
-
- return (
-
-
-
-
-
- No recordings found!
-
- }
- subtext="Please try changing your search parameters."
- // animatedIcon="no-results"
- show={ list.size === 0}
- >
- { list.take(displayedCount).map(session => (
-
- ))}
-
-
-
-
- )
-}
-
-export default connect(state => ({
- list: state.getIn(['funnels', 'sessions']),
- sessionsTotal: state.getIn(['funnels', 'sessionsTotal']),
- funnel: state.getIn(['funnels', 'instance']),
- activeStages: state.getIn(['funnels', 'activeStages']).toJS(),
- liveFilters: state.getIn(['funnelFilters', 'appliedFilter']),
- funnelFilters: state.getIn(['funnels', 'funnelFilters']),
- sessionsSort: state.getIn(['funnels', 'sessionsSort']),
-}), { fetchSessions, fetchSessionsFiltered, setFunnelPage })(FunnelSessionList)
diff --git a/frontend/app/components/Funnels/FunnelSessionList/index.js b/frontend/app/components/Funnels/FunnelSessionList/index.js
deleted file mode 100644
index 45c8e472e..000000000
--- a/frontend/app/components/Funnels/FunnelSessionList/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FunnelSessionList'
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelSessionsHeader/DateRange.js b/frontend/app/components/Funnels/FunnelSessionsHeader/DateRange.js
deleted file mode 100644
index c532f5af6..000000000
--- a/frontend/app/components/Funnels/FunnelSessionsHeader/DateRange.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import { applyFilter, fetchList } from 'Duck/filters';
-import { fetchList as fetchFunnelsList } from 'Duck/funnels';
-import DateRangeDropdown from 'Shared/DateRangeDropdown';
-
-@connect(state => ({
- rangeValue: state.getIn([ 'filters', 'appliedFilter', 'rangeValue' ]),
- startDate: state.getIn([ 'filters', 'appliedFilter', 'startDate' ]),
- endDate: state.getIn([ 'filters', 'appliedFilter', 'endDate' ]),
-}), {
- applyFilter, fetchList, fetchFunnelsList
-})
-export default class DateRange extends React.PureComponent {
- render() {
- const { startDate, endDate, rangeValue, className } = this.props;
- return (
-
- );
- }
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/SortDropdown.js b/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/SortDropdown.js
deleted file mode 100644
index b865a6b57..000000000
--- a/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/SortDropdown.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import Select from 'Shared/Select';
-import { setSessionsSort as sort } from 'Duck/funnels';
-import { setSessionsSort } from 'Duck/funnels';
-
-@connect(state => ({
- sessionsSort: state.getIn(['funnels','sessionsSort'])
-}), { sort, setSessionsSort })
-export default class SortDropdown extends React.PureComponent {
- state = { value: null }
- sort = ({ value }) => {
- this.setState({ value: value })
- const [ sort, order ] = value.split('-');
- const sign = order === 'desc' ? -1 : 1;
- setTimeout(() => this.props.sort(sort, sign), 100);
- }
-
- render() {
- const { options, issuesSort } = this.props;
- return (
-
- );
- }
-}
diff --git a/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/index.js b/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/index.js
deleted file mode 100644
index 9018d24ac..000000000
--- a/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './SortDropdown';
diff --git a/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/sortDropdown.module.css b/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/sortDropdown.module.css
deleted file mode 100644
index 87e26bc68..000000000
--- a/frontend/app/components/Funnels/FunnelSessionsHeader/SortDropdown/sortDropdown.module.css
+++ /dev/null
@@ -1,23 +0,0 @@
-.dropdown {
- display: flex !important;
- padding: 4px 6px;
- border-radius: 3px;
- color: $gray-darkest;
- font-weight: 500;
- &:hover {
- background-color: $gray-light;
- }
-}
-
-.dropdownTrigger {
- padding: 4px 8px;
- border-radius: 3px;
- &:hover {
- background-color: $gray-light;
- }
-}
-
-.dropdownIcon {
- margin-top: 2px;
- margin-left: 3px;
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/IssueFilter/IssueFilter.js b/frontend/app/components/Funnels/IssueFilter/IssueFilter.js
deleted file mode 100644
index 3996b9939..000000000
--- a/frontend/app/components/Funnels/IssueFilter/IssueFilter.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import React from 'react'
-import { connect } from 'react-redux';
-import { Icon, Dropdown, TagBadge } from 'UI'
-import { applyIssueFilter, removeIssueFilter } from 'Duck/funnels';
-import cn from 'classnames';
-import stl from './issueFilter.module.css';
-import { List } from 'immutable';
-
-function IssueFilter(props) {
- const { filters, issueTypes, issueTypesMap } = props;
-
- const onChangeFilter = (e, { name, value }) => {
- const errors = filters.toJS();
- errors.push(value);
- props.applyIssueFilter({ filters: List(errors) });
- }
-
- return (
-
-
-
- Filter
-
- }
- options={ issueTypes.filter(i => !filters.includes(i.value)) }
- name="change"
- icon={null}
- onChange={onChangeFilter}
- basic
- scrolling
- selectOnBlur={false}
- />
-
- {filters.map(err => (
- props.removeIssueFilter(err) }
- outline
- />
- ))}
-
-
- )
-}
-
-export default connect(state => ({
- filters: state.getIn(['funnels', 'issueFilters', 'filters']),
- issueTypes: state.getIn(['funnels', 'issueTypes']).toJS(),
- issueTypesMap: state.getIn(['funnels', 'issueTypesMap']),
-}), { applyIssueFilter, removeIssueFilter })(IssueFilter)
diff --git a/frontend/app/components/Funnels/IssueFilter/index.js b/frontend/app/components/Funnels/IssueFilter/index.js
deleted file mode 100644
index ac69d0f3e..000000000
--- a/frontend/app/components/Funnels/IssueFilter/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './IssueFilter'
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/IssueFilter/issueFilter.module.css b/frontend/app/components/Funnels/IssueFilter/issueFilter.module.css
deleted file mode 100644
index 575c3d319..000000000
--- a/frontend/app/components/Funnels/IssueFilter/issueFilter.module.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.filterBtn {
- border: dashed 1px $teal !important;
- color: $teal;
- &:hover {
- background-color: $active-blue;
- }
-}
\ No newline at end of file
diff --git a/frontend/app/components/Funnels/IssuesEmptyMessage/IssuesEmptyMessage.js b/frontend/app/components/Funnels/IssuesEmptyMessage/IssuesEmptyMessage.js
deleted file mode 100644
index f1fbcc453..000000000
--- a/frontend/app/components/Funnels/IssuesEmptyMessage/IssuesEmptyMessage.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react'
-import { Button } from 'UI'
-import { addEvent } from 'Duck/funnelFilters'
-import Event, { TYPES } from 'Types/filter/event';
-import { connect } from 'react-redux';
-
-function IssuesEmptyMessage(props) {
- const { children, show } = props;
- const createHandler = () => {
- props.addEvent(Event({ type: TYPES.LOCATION, key: TYPES.LOCATION } ))
- props.onAddEvent();
- }
- return (show ? (
-
-
-
See what's impacting conversions
-
Add events to your funnel to identify potential issues that are causing conversion loss.
-
-
-

-
- ) : children
- )
-}
-
-export default connect(null, { addEvent })(IssuesEmptyMessage)
diff --git a/frontend/app/components/Funnels/IssuesEmptyMessage/index.js b/frontend/app/components/Funnels/IssuesEmptyMessage/index.js
deleted file mode 100644
index fccfd2545..000000000
--- a/frontend/app/components/Funnels/IssuesEmptyMessage/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './IssuesEmptyMessage'
\ No newline at end of file
diff --git a/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx b/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx
deleted file mode 100644
index 19a3b7ceb..000000000
--- a/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React from 'react';
-import FilterList from 'Shared/Filters/FilterList';
-import FilterSelection from 'Shared/Filters/FilterSelection';
-import { connect } from 'react-redux';
-import { IconButton } from 'UI';
-import { editFilter, addFilter } from 'Duck/funnels';
-import UpdateFunnelButton from 'Shared/UpdateFunnelButton';
-
-interface Props {
- appliedFilter: any;
- editFilter: typeof editFilter;
- addFilter: typeof addFilter;
-}
-function FunnelSearch(props: Props) {
- const { appliedFilter } = props;
- const hasEvents = appliedFilter.filters.filter(i => i.isEvent).size > 0;
- const hasFilters = appliedFilter.filters.filter(i => !i.isEvent).size > 0;
-
- const onAddFilter = (filter) => {
- props.addFilter(filter);
- }
-
- const onUpdateFilter = (filterIndex, filter) => {
- const newFilters = appliedFilter.filters.map((_filter, i) => {
- if (i === filterIndex) {
- return filter;
- } else {
- return _filter;
- }
- });
-
- props.editFilter({
- ...appliedFilter,
- filters: newFilters,
- });
- }
-
- const onRemoveFilter = (filterIndex) => {
- const newFilters = appliedFilter.filters.filter((_filter, i) => {
- return i !== filterIndex;
- });
-
- props.editFilter({
- filters: newFilters,
- });
- }
-
- const onChangeEventsOrder = (e, { name, value }) => {
- props.editFilter({
- eventsOrder: value,
- });
- }
-
- return (
-
- );
-}
-
-export default connect(state => ({
- appliedFilter: state.getIn([ 'funnels', 'instance', 'filter' ]),
-}), { editFilter, addFilter })(FunnelSearch);
\ No newline at end of file
diff --git a/frontend/app/components/shared/FunnelSearch/index.ts b/frontend/app/components/shared/FunnelSearch/index.ts
deleted file mode 100644
index 2db683671..000000000
--- a/frontend/app/components/shared/FunnelSearch/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './FunnelSearch';
\ No newline at end of file
diff --git a/frontend/app/components/shared/SaveFunnelButton/SaveFunnelButton.tsx b/frontend/app/components/shared/SaveFunnelButton/SaveFunnelButton.tsx
deleted file mode 100644
index bb5b9425c..000000000
--- a/frontend/app/components/shared/SaveFunnelButton/SaveFunnelButton.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React, { useState } from 'react';
-import { Button } from 'UI';
-import FunnelSaveModal from 'App/components/Funnels/FunnelSaveModal';
-import { connect } from 'react-redux';
-import { init } from 'Duck/funnels';
-interface Props {
- filter: any
- init: (instance: any) => void
-}
-function SaveFunnelButton(props: Props) {
- const [showModal, setshowModal] = useState(false)
-
- const handleClick = () => {
- props.init({ filter: props.filter })
- setshowModal(true)
- }
- return (
-
-
-
- setshowModal(false)}
- />
-
- )
-}
-
-export default connect(state => ({
- filter: state.getIn(['search', 'instance']),
-}), { init })(SaveFunnelButton);
\ No newline at end of file
diff --git a/frontend/app/components/shared/SaveFunnelButton/index.ts b/frontend/app/components/shared/SaveFunnelButton/index.ts
deleted file mode 100644
index 246df92ff..000000000
--- a/frontend/app/components/shared/SaveFunnelButton/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './SaveFunnelButton';
\ No newline at end of file
diff --git a/frontend/app/components/shared/UpdateFunnelButton/UpdateFunnelButton.tsx b/frontend/app/components/shared/UpdateFunnelButton/UpdateFunnelButton.tsx
deleted file mode 100644
index 9f7a2eb06..000000000
--- a/frontend/app/components/shared/UpdateFunnelButton/UpdateFunnelButton.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import { IconButton } from 'UI';
-import { connect } from 'react-redux';
-import { save } from 'Duck/funnels';
-
-interface Props {
- save: typeof save;
- loading: boolean;
-}
-function UpdateFunnelButton(props: Props) {
- const { loading } = props;
- return (
-
- props.save()} primaryText label="UPDATE FUNNEL" icon="funnel"
- />
-
- )
-}
-
-export default connect(state => ({
- loading: state.getIn(['funnels', 'saveRequest', 'loading']) ||
- state.getIn(['funnels', 'updateRequest', 'loading']),
-}), { save })(UpdateFunnelButton);
\ No newline at end of file
diff --git a/frontend/app/components/shared/UpdateFunnelButton/index.ts b/frontend/app/components/shared/UpdateFunnelButton/index.ts
deleted file mode 100644
index 7638c11c0..000000000
--- a/frontend/app/components/shared/UpdateFunnelButton/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './UpdateFunnelButton';
\ No newline at end of file
diff --git a/frontend/app/duck/funnelFilters.js b/frontend/app/duck/funnelFilters.js_
similarity index 100%
rename from frontend/app/duck/funnelFilters.js
rename to frontend/app/duck/funnelFilters.js_
diff --git a/frontend/app/duck/funnels.js b/frontend/app/duck/funnels.js
deleted file mode 100644
index dfa567618..000000000
--- a/frontend/app/duck/funnels.js
+++ /dev/null
@@ -1,451 +0,0 @@
-import { List, Map } from 'immutable';
-import Funnel from 'Types/funnel';
-import FunnelIssue from 'Types/funnelIssue';
-import Session from 'Types/session';
-import { fetchListType, fetchType, saveType, editType, initType, removeType } from './funcTools/crud/types';
-import { createItemInListUpdater, mergeReducers, success, array } from './funcTools/tools';
-import { createRequestReducer } from './funcTools/request';
-import { getDateRangeFromValue } from 'App/dateRange';
-import { LAST_7_DAYS } from 'Types/app/period';
-import { filterMap, checkFilterValue, hasFilterApplied } from './search';
-
-const name = 'funnel';
-const idKey = 'funnelId';
-const itemInListUpdater = createItemInListUpdater(idKey);
-
-const FETCH_LIST = fetchListType('funnel/FETCH_LIST');
-const FETCH_ISSUES = fetchType('funnel/FETCH_ISSUES');
-const FETCH_ISSUE = fetchType('funnel/FETCH_ISSUE');
-const FETCH_ISSUE_TYPES = fetchType('funnel/FETCH_ISSUE_TYPES');
-const FETCH_SESSIONS = fetchType('funnel/FETCH_SESSIONS');
-const FETCH = fetchType('funnel/FETCH');
-const FETCH_INSIGHTS = fetchType('funnel/FETCH_INSIGHTS');
-const SAVE = saveType('funnel/SAVE');
-const UPDATE = saveType('funnel/UPDATE');
-const EDIT = editType('funnel/EDIT');
-const EDIT_FILTER = `${name}/EDIT_FILTER`;
-const EDIT_FUNNEL_FILTER = `${name}/EDIT_FUNNEL_FILTER`;
-const REMOVE = removeType('funnel/REMOVE');
-const INIT = initType('funnel/INIT');
-const SET_NAV_REF = 'funnels/SET_NAV_REF'
-
-const RESET_FUNNEL = 'funnels/RESET_FUNNEL'
-const APPLY_FILTER = 'funnels/APPLY_FILTER'
-const APPLY_ISSUE_FILTER = 'funnels/APPLY_ISSUE_FILTER'
-const REMOVE_ISSUE_FILTER = 'funnels/REMOVE_ISSUE_FILTER'
-const SET_ACTIVE_STAGES = 'funnels/SET_ACTIVE_STAGES'
-const SET_SESSIONS_SORT = 'funnels/SET_SESSIONS_SORT'
-const BLINK = 'funnels/BLINK'
-
-const RESET_ISSUE = 'funnles/RESET_ISSUE'
-
-const FETCH_LIST_SUCCESS = success(FETCH_LIST);
-const FETCH_ISSUES_SUCCESS = success(FETCH_ISSUES);
-const FETCH_ISSUE_SUCCESS = success(FETCH_ISSUE);
-const FETCH_ISSUE_TYPES_SUCCESS = success(FETCH_ISSUE_TYPES);
-const FETCH_SESSIONS_SUCCESS = success(FETCH_SESSIONS);
-const FETCH_SUCCESS = success(FETCH);
-const FETCH_INSIGHTS_SUCCESS = success(FETCH_INSIGHTS);
-const SAVE_SUCCESS = success(SAVE);
-const UPDATE_SUCCESS = success(UPDATE);
-const REMOVE_SUCCESS = success(REMOVE);
-
-const range = getDateRangeFromValue(LAST_7_DAYS);
-const defaultDateFilters = {
- rangeValue: LAST_7_DAYS,
- startDate: range.start.ts,
- endDate: range.end.ts
-}
-
-const initialState = Map({
- list: List(),
- instance: Funnel(),
- insights: Funnel(),
- issues: List(),
- issue: FunnelIssue(),
- issuesTotal: 0,
- sessionsTotal: 0,
- sessions: List(),
- activeStages: List(),
- funnelFilters: Map(defaultDateFilters),
- sessionsSort: Map({ order: "desc", sort: "newest" }),
- issueFilters: Map({
- filters: List(),
- sort: { order: "desc", sort: "lostConversions" }
- }),
- sessionFilters: defaultDateFilters,
- navRef: null,
- issueTypes: List(),
- blink: true
-});
-
-const reducer = (state = initialState, action = {}) => {
- switch(action.type) {
- case BLINK:
- return state.set('blink', action.state);
- case EDIT:
- return state.mergeIn([ 'instance' ], action.instance);
- case EDIT_FILTER:
- return state.mergeIn([ 'instance', 'filter' ], action.instance);
- case EDIT_FUNNEL_FILTER:
- return state.mergeIn([ 'funnelFilters' ], action.instance);
- case INIT:
- return state.set('instance', Funnel(action.instance))
- case FETCH_LIST_SUCCESS:
- return state.set('list', List(action.data).map(Funnel))
- case FETCH_ISSUES_SUCCESS:
- return state
- .set('issues', List(action.data.issues.significant).map(FunnelIssue))
- .set('criticalIssuesCount', action.data.issues.criticalIssuesCount)
- case FETCH_SESSIONS_SUCCESS:
- return state
- .set('sessions', List(action.data.sessions).map(s => new Session(s)))
- .set('total', action.data.total)
- case FETCH_ISSUE_SUCCESS:
- return state
- .set('issue', FunnelIssue(action.data.issue))
- .set('sessions', List(action.data.sessions.sessions).map(s => new Session(s)))
- .set('sessionsTotal', action.data.sessions.total)
- case RESET_ISSUE:
- return state.set('isses', FunnelIssue())
- .set('sections', List())
- .set('sessionsTotal', 0);
- case FETCH_SUCCESS:
- const funnel = Funnel(action.data);
- return state.set('instance', funnel)
- case FETCH_ISSUE_TYPES_SUCCESS:
- const tmpMap = {};
- action.data.forEach(element => {
- tmpMap[element.type] = element.title
- });
- return state
- .set('issueTypes', List(action.data.map(({ type, title }) => ({ text: title, value: type }))))
- .set('issueTypesMap', tmpMap);
- case FETCH_INSIGHTS_SUCCESS:
- let stages = [];
- if (action.isRefresh) {
- const activeStages = state.get('activeStages');
- const oldInsights = state.get('insights');
- const lastStage = action.data.stages[action.data.stages.length - 1]
- const lastStageIndex = activeStages.toJS()[1];
- stages = oldInsights.stages.map((stage, i) => {
- stage.dropDueToIssues = lastStageIndex === i ? lastStage.dropDueToIssues : 0;
- return stage;
- });
- return state.set('insights', Funnel({ totalDropDueToIssues: action.data.totalDropDueToIssues, stages, activeStages: activeStages.toJS() }));
- } else {
- stages = action.data.stages.map((stage, i) => {
- stage.dropDueToIssues = 0;
- return stage;
- });
- return state.set('insights', Funnel({ ...action.data, stages }))
- }
- case SAVE_SUCCESS:
- case UPDATE_SUCCESS:
- return state.update('list', itemInListUpdater(CustomField(action.data)))
- case REMOVE_SUCCESS:
- return state.update('list', list => list.filter(item => item.index !== action.index));
- case APPLY_FILTER:
- return state.mergeIn([ action.filterType ], Array.isArray(action.filter) ? action.filter : Map(action.filter));
- case APPLY_ISSUE_FILTER:
- return state.mergeIn(['issueFilters'], action.filter)
- case REMOVE_ISSUE_FILTER:
- return state.updateIn(['issueFilters', 'filters'], list => list.filter(item => item !== action.errorType))
- case SET_ACTIVE_STAGES:
- return state.set('activeStages', List(action.stages))
- case SET_NAV_REF:
- return state.set('navRef', action.navRef);
- case SET_SESSIONS_SORT:
- const comparator = (s1, s2) => {
- let diff = s1[ action.sortKey ] - s2[ action.sortKey ];
- diff = diff === 0 ? s1.startedAt - s2.startedAt : diff;
- return action.sign * diff;
- };
- return state
- .update('sessions', list => list.sort(comparator))
- .set('sessionsSort', { sort: action.sort, sign: action.sign });
- case RESET_FUNNEL:
- return state
- .set('instance', Funnel())
- .set('activeStages', List())
- .set('issuesSort', Map({}))
- // .set('funnelFilters', Map(defaultDateFilters))
- .set('insights', Funnel())
- .set('issues', List())
- .set('sessions', List());
- default:
- return state;
- }
-}
-
-export const fetchList = (range) => {
- return {
- types: array(FETCH_LIST),
- call: client => client.get(`/funnels`),
- }
-}
-
-export const fetch = (funnelId, params) => (dispatch, getState) => {
- return dispatch({
- types: array(FETCH),
- call: client => client.get(`/funnels/${funnelId}`, params)
- });
-}
-
-// const eventMap = ({value, type, key, operator, source, custom}) => ({value, type, key, operator, source, custom});
-// const filterMap = ({value, type, key, operator, source, custom }) => ({value: Array.isArray(value) ? value: [value], custom, type, key, operator, source});
-
-function getParams(params, state) {
- const filter = state.getIn([ 'funnels', 'instance', 'filter']).toData();
- filter.filters = filter.filters.map(filterMap);
- const funnelFilters = state.getIn([ 'funnels', 'funnelFilters']).toJS();
-
- // const appliedFilter = state.getIn([ 'funnels', 'instance', 'filter' ]);
- // const filter = appliedFilter
- // .update('events', list => list.map(event => event.set('value', event.value || '*')).map(eventMap))
- // .toJS();
-
- // filter.filters = state.getIn([ 'funnelFilters', 'appliedFilter', 'filters' ])
- // .map(filterMap).toJS();
-
- return { ...filter, ...funnelFilters };
-}
-
-export const fetchInsights = (funnelId, params = {}, isRefresh = false) => (dispatch, getState) => {
- return dispatch({
- types: array(FETCH_INSIGHTS),
- call: client => client.post(`/funnels/${funnelId}/insights`, getParams(params, getState())),
- isRefresh
- })
-}
-
-
-export const fetchFiltered = (funnelId, params) => (dispatch, getState) => {
- return dispatch({
- types: array(FETCH),
- call: client => client.post(`/funnels/${funnelId}`, params),
- })
-}
-
-export const fetchIssuesFiltered = (funnelId, params) => (dispatch, getState) => {
- return dispatch({
- types: array(FETCH_ISSUES),
- call: client => client.post(`/funnels/${funnelId}/issues`, getParams(params, getState())),
- })
-}
-
-export const fetchSessionsFiltered = (funnelId, params) => (dispatch, getState) => {
- return dispatch({
- types: array(FETCH_SESSIONS),
- call: client => client.post(`/funnels/${funnelId}/sessions`, getParams(params, getState())),
- })
-}
-
-export const fetchIssue = (funnelId, issueId, params) => (dispatch, getState) => {
- const filters = getState().getIn([ 'funnelFilters', 'appliedFilter' ]);
- const _params = { ...filters.toData(), ...params };
- return dispatch({
- types: array(FETCH_ISSUE),
- call: client => client.post(`/funnels/${funnelId}/issues/${issueId}/sessions`, _params),
- })
-}
-
-export const fetchIssues = (funnelId, params) => {
- return {
- types: array(FETCH_ISSUES),
- call: client => client.get(`/funnels/${funnelId}/issues`, params),
- }
-}
-
-export const fetchSessions = (funnelId, params) => {
- return {
- types: array(FETCH_SESSIONS),
- call: client => client.get(`/funnels/${funnelId}/sessions`, params),
- }
-}
-
-export const fetchIssueTypes = () => {
- return {
- types: array(FETCH_ISSUE_TYPES),
- call: client => client.get(`/funnels/issue_types`),
- }
-}
-
-export const save = () => (dispatch, getState) => {
- const instance = getState().getIn([ 'funnels', 'instance'])
- const filter = instance.get('filter').toData();
- filter.filters = filter.filters.map(filterMap);
- const isExist = instance.exists();
-
- const _instance = instance instanceof Funnel ? instance : Funnel(instance);
- const url = isExist ? `/funnels/${ _instance[idKey] }` : `/funnels`;
-
- return dispatch({
- types: array(isExist ? SAVE : UPDATE),
- call: client => client.post(url, { ..._instance.toData(), filter }),
- });
-}
-
-export const updateFunnelFilters = (funnelId, filter) => {
- return {
- types: array(UPDATE),
- call: client => client.post(`/funnels/${funnelId}`, { filter }),
- }
-}
-
-export const remove = (index) => {
- return {
- types: array(REMOVE),
- call: client => client.delete(`/funnels/${index}`),
- index,
- }
-}
-
-export const applyFilter = (filterType='funnelFilters', filter) => {
- return {
- type: APPLY_FILTER,
- filter,
- filterType,
- }
-};
-
-export const applyIssueFilter = (filter) => {
- return {
- type: APPLY_ISSUE_FILTER,
- filter
- }
-};
-
-export const removeIssueFilter = errorType => {
- return {
- type: REMOVE_ISSUE_FILTER,
- errorType,
- }
-};
-
-export const setActiveStages = (stages, filters, funnelId, forceRrefresh = false) => (dispatch, getState) => {
- dispatch({
- type: SET_ACTIVE_STAGES,
- stages,
- })
-
- if (stages.length === 2) {
- const filter = {...filters.toData(), firstStage: stages[0] + 1, lastStage: stages[1] + 1 };
- dispatch(fetchIssuesFiltered(funnelId, filter))
- dispatch(fetchInsights(funnelId, filter, true));
- dispatch(fetchSessionsFiltered(funnelId, filter));
- } else if (forceRrefresh) {
- const filter = {...filters.toData()};
- dispatch(fetchIssuesFiltered(funnelId, filter))
- dispatch(fetchInsights(funnelId, filter));
- dispatch(fetchSessionsFiltered(funnelId, filter));
- }
-};
-
-export const edit = instance => {
- return {
- type: EDIT,
- instance,
- }
-};
-
-export const init = instance => {
- return {
- type: INIT,
- instance,
- }
-};
-
-export const setNavRef = ref => {
- return {
- type: SET_NAV_REF,
- navRef: ref
- }
-};
-
-export const resetIssue = () => {
- return {
- type: RESET_ISSUE,
- }
-}
-
-export const resetFunnel = () => {
- return {
- type: RESET_FUNNEL,
- }
-}
-
-export const setSessionsSort = (sortKey, sign = 1) => {
- return {
- type: SET_SESSIONS_SORT,
- sortKey,
- sign
- }
-}
-
-export const blink = (state = true) => {
- return {
- type: BLINK,
- state
- }
-}
-
-export const refresh = (funnelId) => (dispatch, getState) => {
- // dispatch(fetch(funnelId))
- dispatch(fetchInsights(funnelId))
- dispatch(fetchIssuesFiltered(funnelId, {}))
- dispatch(fetchSessionsFiltered(funnelId, {}))
-}
-
-export default mergeReducers(
- reducer,
- createRequestReducer({
- fetchRequest: FETCH,
- fetchListRequest: FETCH_LIST,
- fetchInsights: FETCH_INSIGHTS,
- fetchIssueRequest: FETCH_ISSUE,
- saveRequest: SAVE,
- updateRequest: UPDATE,
- fetchIssuesRequest: FETCH_ISSUES,
- fetchSessionsRequest: FETCH_SESSIONS,
- }),
-)
-
-const reduceThenFetchList = actionCreator => (...args) => (dispatch, getState) => {
- dispatch(actionCreator(...args));
- dispatch(refresh(getState().getIn([ 'funnels', 'instance', idKey ])));
-
- // const filter = getState().getIn([ 'funnels', 'instance', 'filter']).toData();
- // filter.filters = filter.filters.map(filterMap);
-
- // return dispatch(fetchSessionList(filter));
-};
-
-
-export const editFilter = reduceThenFetchList((instance) => ({
- type: EDIT_FILTER,
- instance,
-}));
-
-export const editFunnelFilter = reduceThenFetchList((instance) => ({
- type: EDIT_FUNNEL_FILTER,
- instance,
-}));
-
-export const addFilter = (filter) => (dispatch, getState) => {
- filter.value = checkFilterValue(filter.value);
- const instance = getState().getIn([ 'funnels', 'instance', 'filter']);
-
- if (hasFilterApplied(instance.filters, filter)) {
-
- } else {
- const filters = instance.filters.push(filter);
- return dispatch(editFilter(instance.set('filters', filters)));
- }
-}
-
-export const addFilterByKeyAndValue = (key, value) => (dispatch, getState) => {
- let defaultFilter = filtersMap[key];
- defaultFilter.value = value;
- dispatch(addFilter(defaultFilter));
-}
\ No newline at end of file
diff --git a/frontend/app/duck/index.ts b/frontend/app/duck/index.ts
index 2a14ce94e..8b9698c8d 100644
--- a/frontend/app/duck/index.ts
+++ b/frontend/app/duck/index.ts
@@ -4,12 +4,11 @@ import { combineReducers } from 'redux-immutable';
import user from './user';
import sessions from './sessions';
import filters from './filters';
-import funnelFilters from './funnelFilters';
import sources from './sources';
import site from './site';
import customFields from './customField';
import integrations from './integrations';
-import funnels from './funnels';
+import errors from './errors';
import customMetrics from './customMetrics';
import search from './search';
import liveSearch from './liveSearch';
@@ -18,10 +17,9 @@ const rootReducer = combineReducers({
user,
sessions,
filters,
- funnelFilters,
site,
customFields,
- funnels,
+ errors,
customMetrics,
search,
liveSearch,
@@ -31,4 +29,4 @@ const rootReducer = combineReducers({
export type RootStore = ReturnType
-export default rootReducer
\ No newline at end of file
+export default rootReducer