From 4e2bcf26a40634b320be697818de6c9543e277f1 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 13 Jun 2022 12:32:13 +0200 Subject: [PATCH] feat(ui) - funnels - issue details --- .../FunnelIssueModal/FunnelIssueModal.tsx | 22 ++++++++++++++ .../Funnels/FunnelIssueModal/index.ts | 1 + .../Funnels/FunnelIssues/FunnelIssues.tsx | 9 ++++-- .../FunnelIssuesList/FunnelIssuesList.tsx | 2 +- .../FunnelIssuesListItem.tsx | 5 +++- .../components/WidgetView/WidgetView.tsx | 6 ++-- frontend/app/mstore/metricStore.ts | 1 + frontend/app/mstore/types/funnel.ts | 29 +++++-------------- frontend/app/mstore/types/widget.ts | 4 ++- 9 files changed, 49 insertions(+), 30 deletions(-) create mode 100644 frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/FunnelIssueModal.tsx create mode 100644 frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/index.ts diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/FunnelIssueModal.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/FunnelIssueModal.tsx new file mode 100644 index 000000000..d33cf2dc8 --- /dev/null +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/FunnelIssueModal.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { withRouter } from 'react-router-dom'; +import { useStore } from 'App/mstore'; +import { useModal } from 'App/components/Modal'; + +interface Props { + +} +function FunnelIssueModal(props: Props) { + const { hideModal } = useModal(); + return ( +
+
+
+
+ ); +} + +export default FunnelIssueModal; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/index.ts b/frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/index.ts new file mode 100644 index 000000000..0261453c0 --- /dev/null +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssueModal/index.ts @@ -0,0 +1 @@ +export { default } from './FunnelIssueModal'; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index 1e206a071..d1f817a21 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -8,6 +8,7 @@ import FunnelIssuesList from '../FunnelIssuesList'; import { DateTime } from 'luxon'; import { debounce } from 'App/utils'; import useIsMounted from 'App/hooks/useIsMounted' +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; function FunnelIssues() { const { metricStore, dashboardStore } = useStore(); @@ -55,8 +56,12 @@ function FunnelIssues() { + +
No issues found
+ + } >
diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesList/FunnelIssuesList.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesList/FunnelIssuesList.tsx index b46a3cbae..9b81a6d1c 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesList/FunnelIssuesList.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesList/FunnelIssuesList.tsx @@ -11,7 +11,7 @@ function FunnelIssuesList(props: Props) { const { funnelStore } = useStore(); const issuesSort = useObserver(() => funnelStore.issuesSort); const issuesFilter = useObserver(() => funnelStore.issuesFilter.map((issue: any) => issue.value)); - // const issues = useObserver(() => funnelStore.issues); + let filteredIssues = useObserver(() => issuesFilter.length > 0 ? issues.filter((issue: any) => issuesFilter.includes(issue.type)) : issues); filteredIssues = useObserver(() => issuesSort.sort ? filteredIssues.slice().sort((a: { [x: string]: number; }, b: { [x: string]: number; }) => a[issuesSort.sort] - b[issuesSort.sort]): filteredIssues); filteredIssues = useObserver(() => issuesSort.order === 'desc' ? filteredIssues.reverse() : filteredIssues); diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesListItem/FunnelIssuesListItem.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesListItem/FunnelIssuesListItem.tsx index 1335c1353..999c01103 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesListItem/FunnelIssuesListItem.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesListItem/FunnelIssuesListItem.tsx @@ -2,6 +2,8 @@ import React from 'react'; import cn from 'classnames'; import { Icon, TextEllipsis } from 'UI'; import FunnelIssueGraph from '../FunnelIssueGraph'; +import { useModal } from 'App/components/Modal'; +import FunnelIssueModal from '../FunnelIssueModal'; interface Props { issue: any; @@ -9,8 +11,9 @@ interface Props { } function FunnelIssuesListItem(props) { const { issue, inDetails = false } = props; + const { showModal } = useModal(); const onClick = () => { - // console.log('onClick', issue); + showModal(, { right: true }); } return (
null}> diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index c4ef52bb2..1edec1c49 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -24,11 +24,9 @@ function WidgetView(props: Props) { const [expanded, setExpanded] = useState(!metricId || metricId === 'create'); React.useEffect(() => { - if (metricId && metricId !== 'create' && (!widget || !widget.exists())) { + if (metricId && metricId !== 'create') { metricStore.fetch(metricId); - } - - if (metricId === 'create') { + } else if (metricId === 'create') { metricStore.init(); } }, []) diff --git a/frontend/app/mstore/metricStore.ts b/frontend/app/mstore/metricStore.ts index f2920acaf..8a9ec96f7 100644 --- a/frontend/app/mstore/metricStore.ts +++ b/frontend/app/mstore/metricStore.ts @@ -90,6 +90,7 @@ export default class MetricStore implements IMetricStore { // State Actions init(metric?: IWidget|null) { + console.log('metric', metric); // const _metric = new Widget().fromJson(sampleJsonErrors) // this.instance.update(metric || _metric) diff --git a/frontend/app/mstore/types/funnel.ts b/frontend/app/mstore/types/funnel.ts index 43bc5a8b3..0085816c8 100644 --- a/frontend/app/mstore/types/funnel.ts +++ b/frontend/app/mstore/types/funnel.ts @@ -1,4 +1,3 @@ -// import Filter, { IFilter } from "./filter" import FunnelStage from './funnelStage' export interface IFunnel { @@ -22,27 +21,15 @@ export default class Funnel implements IFunnel { } fromJSON(json: any) { - const firstStage = json.stages[0] - const lastStage = json.stages[json.stages.length - 1] - this.lostConversions = json.totalDropDueToIssues - this.conversionImpact = this.lostConversions ? Math.round((this.lostConversions / firstStage.sessionsCount) * 100) : 0; - this.stages = json.stages ? json.stages.map((stage: any) => new FunnelStage().fromJSON(stage)) : [] - this.affectedUsers = firstStage.usersCount ? firstStage.usersCount - lastStage.usersCount : 0; + if (json.stages.length >= 1) { + const firstStage = json.stages[0] + const lastStage = json.stages[json.stages.length - 1] + this.lostConversions = json.totalDropDueToIssues + this.conversionImpact = this.lostConversions ? Math.round((this.lostConversions / firstStage.sessionsCount) * 100) : 0; + this.stages = json.stages ? json.stages.map((stage: any) => new FunnelStage().fromJSON(stage)) : [] + this.affectedUsers = firstStage.usersCount ? firstStage.usersCount - lastStage.usersCount : 0; + } return this } - - // toJSON(): any { - // return { - // // funnelId: this.funnelId, - // // name: this.name, - // // filter: this.filter.toJson(), - // // sessionsCount: this.sessionsCount, - // // conversionRate: this.conversionRate, - // } - // } - - // exists(): boolean { - // return this.funnelId !== '' - // } } \ No newline at end of file diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 3fbe21893..a78b7f35f 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -217,8 +217,10 @@ export default class Widget implements IWidget { fetchIssues(filter: any): Promise { return new Promise((resolve, reject) => { metricService.fetchIssues(filter).then((response: any) => { + const significantIssues = response.issues.significant ? response.issues.significant.map((issue: any) => new Funnelissue().fromJSON(issue)) : [] + const insignificantIssues = response.issues.insignificant ? response.issues.insignificant.map((issue: any) => new Funnelissue().fromJSON(issue)) : [] resolve({ - issues: response.issues.insignificant ? response.issues.insignificant.map((issue: any) => new Funnelissue().fromJSON(issue)) : [], + issues: significantIssues.length > 0 ? significantIssues : insignificantIssues, }) }) })