fix(ui): card issues and avg time in path analysis

This commit is contained in:
Shekar Siri 2023-10-31 09:55:08 +01:00
parent c7f013589d
commit e497aa3554
6 changed files with 56 additions and 34 deletions

View file

@ -57,7 +57,7 @@ function CardIssues() {
} }
}; };
const handleClick = (issue: any) => { const handleClick = (issue?: any) => {
showModal(<SessionsModal issue={issue} list={[]} />, { right: true, width: 900 }); showModal(<SessionsModal issue={issue} list={[]} />, { right: true, width: 900 });
}; };
@ -89,7 +89,7 @@ function CardIssues() {
)} )}
</div> </div>
<div> <div>
<Button variant='text-primary'>All Sessions</Button> <Button variant='text-primary' onClick={() => handleClick()}>All Sessions</Button>
</div> </div>
</div> </div>

View file

@ -25,13 +25,15 @@ function SessionsModal(props: Props) {
const fetchSessions = async (filter: any) => { const fetchSessions = async (filter: any) => {
setLoading(true); setLoading(true);
filter.filters = [ filter.filters = [];
{
if (issue) {
filter.filters.push({
type: 'issue', type: 'issue',
operator: 'is', operator: 'is',
value: [issue.type] value: [issue.type]
} });
]; }
const res = await metricService.fetchSessions(null, filter); const res = await metricService.fetchSessions(null, filter);
console.log('res', res); console.log('res', res);
setList(res[0].sessions.map((item: any) => new Session().fromJson(item))); setList(res[0].sessions.map((item: any) => new Session().fromJson(item)));
@ -43,15 +45,10 @@ function SessionsModal(props: Props) {
fetchSessions({ ...dashboardStore.drillDownFilter, ...metricStore.instance.toJson(), limit: 10, page: page }); fetchSessions({ ...dashboardStore.drillDownFilter, ...metricStore.instance.toJson(), limit: 10, page: page });
}, [page]); }, [page]);
useEffect(() => {
fetchSessions({ ...dashboardStore.drillDownFilter, ...metricStore.instance.toJson(), limit: 10, page: 1 });
}, [props.issue]);
return ( return (
<div className='bg-white h-screen'> <div className='bg-white h-screen'>
<Modal.Header title='Sessions'> <Modal.Header title='Sessions'>
Sessions with selected issue {issue ? 'Sessions with selected issue' : 'All sessions'}
</Modal.Header> </Modal.Header>
<Loader loading={loading}> <Loader loading={loading}>
<NoContent show={length == 0} title='No data!'> <NoContent show={length == 0} title='No data!'>

View file

@ -17,7 +17,7 @@ function NodeButton(props: Props) {
return ( return (
<div className='relative'> <div className='relative'>
<Popover content={ <Popover content={
<div className='bg-white rounded w-fit mt-1 text-xs'> <div className='bg-white rounded mt-1 text-xs'>
<div className='border-b py-1 px-2 flex items-center'> <div className='border-b py-1 px-2 flex items-center'>
<div className='w-6 shrink-0'> <div className='w-6 shrink-0'>
<Icon name='link-45deg' size={18} /> <Icon name='link-45deg' size={18} />
@ -30,14 +30,17 @@ function NodeButton(props: Props) {
</div> </div>
<div className='ml-1 font-medium'>Continuing {Math.round(payload.value)}%</div> <div className='ml-1 font-medium'>Continuing {Math.round(payload.value)}%</div>
</div> </div>
<div className='border-b py-1 px-2 flex items-center'> {payload.avgTimeFromPrevious && (
<div className='w-6 shrink-0'> <div className='border-b py-1 px-2 flex items-center'>
<Icon name='clock-history' size={16} /> <div className='w-6 shrink-0'>
<Icon name='clock-history' size={16} />
</div>
<div className='ml-1 font-medium'>
Average time from previous step <span>{payload.avgTimeFromPrevious}</span>
</div>
</div> </div>
<div className='ml-1 font-medium'> )}
Average time from previous step <span>{payload.avgTimeFromPrevious}</span>
</div>
</div>
</div> </div>
} title={<div className='text-sm'>Title</div>}> } title={<div className='text-sm'>Title</div>}>
<div <div

View file

@ -5,7 +5,7 @@ import CustomNode from './CustomNode';
import { NoContent } from 'UI'; import { NoContent } from 'UI';
interface Node { interface Node {
id: number; // Assuming you missed this from your interface idd: number;
name: string; name: string;
eventType: string; eventType: string;
avgTimeFromPrevious: number | null; avgTimeFromPrevious: number | null;

View file

@ -3,20 +3,41 @@
import { DateTime, Duration } from 'luxon'; // TODO import { DateTime, Duration } from 'luxon'; // TODO
import { Timezone } from 'MOBX/types/sessionSettings'; import { Timezone } from 'MOBX/types/sessionSettings';
export const durationFormatted = (duration: Duration):string => { /**
if (duration.as('minutes') < 1) { // show in seconds * Formats a given duration.
duration = duration.toFormat('s\'s\''); *
} else if (duration.as('hours') < 1) { // show in minutes * @param {Duration | number} inputDuration - The duration to format. Can be a Duration object or a number representing milliseconds.
duration = duration.toFormat('m\'m\'s\'s'); * @returns {string} - Formatted duration string.
} else if (duration.as('days') < 1) { // show in hours and minutes *
duration = duration.toFormat('h\'h\'m\'m'); * @example
} else if (duration.as('months') < 1) { // show in days and hours *
duration = duration.toFormat('d\'d\'h\'h'); * // Format a duration from a Duration object
* const duration1 = Duration.fromObject({ hours: 2, minutes: 30 });
* console.log(durationFormatted(duration1)); // Outputs: "2h30m"
*
* // Format a duration from milliseconds
* console.log(durationFormatted(55000)); // Outputs: "55s"
*/
export const durationFormatted = (inputDuration: Duration | number): string => {
let duration: Duration;
if (inputDuration instanceof Duration) {
duration = inputDuration;
} else { } else {
duration = duration.toFormat('m\'m\'s\'s\''); duration = Duration.fromMillis(inputDuration);
} }
return duration; if (duration.as('minutes') < 1) { // show in seconds
return duration.toFormat('s\'s\'');
} else if (duration.as('hours') < 1) { // show in minutes
return duration.toFormat('m\'m\'s\'s\'');
} else if (duration.as('days') < 1) { // show in hours and minutes
return duration.toFormat('h\'h\'m\'m\'');
} else if (duration.as('months') < 1) { // show in days and hours
return duration.toFormat('d\'d\'h\'h\'');
} else {
return duration.toFormat('m\'m\'s\'s\'');
}
}; };
export function durationFromMsFormatted(ms: number): string { export function durationFromMsFormatted(ms: number): string {
@ -44,7 +65,7 @@ export const durationFormattedFull = (duration: Duration): string => {
duration = d + (d > 1 ? ' days' : ' day'); duration = d + (d > 1 ? ' days' : ' day');
} else { } else {
let d = Math.trunc(duration.as('months')); let d = Math.trunc(duration.as('months'));
duration = d + (d > 1 ? ' months' : ' month');; duration = d + (d > 1 ? ' months' : ' month');
} }
return duration; return duration;

View file

@ -14,6 +14,7 @@ import { getChartFormatter } from 'Types/dashboard/helper';
import FilterItem from './filterItem'; import FilterItem from './filterItem';
import { filtersMap } from 'Types/filter/newFilter'; import { filtersMap } from 'Types/filter/newFilter';
import Issue from '../types/issue'; import Issue from '../types/issue';
import { durationFormatted } from 'App/date';
export class InsightIssue { export class InsightIssue {
icon: string; icon: string;
@ -264,12 +265,12 @@ export default class Widget {
if (this.metricType === USER_PATH) { if (this.metricType === USER_PATH) {
_data['nodes'] = data.nodes.map((s: any) => ({ _data['nodes'] = data.nodes.map((s: any) => ({
...s, ...s,
avgTimeFromPrevious: s.avgTimeFromPrevious ? durationFormatted(s.avgTimeFromPrevious) : null,
idd: Math.random().toString(36).substring(7), idd: Math.random().toString(36).substring(7),
})); }));
_data['links'] = data.links.map((s: any) => ({ _data['links'] = data.links.map((s: any) => ({
...s, ...s,
id: Math.random().toString(36).substring(7), id: Math.random().toString(36).substring(7),
// value: Math.round(s.value),
})); }));
Object.assign(this.data, _data); Object.assign(this.data, _data);