mirror of
https://github.com/umami-software/umami.git
synced 2026-02-13 17:15:37 +01:00
Changed steps to dropdown.
This commit is contained in:
parent
edd679295c
commit
3234120bfb
3 changed files with 92 additions and 76 deletions
|
|
@ -1,6 +1,15 @@
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useMessages } from 'components/hooks';
|
import { useMessages } from 'components/hooks';
|
||||||
import { Form, FormButtons, FormInput, FormRow, SubmitButton, TextField } from 'react-basics';
|
import {
|
||||||
|
Dropdown,
|
||||||
|
Form,
|
||||||
|
FormButtons,
|
||||||
|
FormInput,
|
||||||
|
FormRow,
|
||||||
|
Item,
|
||||||
|
SubmitButton,
|
||||||
|
TextField,
|
||||||
|
} from 'react-basics';
|
||||||
import { ReportContext } from '../[reportId]/Report';
|
import { ReportContext } from '../[reportId]/Report';
|
||||||
import BaseParameters from '../[reportId]/BaseParameters';
|
import BaseParameters from '../[reportId]/BaseParameters';
|
||||||
|
|
||||||
|
|
@ -24,12 +33,12 @@ export function JourneyParameters() {
|
||||||
return (
|
return (
|
||||||
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
|
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
|
||||||
<BaseParameters showDateSelect={true} allowWebsiteSelect={!id} />
|
<BaseParameters showDateSelect={true} allowWebsiteSelect={!id} />
|
||||||
<FormRow label={`${formatMessage(labels.steps)} (3 to 7)`}>
|
<FormRow label={formatMessage(labels.steps)}>
|
||||||
<FormInput
|
<FormInput
|
||||||
name="steps"
|
name="steps"
|
||||||
rules={{ required: formatMessage(labels.required), pattern: /[0-9]+/, min: 3, max: 7 }}
|
rules={{ required: formatMessage(labels.required), pattern: /[0-9]+/, min: 3, max: 7 }}
|
||||||
>
|
>
|
||||||
<TextField autoComplete="off" />
|
<Dropdown items={[3, 4, 5, 6, 7]}>{item => <Item key={item}>{item}</Item>}</Dropdown>
|
||||||
</FormInput>
|
</FormInput>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
<FormRow label={formatMessage(labels.startStep)}>
|
<FormRow label={formatMessage(labels.startStep)}>
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ export default function JourneyView() {
|
||||||
const selectedNodes = selectedNode?.paths ?? [];
|
const selectedNodes = selectedNode?.paths ?? [];
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
|
const selected = !!selectedNodes.find(a => a.items[index] === name);
|
||||||
if (!column[name]) {
|
if (!column[name]) {
|
||||||
const selected = !!selectedNodes.find(a => a.items[index] === name);
|
|
||||||
const paths = data.filter((d, i) => {
|
const paths = data.filter((d, i) => {
|
||||||
return i !== index && d.items[index] === name;
|
return i !== index && d.items[index] === name;
|
||||||
});
|
});
|
||||||
|
|
@ -43,23 +43,26 @@ export default function JourneyView() {
|
||||||
const { items, count } = path;
|
const { items, count } = path;
|
||||||
const name = items[index - 1];
|
const name = items[index - 1];
|
||||||
if (!obj[name]) {
|
if (!obj[name]) {
|
||||||
obj[name] = { name, count: +count };
|
obj[name] = { name, count };
|
||||||
} else {
|
} else {
|
||||||
obj[name].count += +count;
|
obj[name].count += count;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
column[name] = {
|
column[name] = {
|
||||||
name,
|
name,
|
||||||
total: +count,
|
count,
|
||||||
|
total: count,
|
||||||
columnIndex: index,
|
columnIndex: index,
|
||||||
selected,
|
selected,
|
||||||
|
selectedCount: count,
|
||||||
paths,
|
paths,
|
||||||
from: objectToArray(from),
|
from: objectToArray(from),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
column[name].total += +count;
|
column[name].selectedCount += selected ? count : 0;
|
||||||
|
column[name].total += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -97,77 +100,81 @@ export default function JourneyView() {
|
||||||
<div className={styles.num}>{columnIndex + 1}</div>
|
<div className={styles.num}>{columnIndex + 1}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.nodes}>
|
<div className={styles.nodes}>
|
||||||
{column.nodes.map(({ name, total, selected, paths, from }, nodeIndex) => {
|
{column.nodes.map(
|
||||||
const active =
|
({ name, total, selected, paths, from, selectedCount }, nodeIndex) => {
|
||||||
selected && activeNode?.paths.find(path => path.items[columnIndex] === name);
|
const active =
|
||||||
|
selected && activeNode?.paths.find(path => path.items[columnIndex] === name);
|
||||||
|
|
||||||
const lines = from?.reduce((arr, { name }: any) => {
|
const lines = from?.reduce((arr, { name }: any) => {
|
||||||
const fromIndex = columns[columnIndex - 1]?.nodes.findIndex(node => {
|
const fromIndex = columns[columnIndex - 1]?.nodes.findIndex(node => {
|
||||||
return node.name === name && node.selected;
|
return node.name === name && node.selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (fromIndex > -1) {
|
if (fromIndex > -1) {
|
||||||
arr.push([fromIndex, nodeIndex]);
|
arr.push([fromIndex, nodeIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={name}
|
key={name}
|
||||||
className={classNames(styles.item, {
|
className={classNames(styles.item, {
|
||||||
[styles.selected]: selected,
|
[styles.selected]: selected,
|
||||||
[styles.active]: active,
|
[styles.active]: active,
|
||||||
})}
|
|
||||||
onClick={() => handleClick(name, columnIndex, paths)}
|
|
||||||
onMouseEnter={() => selected && setActiveNode({ name, columnIndex, paths })}
|
|
||||||
onMouseLeave={() => selected && setActiveNode(null)}
|
|
||||||
>
|
|
||||||
<div className={styles.name}>{name}</div>
|
|
||||||
<div className={styles.count}>{total}</div>
|
|
||||||
{columnIndex < columns.length &&
|
|
||||||
lines.map(([fromIndex, nodeIndex], i) => {
|
|
||||||
const height =
|
|
||||||
(Math.abs(nodeIndex - fromIndex) + 1) * (NODE_HEIGHT + NODE_GAP) -
|
|
||||||
NODE_GAP;
|
|
||||||
const midHeight =
|
|
||||||
(Math.abs(nodeIndex - fromIndex) - 1) * (NODE_HEIGHT + NODE_GAP) +
|
|
||||||
NODE_GAP +
|
|
||||||
LINE_WIDTH;
|
|
||||||
const nodeName = columns[columnIndex - 1]?.nodes[fromIndex].name;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={`${fromIndex}${nodeIndex}${i}`}
|
|
||||||
className={classNames(styles.line, {
|
|
||||||
[styles.active]:
|
|
||||||
active &&
|
|
||||||
activeNode?.paths.find(
|
|
||||||
path =>
|
|
||||||
path.items[columnIndex] === name &&
|
|
||||||
path.items[columnIndex - 1] === nodeName,
|
|
||||||
),
|
|
||||||
[styles.up]: fromIndex < nodeIndex,
|
|
||||||
[styles.down]: fromIndex > nodeIndex,
|
|
||||||
[styles.flat]: fromIndex === nodeIndex,
|
|
||||||
})}
|
|
||||||
style={{ height }}
|
|
||||||
>
|
|
||||||
<div className={classNames(styles.segment, styles.start)} />
|
|
||||||
<div
|
|
||||||
className={classNames(styles.segment, styles.mid)}
|
|
||||||
style={{
|
|
||||||
height: midHeight,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className={classNames(styles.segment, styles.end)} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
})}
|
||||||
</div>
|
onClick={() => handleClick(name, columnIndex, paths)}
|
||||||
);
|
onMouseEnter={() => selected && setActiveNode({ name, columnIndex, paths })}
|
||||||
})}
|
onMouseLeave={() => selected && setActiveNode(null)}
|
||||||
|
>
|
||||||
|
<div className={styles.name}>{name}</div>
|
||||||
|
<div className={styles.count}>
|
||||||
|
{selected || active ? selectedCount : total}
|
||||||
|
</div>
|
||||||
|
{columnIndex < columns.length &&
|
||||||
|
lines.map(([fromIndex, nodeIndex], i) => {
|
||||||
|
const height =
|
||||||
|
(Math.abs(nodeIndex - fromIndex) + 1) * (NODE_HEIGHT + NODE_GAP) -
|
||||||
|
NODE_GAP;
|
||||||
|
const midHeight =
|
||||||
|
(Math.abs(nodeIndex - fromIndex) - 1) * (NODE_HEIGHT + NODE_GAP) +
|
||||||
|
NODE_GAP +
|
||||||
|
LINE_WIDTH;
|
||||||
|
const nodeName = columns[columnIndex - 1]?.nodes[fromIndex].name;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={`${fromIndex}${nodeIndex}${i}`}
|
||||||
|
className={classNames(styles.line, {
|
||||||
|
[styles.active]:
|
||||||
|
active &&
|
||||||
|
activeNode?.paths.find(
|
||||||
|
path =>
|
||||||
|
path.items[columnIndex] === name &&
|
||||||
|
path.items[columnIndex - 1] === nodeName,
|
||||||
|
),
|
||||||
|
[styles.up]: fromIndex < nodeIndex,
|
||||||
|
[styles.down]: fromIndex > nodeIndex,
|
||||||
|
[styles.flat]: fromIndex === nodeIndex,
|
||||||
|
})}
|
||||||
|
style={{ height }}
|
||||||
|
>
|
||||||
|
<div className={classNames(styles.segment, styles.start)} />
|
||||||
|
<div
|
||||||
|
className={classNames(styles.segment, styles.mid)}
|
||||||
|
style={{
|
||||||
|
height: midHeight,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className={classNames(styles.segment, styles.end)} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ interface JourneyResult {
|
||||||
e5: string;
|
e5: string;
|
||||||
e6: string;
|
e6: string;
|
||||||
e7: string;
|
e7: string;
|
||||||
count: string;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getJourney(
|
export async function getJourney(
|
||||||
|
|
@ -267,6 +267,6 @@ function combineSequentialDuplicates(array: any) {
|
||||||
function parseResult(data: any) {
|
function parseResult(data: any) {
|
||||||
return data.map(({ e1, e2, e3, e4, e5, e6, e7, count }) => ({
|
return data.map(({ e1, e2, e3, e4, e5, e6, e7, count }) => ({
|
||||||
items: combineSequentialDuplicates([e1, e2, e3, e4, e5, e6, e7]),
|
items: combineSequentialDuplicates([e1, e2, e3, e4, e5, e6, e7]),
|
||||||
count,
|
count: +count,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue