* feat ui: dashboards redesign start * more cards * fix ui: more different cards... * feat ui: finish cards, all trigger, all icons * change(ui): added missin const * feature(ui): new dashboard modal * feature(ui): new dashboard modal * change(ui): new cards * change(ui): dashboard redesign * change(ui): dashboard redesign * change(ui): dashboard redesign * change(ui): modal context and alert form * change(ui): table card show more with modal * change(ui): examples * change(ui): example categorize and other improvements * change(ui): example categorize and other improvements * change(ui): performance cards * change(ui): insights card * Various style updates in dashboards and other pages. (#2308) * Various minor style updates * Various style improvements * Update ExampleCards.tsx * change(ui): fixed an issue with card create * change(ui): fixed an issue with card create * change(ui): default filters and events order * change(ui): random data * Dashboards redesign - improvments (#2313) * Various minor style updates * Various style improvements * Update ExampleCards.tsx * various minor improvements in dashbaords. * revised dashboard widget header * change(ui): sessions by user * change(ui): funnel example * change(ui): modal height and scroll * change(ui): example cards with data * change(ui): example cards with data * change(ui): funnel bar text color * change(ui): example cards overlay click * change(ui): path analysis filter card --------- Co-authored-by: Shekar Siri <sshekarsiri@gmail.com> Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
179 lines
6.9 KiB
TypeScript
179 lines
6.9 KiB
TypeScript
import React from 'react';
|
|
import {Card, Space, Typography, Button} from "antd";
|
|
import {useStore} from "App/mstore";
|
|
import {eventKeys} from "Types/filter/newFilter";
|
|
import {
|
|
CLICKMAP,
|
|
ERRORS,
|
|
FUNNEL,
|
|
INSIGHTS,
|
|
PERFORMANCE,
|
|
RESOURCE_MONITORING,
|
|
RETENTION,
|
|
TABLE,
|
|
USER_PATH, WEB_VITALS
|
|
} from "App/constants/card";
|
|
import FilterSeries from "Components/Dashboard/components/FilterSeries/FilterSeries";
|
|
import {metricOf} from "App/constants/filterOptions";
|
|
import {AudioWaveform, ChevronDown, ChevronUp, PlusIcon} from "lucide-react";
|
|
import {observer} from "mobx-react-lite";
|
|
import AddStepButton from "Components/Dashboard/components/FilterSeries/AddStepButton";
|
|
import {Icon} from "UI";
|
|
import FilterItem from "Shared/Filters/FilterItem";
|
|
import {FilterKey} from "Types/filter/filterType";
|
|
|
|
function WidgetFormNew() {
|
|
const {metricStore, dashboardStore, aiFiltersStore} = useStore();
|
|
const metric: any = metricStore.instance;
|
|
|
|
const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length;
|
|
const filtersLength = metric.series[0].filter.filters.filter((i: any) => i && !i.isEvent).length;
|
|
const isClickMap = metric.metricType === CLICKMAP;
|
|
const isPathAnalysis = metric.metricType === USER_PATH;
|
|
const excludeFilterKeys = isClickMap || isPathAnalysis ? eventKeys : [];
|
|
const hasFilters = filtersLength > 0 || eventsLength > 0;
|
|
const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes(metric.metricType);
|
|
|
|
return isPredefined ? <PredefinedMessage/> : (
|
|
<Space direction="vertical" className="w-full">
|
|
<AdditionalFilters/>
|
|
<Card
|
|
styles={{
|
|
body: {padding: '0'},
|
|
cover: {}
|
|
}}
|
|
>
|
|
{!hasFilters && (
|
|
<DefineSteps metric={metric} excludeFilterKeys={excludeFilterKeys}/>
|
|
)}
|
|
</Card>
|
|
|
|
{hasFilters && (
|
|
<FilterSection metric={metric} excludeFilterKeys={excludeFilterKeys}/>
|
|
)}
|
|
</Space>
|
|
);
|
|
}
|
|
|
|
export default observer(WidgetFormNew);
|
|
|
|
|
|
function DefineSteps({metric, excludeFilterKeys}: any) {
|
|
return (
|
|
<Space className="px-4 py-2 rounded-lg shadow-sm">
|
|
<Typography.Text strong>Define Steps</Typography.Text>
|
|
<AddStepButton excludeFilterKeys={excludeFilterKeys} series={metric.series[0]}/>
|
|
</Space>
|
|
);
|
|
}
|
|
|
|
|
|
const FilterSection = observer(({metric, excludeFilterKeys}: any) => {
|
|
// const timeseriesOptions = metricOf.filter((i) => i.type === 'timeseries');
|
|
// const tableOptions = metricOf.filter((i) => i.type === 'table');
|
|
const isTable = metric.metricType === TABLE;
|
|
const isClickMap = metric.metricType === CLICKMAP;
|
|
const isFunnel = metric.metricType === FUNNEL;
|
|
const isInsights = metric.metricType === INSIGHTS;
|
|
const isPathAnalysis = metric.metricType === USER_PATH;
|
|
const isRetention = metric.metricType === RETENTION;
|
|
const canAddSeries = metric.series.length < 3;
|
|
const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length;
|
|
// const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1);
|
|
|
|
const isSingleSeries = isTable || isFunnel || isClickMap || isInsights || isRetention
|
|
|
|
// const onAddFilter = (filter: any) => {
|
|
// metric.series[0].filter.addFilter(filter);
|
|
// metric.updateKey('hasChanged', true)
|
|
// }
|
|
|
|
return (
|
|
<>
|
|
{
|
|
metric.series.length > 0 && metric.series
|
|
.slice(0, isSingleSeries ? 1 : metric.series.length)
|
|
.map((series: any, index: number) => (
|
|
<div className='mb-2' key={series.name}>
|
|
<FilterSeries
|
|
canExclude={isPathAnalysis}
|
|
supportsEmpty={!isClickMap && !isPathAnalysis}
|
|
excludeFilterKeys={excludeFilterKeys}
|
|
observeChanges={() => metric.updateKey('hasChanged', true)}
|
|
hideHeader={isTable || isClickMap || isInsights || isPathAnalysis || isFunnel}
|
|
seriesIndex={index}
|
|
series={series}
|
|
onRemoveSeries={() => metric.removeSeries(index)}
|
|
canDelete={metric.series.length > 1}
|
|
emptyMessage={
|
|
isTable
|
|
? 'Filter data using any event or attribute. Use Add Step button below to do so.'
|
|
: 'Add user event or filter to define the series by clicking Add Step.'
|
|
}
|
|
expandable={isSingleSeries}
|
|
/>
|
|
</div>
|
|
))
|
|
}
|
|
|
|
{!isSingleSeries && canAddSeries && (
|
|
<Card styles={{body: {padding: '4px'}}}>
|
|
<Button
|
|
type='link'
|
|
onClick={() => {
|
|
metric.addSeries();
|
|
|
|
}}
|
|
disabled={!canAddSeries}
|
|
size="small"
|
|
>
|
|
<Space>
|
|
<AudioWaveform size={16}/>
|
|
New Chart Series
|
|
</Space>
|
|
</Button>
|
|
</Card>
|
|
)}
|
|
</>
|
|
);
|
|
})
|
|
|
|
|
|
const PathAnalysisFilter = observer(({metric}: any) => (
|
|
<Card styles={{
|
|
body: {padding: '4px 20px'},
|
|
header: {padding: '4px 20px', fontSize: '14px', fontWeight: 'bold', borderBottom: 'none'},
|
|
}}
|
|
title={metric.startType === 'start' ? 'Start Point' : 'End Point'}
|
|
>
|
|
<div className='form-group flex flex-col'>
|
|
<FilterItem
|
|
hideDelete
|
|
filter={metric.startPoint}
|
|
allowedFilterKeys={[FilterKey.LOCATION, FilterKey.CLICK, FilterKey.INPUT, FilterKey.CUSTOM]}
|
|
onUpdate={val => metric.updateStartPoint(val)}
|
|
onRemoveFilter={() => {
|
|
}}
|
|
/>
|
|
</div>
|
|
</Card>
|
|
));
|
|
|
|
const AdditionalFilters = observer(() => {
|
|
const {metricStore, dashboardStore, aiFiltersStore} = useStore();
|
|
const metric: any = metricStore.instance;
|
|
|
|
return (
|
|
<Space direction="vertical" className="w-full">
|
|
{metric.metricType === USER_PATH && <PathAnalysisFilter metric={metric}/>}
|
|
</Space>
|
|
)
|
|
});
|
|
|
|
|
|
const PredefinedMessage = () => (
|
|
<div className='flex items-center my-6 justify-center'>
|
|
<Icon name='info-circle' size='18' color='gray-medium'/>
|
|
<div className='ml-2'>Filtering and drill-downs will be supported soon for this card type.</div>
|
|
</div>
|
|
);
|