fix(ui): issues drilldown payload

This commit is contained in:
Shekar Siri 2024-07-02 11:29:14 +02:00
parent a62a19a38d
commit b38eda8821
4 changed files with 111 additions and 123 deletions

View file

@ -1,60 +1,60 @@
import React from 'react';
import { List, Progress, Typography } from "antd";
import cn from "classnames";
import { List, Progress, Typography } from 'antd';
import cn from 'classnames';
interface Props {
list: any;
selected?: any;
onClickHandler?: (event: any, data: any) => void;
list: any;
selected?: any;
onClickHandler?: (event: any, data: any) => void;
}
function CardSessionsByList({ list, selected, onClickHandler = () => null }: Props) {
return (
<List
dataSource={list}
split={false}
renderItem={(row: any) => (
<List.Item
key={row.name}
onClick={(e) => onClickHandler(e, row)} // Remove onClick handler to disable click interaction
style={{
borderBottom: '1px dotted rgba(0, 0, 0, 0.05)',
padding: '4px 10px',
lineHeight: '1px'
}}
className={cn('rounded', selected === row.name ? 'bg-active-blue' : '')} // Remove hover:bg-active-blue and cursor-pointer
>
<List.Item.Meta
className="m-0"
avatar={row.icon ? row.icon : null}
title={(
<div className="m-0">
<div className="flex justify-between m-0 p-0">
<Typography.Text>{row.name}</Typography.Text>
<Typography.Text type="secondary"> {row.sessionCount}</Typography.Text>
</div>
return (
<List
dataSource={list}
split={false}
renderItem={(row: any) => (
<List.Item
key={row.name}
onClick={(e) => onClickHandler(e, row)} // Remove onClick handler to disable click interaction
style={{
borderBottom: '1px dotted rgba(0, 0, 0, 0.05)',
padding: '4px 10px',
lineHeight: '1px'
}}
className={cn('rounded', selected === row.name ? 'bg-active-blue' : '')} // Remove hover:bg-active-blue and cursor-pointer
>
<List.Item.Meta
className="m-0"
avatar={row.icon ? row.icon : null}
title={(
<div className="m-0">
<div className="flex justify-between m-0 p-0">
<Typography.Text>{row.displayName}</Typography.Text>
<Typography.Text type="secondary"> {row.sessionCount}</Typography.Text>
</div>
<Progress
percent={row.progress}
showInfo={false}
strokeColor={{
'0%': '#394EFF',
'100%': '#394EFF',
}}
size={['small', 2]}
style={{
padding: '0 0px',
margin: '0 0px',
height: 4
}}
/>
</div>
)}
/>
</List.Item>
<Progress
percent={row.progress}
showInfo={false}
strokeColor={{
'0%': '#394EFF',
'100%': '#394EFF'
}}
size={['small', 2]}
style={{
padding: '0 0px',
margin: '0 0px',
height: 4
}}
/>
</div>
)}
/>
);
/>
</List.Item>
)}
/>
);
}
export default CardSessionsByList;

View file

@ -67,6 +67,7 @@ function SessionsBy(props: Props) {
/>
) : (
<div className="flex flex-col justify-between w-full" style={{ height: 220 }}>
{/* TODO - remove slice once the api pagination is fixed */}
<CardSessionsByList list={data.values.slice(0, 3)}
selected={selected}
onClickHandler={onClickHandler} />
@ -74,7 +75,7 @@ function SessionsBy(props: Props) {
<div className="flex">
<Button type="link" onClick={showMore}>
<Space className="flex font-medium gap-1">
{total - 5} More
{total - 3} More
<ArrowRight size={16} />
</Space>
</Button>

View file

@ -8,7 +8,6 @@ function BackButton() {
const siteId = location.pathname.split('/')[1];
const handleBackClick = () => {
console.log('siteId', siteId);
history.push(`/${siteId}/dashboard`);
};

View file

@ -1,98 +1,86 @@
import {numberWithCommas} from "App/utils";
import {countries} from "App/constants";
import { numberWithCommas } from 'App/utils';
import { countries } from 'App/constants';
import {
BrowserIconProvider,
CountryIconProvider, DeviceIconProvider,
IconProvider,
IssueIconProvider, OsIconProvider,
UrlIconProvider, UserIconProvider
} from "./IconProvider";
BrowserIconProvider,
CountryIconProvider, DeviceIconProvider,
IconProvider,
IssueIconProvider, OsIconProvider,
UrlIconProvider, UserIconProvider
} from './IconProvider';
import React from 'react';
interface NameFormatter {
format(name: string): string;
format(name: string): string;
}
class BaseFormatter implements NameFormatter {
format(name: string): string {
return name.replace(/_/g, ' ').replace(/\w\S*/g, (w) => (w.replace(/^\w/, (c) => c.toUpperCase()))).trim();
}
format(name: string): string {
return name.replace(/_/g, ' ').replace(/\w\S*/g, (w) => (w.replace(/^\w/, (c) => c.toUpperCase()))).trim();
}
}
class BrowserFormatter extends BaseFormatter {
format(name: string): string {
return super.format(name);
}
format(name: string): string {
return super.format(name);
}
}
class CountryFormatter extends BaseFormatter {
format(name: string): string {
if (name === 'UN') {
return 'Unknown Country';
}
return countries[name.toUpperCase()] || name;
format(name: string): string {
if (name === 'UN') {
return 'Unknown Country';
}
return countries[name.toUpperCase()] || name;
}
}
class IssueFormatter extends BaseFormatter {
format(name: string): string {
return super.format(name);
}
format(name: string): string {
return super.format(name);
}
}
export class SessionsByRow {
name: string;
sessionCount: number;
progress: number;
icon: React.ReactNode;
name: string;
displayName: string;
sessionCount: number;
progress: number;
icon: React.ReactNode;
fromJson(json: any, totalSessions: number, metricType: string) {
const {nameFormatter, iconProvider} = this.getFormatters(metricType);
this.name = nameFormatter.format(json.name) || 'Unidentified';
this.sessionCount = numberWithCommas(json.sessionCount);
this.progress = Math.round((json.sessionCount / totalSessions) * 100);
this.icon = iconProvider.getIcon(json.name);
return this;
}
fromJson(json: any, totalSessions: number, metricType: string) {
const { nameFormatter, iconProvider } = this.getFormatters(metricType);
this.name = json.name;
this.displayName = nameFormatter.format(json.name) || 'Unidentified';
this.sessionCount = numberWithCommas(json.sessionCount);
this.progress = Math.round((json.sessionCount / totalSessions) * 100);
this.icon = iconProvider.getIcon(json.name);
return this;
}
private getFormatters(metricType: string): { nameFormatter: NameFormatter; iconProvider: IconProvider } {
switch (metricType) {
case 'userBrowser':
return {nameFormatter: new BrowserFormatter(), iconProvider: new BrowserIconProvider()};
case 'userCountry':
return {nameFormatter: new CountryFormatter(), iconProvider: new CountryIconProvider()};
case 'issue':
return {nameFormatter: new IssueFormatter(), iconProvider: new IssueIconProvider()};
case 'location':
return {nameFormatter: new BaseFormatter(), iconProvider: new UrlIconProvider()};
case 'userDevice':
return {nameFormatter: new BaseFormatter(), iconProvider: new DeviceIconProvider()};
case 'platform':
return {nameFormatter: new BaseFormatter(), iconProvider: new OsIconProvider()};
case 'userId':
return {nameFormatter: new BaseFormatter(), iconProvider: new UserIconProvider()};
default:
return {nameFormatter: new BaseFormatter(), iconProvider: new DefaultIconProvider()};
}
private getFormatters(metricType: string): { nameFormatter: NameFormatter; iconProvider: IconProvider } {
switch (metricType) {
case 'userBrowser':
return { nameFormatter: new BrowserFormatter(), iconProvider: new BrowserIconProvider() };
case 'userCountry':
return { nameFormatter: new CountryFormatter(), iconProvider: new CountryIconProvider() };
case 'issue':
return { nameFormatter: new IssueFormatter(), iconProvider: new IssueIconProvider() };
case 'location':
return { nameFormatter: new BaseFormatter(), iconProvider: new UrlIconProvider() };
case 'userDevice':
return { nameFormatter: new BaseFormatter(), iconProvider: new DeviceIconProvider() };
case 'platform':
return { nameFormatter: new BaseFormatter(), iconProvider: new OsIconProvider() };
case 'userId':
return { nameFormatter: new BaseFormatter(), iconProvider: new UserIconProvider() };
default:
return { nameFormatter: new BaseFormatter(), iconProvider: new DefaultIconProvider() };
}
}
}
class DefaultIconProvider implements IconProvider {
getIcon(name: string): string {
return 'ic-user-path';
}
getIcon(name: string): string {
return 'ic-user-path';
}
}
// Usage example
// const data = [
// {
// values: [
// {name: 'chrome', sessionCount: 120},
// {name: 'firefox', sessionCount: 80},
// {name: 'safari', sessionCount: 50},
// ]
// }
// ];
// const totalSessions = 1000;
// const metricOf = 'browser';
//
// data[0]['values'] = data[0]['values'].map((s: any) => new SessionsByRow().fromJson(s, totalSessions, metricOf));