Fixed path counts. Updated number display.

This commit is contained in:
Mike Cao 2024-06-18 22:38:36 -07:00
parent 45d6b16b0d
commit f56849a431
3 changed files with 63 additions and 77 deletions

View File

@ -1,6 +1,7 @@
.menu { .menu {
position: relative; position: relative;
width: 300px; width: 300px;
padding-top: 20px;
padding-inline-end: 20px; padding-inline-end: 20px;
border-inline-end: 1px solid var(--base300); border-inline-end: 1px solid var(--base300);
grid-row: 2 / 3; grid-row: 2 / 3;
@ -9,6 +10,7 @@
.button { .button {
position: absolute; position: absolute;
top: 0;
right: 0; right: 0;
display: flex; display: flex;
place-content: center; place-content: center;

View File

@ -80,7 +80,7 @@
padding-bottom: 10px; padding-bottom: 10px;
} }
.item { .node {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
padding: 10px 20px; padding: 10px 20px;
@ -89,37 +89,35 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
min-width: 300px; width: 300px;
max-width: 300px; max-width: 300px;
min-height: 60px; height: 60px;
max-height: 60px;
} }
.item:hover:not(.selected) { .node:hover:not(.selected) {
color: var(--base900); color: var(--base900);
background: var(--base100); background: var(--base100);
} }
.item.selected { .node.selected {
color: var(--base75); color: var(--base75);
background: var(--base900); background: var(--base900);
font-weight: 400; font-weight: 400;
} }
.item.active { .node.active {
color: var(--light50); color: var(--light50);
background: var(--primary400); background: var(--primary400);
} }
.behind { .node.selected .count {
color: var(--base400); color: var(--base50);
background: var(--base800);
} }
.ahead { .node.selected.active .count {
color: var(--base400); background: var(--primary600);
}
.current {
color: var(--base500);
} }
.name { .name {
@ -132,20 +130,12 @@
background: var(--base200); background: var(--base200);
} }
.item.selected .count {
color: var(--base50);
background: var(--base800);
}
.item.selected.active .count {
background: var(--primary600);
}
.line { .line {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: -100px; left: -100px;
width: 100px; width: 100px;
pointer-events: none;
} }
.line.up { .line.up {
@ -230,8 +220,8 @@
border-radius: 100%; border-radius: 100%;
border: 3px solid var(--journey-line-color); border: 3px solid var(--journey-line-color);
background: var(--light50); background: var(--light50);
width: 13px; width: 14px;
height: 13px; height: 14px;
} }
.line:not(.active) .start:before, .line:not(.active) .start:before,

View File

@ -5,8 +5,8 @@ import classNames from 'classnames';
import { useEscapeKey, useMessages } from 'components/hooks'; import { useEscapeKey, useMessages } from 'components/hooks';
import { objectToArray } from 'lib/data'; import { objectToArray } from 'lib/data';
import { ReportContext } from '../[reportId]/Report'; import { ReportContext } from '../[reportId]/Report';
// eslint-disable-next-line css-modules/no-unused-class
import styles from './JourneyView.module.css'; import styles from './JourneyView.module.css';
import { formatLongNumber } from 'lib/format';
const NODE_HEIGHT = 60; const NODE_HEIGHT = 60;
const NODE_GAP = 10; const NODE_GAP = 10;
@ -37,27 +37,11 @@ export default function JourneyView() {
const name = items[columnIndex]; const name = items[columnIndex];
if (name) { if (name) {
const selected = !!selectedPaths.find(path => path.items[columnIndex] === name); const selected = !!selectedPaths.find(({ items }) => items[columnIndex] === name);
const active = selected && !!activePaths.find(path => path.items[columnIndex] === name); const active = selected && !!activePaths.find(({ items }) => items[columnIndex] === name);
if (!nodes[name]) { if (!nodes[name]) {
const paths = data.filter(d => d.items[columnIndex] === name); const paths = data.filter(({ items }) => items[columnIndex] === name);
const from =
columnIndex > 0 &&
selected &&
paths.reduce((obj, path) => {
const { items, count } = path;
const name = items[columnIndex - 1];
if (!obj[name]) {
obj[name] = { name, count };
} else {
obj[name].count += count;
}
return obj;
}, {});
nodes[name] = { nodes[name] = {
name, name,
@ -68,7 +52,9 @@ export default function JourneyView() {
selected, selected,
active, active,
paths, paths,
from: objectToArray(from), pathMap: paths.map(({ items, count }) => ({
[`${columnIndex}:${items.join(':')}`]: count,
})),
}; };
} else { } else {
nodes[name].totalCount += count; nodes[name].totalCount += count;
@ -82,43 +68,45 @@ export default function JourneyView() {
} }
columns.forEach((column, columnIndex) => { columns.forEach((column, columnIndex) => {
const nodes = column.nodes.map((node, nodeIndex) => { const nodes = column.nodes.map((currentNode, currentNodeIndex) => {
const { from, totalCount } = node;
const previousNodes = columns[columnIndex - 1]?.nodes; const previousNodes = columns[columnIndex - 1]?.nodes;
let selectedCount = from?.length ? 0 : totalCount; let selectedCount = previousNodes ? 0 : currentNode.totalCount;
let activeCount = selectedCount; let activeCount = selectedCount;
const lines = from?.reduce((arr: any[][], { name, count }: any) => { const lines =
const fromIndex = previousNodes.findIndex((node: { name: any; selected: any }) => { previousNodes?.reduce((arr: any[][], previousNode: any, previousNodeIndex: number) => {
return node.name === name && node.selected; const fromCount = selectedNode?.paths.reduce((sum, path) => {
}); if (
previousNode.name === path.items[columnIndex - 1] &&
currentNode.name === path.items[columnIndex]
) {
sum += path.count;
}
return sum;
}, 0);
if (fromIndex > -1) { if (currentNode.selected && previousNode.selected && fromCount) {
arr.push([fromIndex, nodeIndex]); arr.push([previousNodeIndex, currentNodeIndex]);
selectedCount += count; selectedCount += fromCount;
}
if ( if (previousNode.active) {
previousNodes.findIndex(node => { activeCount += fromCount;
return node.name === name && node.active; }
}) > -1 }
) {
activeCount += count;
}
return arr; return arr;
}, []); }, []) || [];
return { ...node, selectedCount, activeCount, lines }; return { ...currentNode, selectedCount, activeCount, lines };
}); });
const visitorCount = nodes.reduce( const visitorCount = nodes.reduce(
(sum: number, { selected, selectedCount, active, activeCount, totalCount }) => { (sum: number, { selected, selectedCount, active, activeCount, totalCount }) => {
if (!selectedNode) { if (!selectedNode) {
sum += totalCount; sum += totalCount;
} else if (!activeNode && selected) { } else if (!activeNode && selectedNode && selected) {
sum += selectedCount; sum += selectedCount;
} else if (active) { } else if (activeNode && active) {
sum += activeCount; sum += activeCount;
} }
return sum; return sum;
@ -136,9 +124,9 @@ export default function JourneyView() {
return columns; return columns;
}, [data, selectedNode, activeNode]); }, [data, selectedNode, activeNode]);
const handleClick = (name: string, index: number, paths: any[]) => { const handleClick = (name: string, columnIndex: number, paths: any[]) => {
if (name !== selectedNode?.name || index !== selectedNode?.index) { if (name !== selectedNode?.name || columnIndex !== selectedNode?.columnIndex) {
setSelectedNode({ name, index, paths }); setSelectedNode({ name, columnIndex, paths });
} else { } else {
setSelectedNode(null); setSelectedNode(null);
} }
@ -165,8 +153,8 @@ export default function JourneyView() {
<div className={styles.header}> <div className={styles.header}>
<div className={styles.num}>{columnIndex + 1}</div> <div className={styles.num}>{columnIndex + 1}</div>
<div className={styles.stats}> <div className={styles.stats}>
<div className={styles.visitors}> <div className={styles.visitors} title={column.visitorCount}>
{column.visitorCount} {formatMessage(labels.visitors)} {formatLongNumber(column.visitorCount)} {formatMessage(labels.visitors)}
</div> </div>
{columnIndex > 0 && <div className={styles.dropoff}>{dropOffPercent}</div>} {columnIndex > 0 && <div className={styles.dropoff}>{dropOffPercent}</div>}
</div> </div>
@ -183,6 +171,12 @@ export default function JourneyView() {
selectedCount, selectedCount,
lines, lines,
}) => { }) => {
const nodeCount = selected
? active
? activeCount
: selectedCount
: totalCount;
return ( return (
<div <div
key={name} key={name}
@ -191,7 +185,7 @@ export default function JourneyView() {
onMouseLeave={() => selected && setActiveNode(null)} onMouseLeave={() => selected && setActiveNode(null)}
> >
<div <div
className={classNames(styles.item, { className={classNames(styles.node, {
[styles.selected]: selected, [styles.selected]: selected,
[styles.active]: active, [styles.active]: active,
})} })}
@ -199,8 +193,8 @@ export default function JourneyView() {
> >
<div className={styles.name}>{name}</div> <div className={styles.name}>{name}</div>
<TooltipPopup label={dropOffPercent} disabled={!selected}> <TooltipPopup label={dropOffPercent} disabled={!selected}>
<div className={styles.count}> <div className={styles.count} title={nodeCount}>
{selected ? (active ? activeCount : selectedCount) : totalCount} {formatLongNumber(nodeCount)}
</div> </div>
</TooltipPopup> </TooltipPopup>
{columnIndex < columns.length && {columnIndex < columns.length &&