change(ui): cards menu
This commit is contained in:
parent
0e42041aa8
commit
ecec4d8fd7
8 changed files with 265 additions and 158 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NoContent } from 'UI';
|
import { NoContent } from 'UI';
|
||||||
import { Styles, AvgLabel } from '../../common';
|
import { Styles, AvgLabel } from '../../common';
|
||||||
import {
|
import {
|
||||||
ComposedChart, Bar, BarChart, CartesianGrid, ResponsiveContainer,
|
ComposedChart, Bar, BarChart, CartesianGrid, ResponsiveContainer,
|
||||||
XAxis, YAxis, ReferenceLine, Tooltip
|
XAxis, YAxis, ReferenceLine, Tooltip
|
||||||
} from 'recharts';
|
} from 'recharts';
|
||||||
import { NO_METRIC_DATA } from 'App/constants/messages'
|
import { NO_METRIC_DATA } from 'App/constants/messages'
|
||||||
|
|
@ -41,26 +41,25 @@ const PercentileLine = props => {
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: any
|
data: any
|
||||||
metric?: any
|
|
||||||
}
|
}
|
||||||
function ResponseTimeDistribution(props: Props) {
|
function ResponseTimeDistribution(props: Props) {
|
||||||
const { data, metric } = props;
|
const { data } = props;
|
||||||
const colors = Styles.colors;
|
const colors = Styles.colors;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NoContent
|
<NoContent
|
||||||
size="small"
|
size="small"
|
||||||
title={NO_METRIC_DATA}
|
title={NO_METRIC_DATA}
|
||||||
show={ metric.data.chart.length === 0 }
|
show={ data.chart.length === 0 }
|
||||||
style={ { height: '240px' } }
|
style={ { height: '240px' } }
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-end mb-3">
|
<div className="flex items-center justify-end mb-3">
|
||||||
<AvgLabel text="Avg" unit="ms" className="ml-3" count={metric.data.value} />
|
<AvgLabel text="Avg" unit="ms" className="ml-3" count={data.value} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex mb-4">
|
<div className="flex mb-4">
|
||||||
<ResponsiveContainer height={ 240 } width="100%">
|
<ResponsiveContainer height={ 240 } width="100%">
|
||||||
<ComposedChart
|
<ComposedChart
|
||||||
data={metric.data.chart}
|
data={data.chart}
|
||||||
margin={Styles.chartMargins}
|
margin={Styles.chartMargins}
|
||||||
barSize={50}
|
barSize={50}
|
||||||
>
|
>
|
||||||
|
|
@ -68,7 +67,7 @@ function ResponseTimeDistribution(props: Props) {
|
||||||
<XAxis
|
<XAxis
|
||||||
{...Styles.xaxis}
|
{...Styles.xaxis}
|
||||||
dataKey="responseTime"
|
dataKey="responseTime"
|
||||||
label={{
|
label={{
|
||||||
...Styles.axisLabelLeft,
|
...Styles.axisLabelLeft,
|
||||||
angle: 0,
|
angle: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
|
@ -87,7 +86,7 @@ function ResponseTimeDistribution(props: Props) {
|
||||||
/>
|
/>
|
||||||
<Bar minPointSize={1} name="Calls" dataKey="count" stackId="a" fill={colors[2]} label="Backend" />
|
<Bar minPointSize={1} name="Calls" dataKey="count" stackId="a" fill={colors[2]} label="Backend" />
|
||||||
<Tooltip {...Styles.tooltip} labelFormatter={val => 'Page Response Time: ' + val} />
|
<Tooltip {...Styles.tooltip} labelFormatter={val => 'Page Response Time: ' + val} />
|
||||||
{ metric.data.percentiles && metric.data.percentiles.map((item: any, i: number) => (
|
{ data.percentiles && data.percentiles.map((item: any, i: number) => (
|
||||||
<ReferenceLine
|
<ReferenceLine
|
||||||
key={i}
|
key={i}
|
||||||
label={
|
label={
|
||||||
|
|
@ -111,13 +110,13 @@ function ResponseTimeDistribution(props: Props) {
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
<ResponsiveContainer height={ 240 } width="10%">
|
<ResponsiveContainer height={ 240 } width="10%">
|
||||||
<BarChart
|
<BarChart
|
||||||
data={metric.data.extremeValues}
|
data={data.extremeValues}
|
||||||
margin={Styles.chartMargins}
|
margin={Styles.chartMargins}
|
||||||
barSize={40}
|
barSize={40}
|
||||||
>
|
>
|
||||||
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
||||||
<XAxis {...Styles.xaxis} dataKey="time" />
|
<XAxis {...Styles.xaxis} dataKey="time" />
|
||||||
<YAxis hide type="number" domain={[0, metric.data.total]} {...Styles.yaxis} allowDecimals={false} />
|
<YAxis hide type="number" domain={[0, data.total]} {...Styles.yaxis} allowDecimals={false} />
|
||||||
<Tooltip {...Styles.tooltip} />
|
<Tooltip {...Styles.tooltip} />
|
||||||
<Bar minPointSize={1} name="Extreme Values" dataKey="count" stackId="a" fill={colors[0]} />
|
<Bar minPointSize={1} name="Extreme Values" dataKey="count" stackId="a" fill={colors[0]} />
|
||||||
</BarChart>
|
</BarChart>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,17 @@ import ByBrowser from './Examples/SessionsBy/ByBrowser';
|
||||||
import BySystem from './Examples/SessionsBy/BySystem';
|
import BySystem from './Examples/SessionsBy/BySystem';
|
||||||
import ByCountry from './Examples/SessionsBy/ByCountry';
|
import ByCountry from './Examples/SessionsBy/ByCountry';
|
||||||
import ByUrl from './Examples/SessionsBy/ByUrl';
|
import ByUrl from './Examples/SessionsBy/ByUrl';
|
||||||
import { ERRORS, FUNNEL, INSIGHTS, PERFORMANCE, TABLE, TIMESERIES, USER_PATH, WEB_VITALS } from 'App/constants/card';
|
import {
|
||||||
|
CLICKMAP,
|
||||||
|
ERRORS,
|
||||||
|
FUNNEL,
|
||||||
|
INSIGHTS,
|
||||||
|
PERFORMANCE,
|
||||||
|
TABLE,
|
||||||
|
TIMESERIES,
|
||||||
|
USER_PATH,
|
||||||
|
WEB_VITALS
|
||||||
|
} from 'App/constants/card';
|
||||||
import { FilterKey } from 'Types/filter/filterType';
|
import { FilterKey } from 'Types/filter/filterType';
|
||||||
import { Activity, BarChart, TableCellsMerge, TrendingUp } from 'lucide-react';
|
import { Activity, BarChart, TableCellsMerge, TrendingUp } from 'lucide-react';
|
||||||
import WebVital from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/WebVital';
|
import WebVital from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/WebVital';
|
||||||
|
|
@ -25,6 +35,7 @@ import SlowestDomains
|
||||||
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains';
|
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains';
|
||||||
import SpeedIndexByLocationExample
|
import SpeedIndexByLocationExample
|
||||||
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample';
|
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample';
|
||||||
|
import HeatmapsExample from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/HeatmapsExample';
|
||||||
|
|
||||||
export const CARD_CATEGORY = {
|
export const CARD_CATEGORY = {
|
||||||
PRODUCT_ANALYTICS: 'product-analytics',
|
PRODUCT_ANALYTICS: 'product-analytics',
|
||||||
|
|
@ -90,6 +101,14 @@ export const CARD_LIST: CardType[] = [
|
||||||
totalDropDueToIssues: 294
|
totalDropDueToIssues: 294
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Heatmaps',
|
||||||
|
key: CLICKMAP,
|
||||||
|
cardType: CLICKMAP,
|
||||||
|
metricOf: 'sessionCount',
|
||||||
|
category: CARD_CATEGORIES[0].key,
|
||||||
|
example: HeatmapsExample
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Path Finder',
|
title: 'Path Finder',
|
||||||
key: USER_PATH,
|
key: USER_PATH,
|
||||||
|
|
@ -122,6 +141,7 @@ export const CARD_LIST: CardType[] = [
|
||||||
example: ByIssues
|
example: ByIssues
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
title: 'Insights',
|
title: 'Insights',
|
||||||
key: INSIGHTS,
|
key: INSIGHTS,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import ExCard from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard';
|
||||||
|
import heatmapRenderer from 'Player/web/addons/simpleHeatmap';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
type: string;
|
||||||
|
onCard: (card: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function HeatmapsExample(props: Props) {
|
||||||
|
const canvasRef = React.useRef<HTMLCanvasElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pointMap: Record<string, { times: number; data: number[], original: any }> = {};
|
||||||
|
let maxIntensity = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const x = Math.floor(Math.random() * 300);
|
||||||
|
const y = Math.floor(Math.random() * 180);
|
||||||
|
const key = `${x}-${y}`;
|
||||||
|
if (!pointMap[key]) {
|
||||||
|
pointMap[key] = {
|
||||||
|
times: Math.floor(Math.random() * 100),
|
||||||
|
data: [x, y],
|
||||||
|
original: { x, y }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
maxIntensity = Math.max(maxIntensity, pointMap[key].times);
|
||||||
|
}
|
||||||
|
|
||||||
|
const heatmapData: number[][] = [];
|
||||||
|
for (const key in pointMap) {
|
||||||
|
const { data, times } = pointMap[key];
|
||||||
|
heatmapData.push([...data, times]);
|
||||||
|
}
|
||||||
|
|
||||||
|
heatmapRenderer
|
||||||
|
.setCanvas(canvasRef?.current!)
|
||||||
|
.setData(heatmapData)
|
||||||
|
.setRadius(15, 10)
|
||||||
|
.setMax(maxIntensity)
|
||||||
|
.resize()
|
||||||
|
.draw();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
// const data = {};
|
||||||
|
return (
|
||||||
|
<ExCard
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<canvas ref={canvasRef}
|
||||||
|
style={{ width: '100%', height: '224px', backgroundColor: '#F4F4F4', borderRadius: '10px' }} />
|
||||||
|
</ExCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HeatmapsExample;
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ExCard from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard';
|
||||||
|
import CustomMetricOverviewChart from 'Components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart';
|
||||||
|
import ResponseTimeDistribution from 'Components/Dashboard/Widgets/PredefinedWidgets/ResponseTimeDistribution';
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
type: string;
|
||||||
|
onCard: (card: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PageResponseTimeDistributionExample(props: Props) {
|
||||||
|
const data = {
|
||||||
|
chart: []
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ExCard
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ResponseTimeDistribution data={data} />
|
||||||
|
</ExCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PageResponseTimeDistributionExample;
|
||||||
|
|
@ -54,8 +54,8 @@ function DashboardWidgetGrid(props: Props) {
|
||||||
}
|
}
|
||||||
dashboardId={dashboardId}
|
dashboardId={dashboardId}
|
||||||
siteId={siteId}
|
siteId={siteId}
|
||||||
isWidget={false}
|
|
||||||
grid="other"
|
grid="other"
|
||||||
|
showMenu={true}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -1,159 +1,161 @@
|
||||||
import React, {useRef} from 'react';
|
import React, { useRef } from 'react';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import {Card, Tooltip, Button} from 'antd';
|
import { Card, Tooltip, Button } from 'antd';
|
||||||
import {useDrag, useDrop} from 'react-dnd';
|
import { useDrag, useDrop } from 'react-dnd';
|
||||||
import WidgetChart from '../WidgetChart';
|
import WidgetChart from '../WidgetChart';
|
||||||
import {observer} from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
import {useStore} from 'App/mstore';
|
import { useStore } from 'App/mstore';
|
||||||
import {withRouter, RouteComponentProps} from 'react-router-dom';
|
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||||
import {withSiteId, dashboardMetricDetails} from 'App/routes';
|
import { withSiteId, dashboardMetricDetails } from 'App/routes';
|
||||||
import TemplateOverlay from './TemplateOverlay';
|
import TemplateOverlay from './TemplateOverlay';
|
||||||
import stl from './widgetWrapper.module.css';
|
import stl from './widgetWrapper.module.css';
|
||||||
import {FilterKey} from 'App/types/filter/filterType';
|
import { FilterKey } from 'App/types/filter/filterType';
|
||||||
import LazyLoad from 'react-lazyload';
|
import LazyLoad from 'react-lazyload';
|
||||||
import {TIMESERIES} from "App/constants/card";
|
import { TIMESERIES } from 'App/constants/card';
|
||||||
import CardMenu from "Components/Dashboard/components/WidgetWrapper/CardMenu";
|
import CardMenu from 'Components/Dashboard/components/WidgetWrapper/CardMenu';
|
||||||
import AlertButton from "Components/Dashboard/components/WidgetWrapper/AlertButton";
|
import AlertButton from 'Components/Dashboard/components/WidgetWrapper/AlertButton';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
widget?: any;
|
widget?: any;
|
||||||
index?: number;
|
index?: number;
|
||||||
moveListItem?: any;
|
moveListItem?: any;
|
||||||
isPreview?: boolean;
|
isPreview?: boolean;
|
||||||
isTemplate?: boolean;
|
isTemplate?: boolean;
|
||||||
dashboardId?: string;
|
dashboardId?: string;
|
||||||
siteId?: string;
|
siteId?: string;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
history?: any;
|
history?: any;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
isWidget?: boolean;
|
isWidget?: boolean;
|
||||||
hideName?: boolean;
|
hideName?: boolean;
|
||||||
grid?: string;
|
grid?: string;
|
||||||
isGridView?: boolean;
|
isGridView?: boolean;
|
||||||
|
showMenu?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function WidgetWrapperNew(props: Props & RouteComponentProps) {
|
function WidgetWrapperNew(props: Props & RouteComponentProps) {
|
||||||
const {dashboardStore} = useStore();
|
const { dashboardStore } = useStore();
|
||||||
const {
|
const {
|
||||||
isWidget = false,
|
isWidget = false,
|
||||||
active = false,
|
active = false,
|
||||||
index = 0,
|
index = 0,
|
||||||
moveListItem = null,
|
moveListItem = null,
|
||||||
isPreview = false,
|
isPreview = false,
|
||||||
isTemplate = false,
|
isTemplate = false,
|
||||||
siteId,
|
siteId,
|
||||||
grid = '',
|
grid = '',
|
||||||
isGridView = false,
|
isGridView = false,
|
||||||
} = props;
|
showMenu = false
|
||||||
const widget: any = props.widget;
|
} = props;
|
||||||
const isTimeSeries = widget.metricType === TIMESERIES;
|
const widget: any = props.widget;
|
||||||
const isPredefined = widget.metricType === 'predefined';
|
const isTimeSeries = widget.metricType === TIMESERIES;
|
||||||
const dashboard = dashboardStore.selectedDashboard;
|
const isPredefined = widget.metricType === 'predefined';
|
||||||
|
const dashboard = dashboardStore.selectedDashboard;
|
||||||
|
|
||||||
const [{isDragging}, dragRef] = useDrag({
|
const [{ isDragging }, dragRef] = useDrag({
|
||||||
type: 'item',
|
type: 'item',
|
||||||
item: {index, grid},
|
item: { index, grid },
|
||||||
collect: (monitor) => ({
|
collect: (monitor) => ({
|
||||||
isDragging: monitor.isDragging(),
|
isDragging: monitor.isDragging()
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const [{isOver, canDrop}, dropRef] = useDrop({
|
const [{ isOver, canDrop }, dropRef] = useDrop({
|
||||||
accept: 'item',
|
accept: 'item',
|
||||||
drop: (item: any) => {
|
drop: (item: any) => {
|
||||||
if (item.index === index || item.grid !== grid) return;
|
if (item.index === index || item.grid !== grid) return;
|
||||||
moveListItem(item.index, index);
|
moveListItem(item.index, index);
|
||||||
},
|
},
|
||||||
canDrop(item) {
|
canDrop(item) {
|
||||||
return item.grid === grid;
|
return item.grid === grid;
|
||||||
},
|
},
|
||||||
collect: (monitor: any) => ({
|
collect: (monitor: any) => ({
|
||||||
isOver: monitor.isOver(),
|
isOver: monitor.isOver(),
|
||||||
canDrop: monitor.canDrop(),
|
canDrop: monitor.canDrop()
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const onChartClick = () => {
|
const onChartClick = () => {
|
||||||
// if (!isWidget || isPredefined) return;
|
// if (!isWidget || isPredefined) return;
|
||||||
props.history.push(
|
props.history.push(
|
||||||
withSiteId(dashboardMetricDetails(dashboard?.dashboardId, widget.metricId), siteId)
|
withSiteId(dashboardMetricDetails(dashboard?.dashboardId, widget.metricId), siteId)
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ref: any = useRef(null);
|
|
||||||
const dragDropRef: any = dragRef(dropRef(ref));
|
|
||||||
const addOverlay =
|
|
||||||
isTemplate ||
|
|
||||||
(!isPredefined &&
|
|
||||||
isWidget &&
|
|
||||||
widget.metricOf !== FilterKey.ERRORS &&
|
|
||||||
widget.metricOf !== FilterKey.SESSIONS);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
className={cn(
|
|
||||||
'relative group rounded-lg',
|
|
||||||
'col-span-' + widget.config.col,
|
|
||||||
{'hover:shadow-sm': !isTemplate && isWidget},
|
|
||||||
)}
|
|
||||||
style={{
|
|
||||||
userSelect: 'none',
|
|
||||||
opacity: isDragging ? 0.5 : 1,
|
|
||||||
borderColor:
|
|
||||||
(canDrop && isOver) || active ? '#394EFF' : isPreview ? 'transparent' : '#EEEEEE',
|
|
||||||
}}
|
|
||||||
ref={dragDropRef}
|
|
||||||
onClick={props.onClick ? props.onClick : () => null}
|
|
||||||
id={`widget-${widget.widgetId}`}
|
|
||||||
title={!props.hideName ? widget.name : null}
|
|
||||||
extra={isWidget ? [
|
|
||||||
<div className="flex items-center" id="no-print">
|
|
||||||
{!isPredefined && isTimeSeries && !isGridView && (
|
|
||||||
<AlertButton seriesId={widget.series[0] && widget.series[0].seriesId}/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!isTemplate && !isGridView && (
|
|
||||||
<CardMenu card={widget} key="card-menu"/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
] : []}
|
|
||||||
styles={{
|
|
||||||
header: {
|
|
||||||
padding: '0 14px',
|
|
||||||
borderBottom: 'none',
|
|
||||||
minHeight: 44,
|
|
||||||
fontWeight: 500,
|
|
||||||
fontSize: 14,
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
padding: 0,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!isTemplate && isWidget && isPredefined && (
|
|
||||||
<Tooltip title="Cannot drill down system provided metrics">
|
|
||||||
<div
|
|
||||||
className={cn(stl.drillDownMessage, 'disabled text-gray text-sm invisible group-hover:visible')}>
|
|
||||||
{'Cannot drill down system provided metrics'}
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{addOverlay && <TemplateOverlay onClick={onChartClick} isTemplate={isTemplate}/>}
|
|
||||||
|
|
||||||
<LazyLoad offset={!isTemplate ? 100 : 600}>
|
|
||||||
<div className="px-4" onClick={onChartClick}>
|
|
||||||
<WidgetChart
|
|
||||||
isPreview={isPreview}
|
|
||||||
metric={widget}
|
|
||||||
isTemplate={isTemplate}
|
|
||||||
isWidget={isWidget}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</LazyLoad>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ref: any = useRef(null);
|
||||||
|
const dragDropRef: any = dragRef(dropRef(ref));
|
||||||
|
const addOverlay =
|
||||||
|
isTemplate ||
|
||||||
|
(!isPredefined &&
|
||||||
|
isWidget &&
|
||||||
|
widget.metricOf !== FilterKey.ERRORS &&
|
||||||
|
widget.metricOf !== FilterKey.SESSIONS);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
className={cn(
|
||||||
|
'relative group rounded-lg',
|
||||||
|
'col-span-' + widget.config.col,
|
||||||
|
{ 'hover:shadow-sm': !isTemplate && isWidget }
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
userSelect: 'none',
|
||||||
|
opacity: isDragging ? 0.5 : 1,
|
||||||
|
borderColor:
|
||||||
|
(canDrop && isOver) || active ? '#394EFF' : isPreview ? 'transparent' : '#EEEEEE'
|
||||||
|
}}
|
||||||
|
ref={dragDropRef}
|
||||||
|
onClick={props.onClick ? props.onClick : () => null}
|
||||||
|
id={`widget-${widget.widgetId}`}
|
||||||
|
title={!props.hideName ? widget.name : null}
|
||||||
|
extra={[
|
||||||
|
<div className="flex items-center" id="no-print">
|
||||||
|
{!isPredefined && isTimeSeries && !isGridView && (
|
||||||
|
<AlertButton seriesId={widget.series[0] && widget.series[0].seriesId} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showMenu && (
|
||||||
|
<CardMenu card={widget} key="card-menu" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
]}
|
||||||
|
styles={{
|
||||||
|
header: {
|
||||||
|
padding: '0 14px',
|
||||||
|
borderBottom: 'none',
|
||||||
|
minHeight: 44,
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!isTemplate && isWidget && isPredefined && (
|
||||||
|
<Tooltip title="Cannot drill down system provided metrics">
|
||||||
|
<div
|
||||||
|
className={cn(stl.drillDownMessage, 'disabled text-gray text-sm invisible group-hover:visible')}>
|
||||||
|
{'Cannot drill down system provided metrics'}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{addOverlay && <TemplateOverlay onClick={onChartClick} isTemplate={isTemplate} />}
|
||||||
|
|
||||||
|
<LazyLoad offset={!isTemplate ? 100 : 600}>
|
||||||
|
<div className="px-4" onClick={onChartClick}>
|
||||||
|
<WidgetChart
|
||||||
|
isPreview={isPreview}
|
||||||
|
metric={widget}
|
||||||
|
isTemplate={isTemplate}
|
||||||
|
isWidget={isWidget}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</LazyLoad>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(observer(WidgetWrapperNew));
|
export default withRouter(observer(WidgetWrapperNew));
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ function FunnelBar(props: Props) {
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<Icon name="arrow-right-short" size="20" color="green" />
|
<Icon name="arrow-right-short" size="20" color="green" />
|
||||||
<span className="mx-1 font-medium">{filter.sessionsCount} Sessions</span>
|
<span className="mx-1">{filter.sessionsCount} Sessions</span>
|
||||||
<span className="color-gray-medium text-sm">
|
<span className="color-gray-medium text-sm">
|
||||||
({filter.completedPercentage}%) Completed
|
({filter.completedPercentage}%) Completed
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -70,7 +70,7 @@ function FunnelBar(props: Props) {
|
||||||
<Space className="items-center">
|
<Space className="items-center">
|
||||||
<Icon name="caret-down-fill" color={filter.droppedCount > 0 ? 'red' : 'gray-light'} size={16} />
|
<Icon name="caret-down-fill" color={filter.droppedCount > 0 ? 'red' : 'gray-light'} size={16} />
|
||||||
<span
|
<span
|
||||||
className={'font-medium mx-1 ' + (filter.droppedCount > 0 ? 'color-red' : 'disabled')}>{filter.droppedCount} Sessions</span>
|
className={'mx-1 ' + (filter.droppedCount > 0 ? 'color-red' : 'disabled')}>{filter.droppedCount} Sessions</span>
|
||||||
<span
|
<span
|
||||||
className={'text-sm ' + (filter.droppedCount > 0 ? 'color-red' : 'disabled')}>({filter.droppedPercentage}%) Dropped</span>
|
className={'text-sm ' + (filter.droppedCount > 0 ? 'color-red' : 'disabled')}>({filter.droppedPercentage}%) Dropped</span>
|
||||||
</Space>
|
</Space>
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ export const Stage = observer(({ stage, index, isWidget, uxt, focusStage, focuse
|
||||||
>
|
>
|
||||||
<IndexNumber index={index} />
|
<IndexNumber index={index} />
|
||||||
{!uxt ? <Funnelbar index={index} filter={stage} focusStage={focusStage} focusedFilter={focusedFilter} /> : <UxTFunnelBar filter={stage} />}
|
{!uxt ? <Funnelbar index={index} filter={stage} focusStage={focusStage} focusedFilter={focusedFilter} /> : <UxTFunnelBar filter={stage} />}
|
||||||
{!isWidget && !uxt && <BarActions bar={stage} />}
|
{/*{!isWidget && !uxt && <BarActions bar={stage} />}*/}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue