fix(ui) - click maps count and percentage, dropdown
This commit is contained in:
parent
b368dc3adf
commit
a4f0b323c5
4 changed files with 133 additions and 134 deletions
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Dropdown, Loader, Icon } from 'UI';
|
||||
import DateRange from 'Shared/DateRange';
|
||||
import { Loader, Icon } from 'UI';
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchInsights } from 'Duck/sessions';
|
||||
import SelectorsList from './components/SelectorsList/SelectorsList';
|
||||
|
|
@ -11,100 +10,103 @@ import Period from 'Types/app/period';
|
|||
|
||||
const JUMP_OFFSET = 1000;
|
||||
interface Props {
|
||||
filters: any
|
||||
fetchInsights: (filters: Record<string, any>) => void
|
||||
urls: []
|
||||
insights: any
|
||||
events: Array<any>
|
||||
urlOptions: Array<any>
|
||||
loading: boolean
|
||||
host: string
|
||||
setActiveTab: (tab: string) => void
|
||||
filters: any;
|
||||
fetchInsights: (filters: Record<string, any>) => void;
|
||||
urls: [];
|
||||
insights: any;
|
||||
events: Array<any>;
|
||||
urlOptions: Array<any>;
|
||||
loading: boolean;
|
||||
host: string;
|
||||
setActiveTab: (tab: string) => void;
|
||||
}
|
||||
|
||||
function PageInsightsPanel({
|
||||
filters, fetchInsights, events = [], insights, urlOptions, host, loading = true, setActiveTab
|
||||
}: Props) {
|
||||
const [insightsFilters, setInsightsFilters] = useState(filters)
|
||||
const defaultValue = (urlOptions && urlOptions[0]) ? urlOptions[0].value : ''
|
||||
function PageInsightsPanel({ filters, fetchInsights, events = [], insights, urlOptions, host, loading = true, setActiveTab }: Props) {
|
||||
const [insightsFilters, setInsightsFilters] = useState(filters);
|
||||
const defaultValue = urlOptions && urlOptions[0] ? urlOptions[0].value : '';
|
||||
|
||||
const period = new Period({
|
||||
start: insightsFilters.startDate,
|
||||
end: insightsFilters.endDate,
|
||||
rangeName: insightsFilters.rangeValue
|
||||
});
|
||||
const period = Period({
|
||||
start: insightsFilters.startDate,
|
||||
end: insightsFilters.endDate,
|
||||
rangeName: insightsFilters.rangeValue,
|
||||
});
|
||||
|
||||
const onDateChange = (e) => {
|
||||
const { startDate, endDate, rangeValue } = e.toJSON();
|
||||
setInsightsFilters({ ...insightsFilters, startDate, endDate, rangeValue })
|
||||
}
|
||||
const onDateChange = (e: any) => {
|
||||
const { startDate, endDate, rangeValue } = e.toJSON();
|
||||
setInsightsFilters({ ...insightsFilters, startDate, endDate, rangeValue });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
markTargets(insights.toJS());
|
||||
return () => {
|
||||
markTargets(null)
|
||||
}
|
||||
}, [insights])
|
||||
useEffect(() => {
|
||||
markTargets(insights.toJS());
|
||||
return () => {
|
||||
markTargets(null);
|
||||
};
|
||||
}, [insights]);
|
||||
|
||||
useEffect(() => {
|
||||
if (urlOptions && urlOptions[0]) {
|
||||
const url = insightsFilters.url ? insightsFilters.url : host + urlOptions[0].value;
|
||||
Player.pause();
|
||||
fetchInsights({ ...insightsFilters, url })
|
||||
}
|
||||
}, [insightsFilters])
|
||||
useEffect(() => {
|
||||
if (urlOptions && urlOptions[0]) {
|
||||
const url = insightsFilters.url ? insightsFilters.url : host + urlOptions[0].value;
|
||||
Player.pause();
|
||||
fetchInsights({ ...insightsFilters, url });
|
||||
}
|
||||
}, [insightsFilters]);
|
||||
|
||||
const onPageSelect = ({ value }: { value: Array<any> }) => {
|
||||
const event = events.find(item => item.url === value)
|
||||
Player.jump(event.time + JUMP_OFFSET)
|
||||
setInsightsFilters({ ...insightsFilters, url: host + value })
|
||||
markTargets([])
|
||||
};
|
||||
const onPageSelect = ({ value }: any) => {
|
||||
const event = events.find((item) => item.url === value.value);
|
||||
Player.jump(event.time + JUMP_OFFSET);
|
||||
setInsightsFilters({ ...insightsFilters, url: host + value.value });
|
||||
markTargets([]);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 bg-white">
|
||||
<div className="pb-3 flex items-center" style={{ maxWidth: '241px', paddingTop: '5px' }}>
|
||||
<div className="flex items-center">
|
||||
<span className="mr-1 text-xl">Clicks</span>
|
||||
<SelectDateRange period={period} onChange={onDateChange} disableCustom />
|
||||
return (
|
||||
<div className="p-4 bg-white">
|
||||
<div className="pb-3 flex items-center" style={{ maxWidth: '241px', paddingTop: '5px' }}>
|
||||
<div className="flex items-center">
|
||||
<span className="mr-1 text-xl">Clicks</span>
|
||||
<SelectDateRange period={period} onChange={onDateChange} disableCustom />
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
setActiveTab('');
|
||||
}}
|
||||
className="ml-auto flex items-center justify-center bg-white cursor-pointer"
|
||||
>
|
||||
<Icon name="close" size="18" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4 flex items-center">
|
||||
<div className="mr-2 flex-shrink-0">In Page</div>
|
||||
<Select
|
||||
isSearchable={true}
|
||||
right
|
||||
placeholder="change"
|
||||
options={urlOptions}
|
||||
name="url"
|
||||
defaultValue={defaultValue}
|
||||
onChange={onPageSelect}
|
||||
id="change-dropdown"
|
||||
className="w-full"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<Loader loading={loading}>
|
||||
<SelectorsList />
|
||||
</Loader>
|
||||
</div>
|
||||
<div
|
||||
onClick={() => { setActiveTab(''); }}
|
||||
className="ml-auto flex items-center justify-center bg-white cursor-pointer"
|
||||
>
|
||||
<Icon name="close" size="18" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4 flex items-center">
|
||||
<div className="mr-2 flex-shrink-0">In Page</div>
|
||||
<Select
|
||||
isSearchable={true}
|
||||
right
|
||||
placeholder="change"
|
||||
options={ urlOptions }
|
||||
name="url"
|
||||
defaultValue={defaultValue}
|
||||
onChange={ onPageSelect }
|
||||
id="change-dropdown"
|
||||
className="w-full"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<Loader loading={ loading }>
|
||||
<SelectorsList />
|
||||
</Loader>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(state => {
|
||||
const events = state.getIn([ 'sessions', 'visitedEvents' ])
|
||||
return {
|
||||
filters: state.getIn(['sessions', 'insightFilters']),
|
||||
host: state.getIn([ 'sessions', 'host' ]),
|
||||
insights: state.getIn([ 'sessions', 'insights' ]),
|
||||
events: events,
|
||||
urlOptions: events.map(({ url, host }: any) => ({ label: url, value: url, host })),
|
||||
loading: state.getIn([ 'sessions', 'fetchInsightsRequest', 'loading' ]),
|
||||
}
|
||||
}, { fetchInsights })(PageInsightsPanel);
|
||||
export default connect(
|
||||
(state) => {
|
||||
const events = state.getIn(['sessions', 'visitedEvents']);
|
||||
return {
|
||||
filters: state.getIn(['sessions', 'insightFilters']),
|
||||
host: state.getIn(['sessions', 'host']),
|
||||
insights: state.getIn(['sessions', 'insights']),
|
||||
events: events,
|
||||
urlOptions: events.map(({ url, host }: any) => ({ label: url, value: url, host })),
|
||||
loading: state.getIn(['sessions', 'fetchInsightsRequest', 'loading']),
|
||||
};
|
||||
},
|
||||
{ fetchInsights }
|
||||
)(PageInsightsPanel);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,34 @@
|
|||
import React, { useState } from 'react'
|
||||
import stl from './SelectorCard.module.css'
|
||||
import React, { useState } from 'react';
|
||||
import stl from './SelectorCard.module.css';
|
||||
import cn from 'classnames';
|
||||
import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen';
|
||||
import { activeTarget } from 'Player';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
interface Props {
|
||||
index?: number,
|
||||
target: MarkedTarget,
|
||||
showContent: boolean
|
||||
index?: number;
|
||||
target: MarkedTarget;
|
||||
showContent: boolean;
|
||||
}
|
||||
|
||||
export default function SelectorCard({ index = 1, target, showContent } : Props) {
|
||||
return (
|
||||
<div className={cn(stl.wrapper, { [stl.active]: showContent })} onClick={() => activeTarget(index)}>
|
||||
<div className={stl.top}>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip position='top' title="Rank of the most clicked element"><div className={stl.index}>{index + 1}</div></Tooltip>
|
||||
<div className="truncate">{target.selector}</div>
|
||||
</div>
|
||||
{ showContent && (
|
||||
<div className={stl.counts}>
|
||||
<div>{target.count} Clicks - {target.percent}%</div>
|
||||
<div className="color-gray-medium">TOTAL CLICKS</div>
|
||||
export default function SelectorCard({ index = 1, target, showContent }: Props) {
|
||||
return (
|
||||
<div className={cn(stl.wrapper, { [stl.active]: showContent })} onClick={() => activeTarget(index)}>
|
||||
<div className={stl.top}>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip position="top" title="Rank of the most clicked element">
|
||||
<div className={stl.index}>{index + 1}</div>
|
||||
</Tooltip>
|
||||
<div className="truncate">{target.selector}</div>
|
||||
</div>
|
||||
{showContent && (
|
||||
<div className={stl.counts}>
|
||||
<div>
|
||||
{target.count} Clicks - {target.percent}%
|
||||
</div>
|
||||
<div className="color-gray-medium">TOTAL CLICKS</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,26 @@
|
|||
import React, { useState } from 'react'
|
||||
import { NoContent } from 'UI'
|
||||
import React from 'react';
|
||||
import { NoContent } from 'UI';
|
||||
import { connectPlayer } from 'Player/store';
|
||||
import SelectorCard from '../SelectorCard/SelectorCard';
|
||||
import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen';
|
||||
import stl from './selectorList.module.css'
|
||||
import stl from './selectorList.module.css';
|
||||
|
||||
interface Props {
|
||||
targets: Array<MarkedTarget>,
|
||||
activeTargetIndex: number
|
||||
targets: Array<MarkedTarget>;
|
||||
activeTargetIndex: number;
|
||||
}
|
||||
|
||||
function SelectorsList({ targets, activeTargetIndex }: Props) {
|
||||
return (
|
||||
<NoContent
|
||||
title="No data available."
|
||||
size="small"
|
||||
show={ targets && targets.length === 0 }
|
||||
>
|
||||
<div className={stl.wrapper}>
|
||||
{ targets && targets.map((target, index) => (
|
||||
<SelectorCard target={target} index={index} showContent={activeTargetIndex === index} />
|
||||
))}
|
||||
</div>
|
||||
</NoContent>
|
||||
)
|
||||
function SelectorsList({ targets, activeTargetIndex }: Props) {
|
||||
return (
|
||||
<NoContent title="No data available." size="small" show={targets && targets.length === 0}>
|
||||
<div className={stl.wrapper}>
|
||||
{targets && targets.map((target, index) => <SelectorCard target={target} index={index} showContent={activeTargetIndex === index} />)}
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default connectPlayer(state => ({
|
||||
targets: state.markedTargets,
|
||||
activeTargetIndex: state.activeTargetIndex,
|
||||
}))(SelectorsList)
|
||||
export default connectPlayer((state: any) => ({
|
||||
targets: state.markedTargets,
|
||||
activeTargetIndex: state.activeTargetIndex,
|
||||
}))(SelectorsList);
|
||||
|
|
|
|||
|
|
@ -145,9 +145,9 @@ export default class StatedScreen extends Screen {
|
|||
...s,
|
||||
el,
|
||||
index: index++,
|
||||
percent: 0,
|
||||
percent: Math.round((s.count * 100) / totalCount),
|
||||
boundingRect: this.calculateRelativeBoundingRect(el),
|
||||
count: Math.round((s.count * 100) / totalCount)
|
||||
count: s.count,
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue