* ui: start redesign for live search/list
* ui: remove search field, show filters picker by default for assist
* ui: filter modal wip
* ui: filter modal wip
* ui: finish with omnisearch thing
* ui: start new dashboard redesign
* refining new card section
* ui: some "new dashboard" view improvs, fix icons fill inheritance, add ai button colors
* ui: split up search component (1.22+ tbd?), restrict filter type to own modals
* ui: mimic ant card
* ui: some changes for card creation flow, add series table to CustomMetricLineChart.tsx
* ui: more chart types, add table with filtering out series, start "compare to" thing
* ui: comparison designs
* ui: better granularity support, comparison view for bar chart
* ui: add comparison to more charts, add "metric" chart (BigNumChart.tsx)
* ui: cleanup logs
* ui: fix defualt import, fix sessheader crash, fix condition set ui
* ui: some refactoring and type coverage...
* ui: more refactoring; silence warnings for list renderers
* ui: moveing and renaming filters
* ui: add metricOf selector
* ui: check for metric type
* ui: fix crashes, add widget library table
* ui: change new series btn
* ui: restrict filterselection
* ui: fix timeseries table format
* ui: autoclose autocomplete modal
* ui: some fixes to issue filters default value, display and placeholder consistency
* ui: some dashboard issues with card selection modal and empty states
* ui: comparing for funnels, alternate column view, some refactoring to prepare for customizations...
* Style improvements in omnisearch headers
* Revert "Style improvements in omnisearch headers"
This reverts commit 89e51b0531.
* ui: show health status fetch error
* ui: table, bignum and comp for funnel, add csv export
* Omni-search improvements. (#2823)
Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
* ui: fix bad merge (git hallo?)
* ui: fix filter mapper
* rm husky
* ui: add card floater
* ui: add card floater
* ui: refactor local autocomplete input
* ui: filterout empty options
* UI improvements in New Cards (#2864)
* ui: some minor dashb improvements
* ui: metric type selector for head
* ui: change card type selector, add automapping
* ui: check chart/widget components for crashes
* ui: fix crash with table metrics
* ui: fix crashes related to metric type changes
* ui: filter category for clickmap filt
* ui: fix dash options menu, fix cr/up button
* ui: fix dash list menu propagation
* ui: hide addevent in heatmaps
* ui: fix time mapping for charts
* ui: fix exclusion component for path
* ui: fix series amount for path analysis, rm grid/list selector
* ui: fix icons in list view
* ui: fix for dlt button in widgets
* Various improvements Cards, OmniSearch and Cards Listing (#2881)
* ui: some improvements for cards list view, funnels and general filter display
* ui: longer node width for journey
* Product Analytics UI Improvements. (#2896)
* Various improvements Cards, OmniSearch and Cards Listing
* Improved cards listing page
* Various improvements in product analytics
* Charts UI improvements
---------
Co-authored-by: nick-delirium <nikita@openreplay.com>
* Live se red s2 (#2902)
* Various improvements Cards, OmniSearch and Cards Listing
* Improved cards listing page
* Various improvements in product analytics
* Charts UI improvements
* ui crash
---------
Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
* ui: fix lucide version
* ui: fix custom comparison period
* ui: fix custom comparison period
* ui: handle minor paths on frontend for path/sankey
* ui: assign icon for event types in sankey nodes
* ui: some strings changed
* ui: hide btn control for table view
* Various improvements in graphs, and analytics pages. (#2908)
* Various improvements Cards, OmniSearch and Cards Listing
* Improved cards listing page
* Various improvements in product analytics
* Charts UI improvements
* ui crash
* Chart improvements and layout toggling
* Various improvements
* Tooltips
---------
Co-authored-by: nick-delirium <nikita@openreplay.com>
* ui: fix weekday mapper for x axis on >7d range
* ui: lower default density to 35, fix table card display
* ui: filterMinorPaths -> return input data if nodes arr. is empty
* ui: use default filter for sessions, move around saved search actions, remove tags modal
* ui: fix card creator visibility in grid, fix table exporter visiblility in grid
* ui: fix some proptype warnings
* ui: change new series default expand state
* ui: save comp range in widget details
* ui: move timeseries to apache echarts
* ui: use unique id for window values
* ui: add timestamp for comp tooltip row
* ui: rename var for readability
* ui: fix comparison for 24hr
* Streamlined icons and improved echarts trends (#2920)
* Various improvements Cards, OmniSearch and Cards Listing
* Improved cards listing page
* Various improvements in product analytics
* Charts UI improvements
* ui crash
* Chart improvements and layout toggling
* Various improvements
* Tooltips
* Improved icons in cards listing page
* Update WidgetFormNew.tsx
* Sankey improvements
* Icon and text updates
Text alignment and color changes in x-ray
Icon Mapping with appropriate names and shapes
* Colors and Trend Chart Interaction updates
* ui
---------
Co-authored-by: nick-delirium <nikita@openreplay.com>
* ui: series update observe
* ui: resize chart on window
* ui: move barchart to echarts
* ui: fixing bars under comparison
* ui: fixing horizontal bar tooltip
* ui: rm unused
* ui: keep state in storage
* ui: small fixes for granularity and comparisons
* ui: fix savesearch button, fix comparison period tracking
* ui: fix funnel type selection
* ui: fixing saved search button
* ui: enable error logging, remove immutable reference
* ui: update savedsearch drop
* ui: disable button if no saved
* ui: small ui fixes
* ui: add drill to summary charts, add more options to card category picker
* ui: filter compSeries with table
* ui: swap tag_el operator and value
* ui: fix top countries
* ui: further changes for search/cards
* ui: move focus to session list on line click
* ui: fix issue filter mapper
* ui: fix alert pre-init function, fix metric list options, fix legend placement
* ui: fixes for card library
* ui: work on new sankey chart
* ui: fix metadata prefetch
* ui: moving snakey to echarts
* ui: fix funnel comparison focus
* ui: stale loader
---------
Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
308 lines
8.9 KiB
TypeScript
308 lines
8.9 KiB
TypeScript
import React from 'react';
|
|
import { FolderOutlined } from '@ant-design/icons';
|
|
import { Segmented, Button } from 'antd';
|
|
import {
|
|
LineChart,
|
|
Filter,
|
|
ArrowUpDown,
|
|
WifiOff,
|
|
Turtle,
|
|
FileStack,
|
|
AppWindow,
|
|
Combine,
|
|
Users,
|
|
Sparkles,
|
|
Globe,
|
|
MonitorSmartphone,
|
|
} from 'lucide-react';
|
|
import { Icon } from 'UI';
|
|
import FilterSeries from 'App/mstore/types/filterSeries';
|
|
import { useModal } from 'App/components/Modal';
|
|
import {
|
|
CARD_LIST,
|
|
CardType,
|
|
} from '../DashboardList/NewDashModal/ExampleCards';
|
|
import { useStore } from 'App/mstore';
|
|
import {
|
|
HEATMAP,
|
|
FUNNEL,
|
|
TABLE,
|
|
TIMESERIES,
|
|
USER_PATH,
|
|
CATEGORIES,
|
|
} from 'App/constants/card';
|
|
import { useHistory } from 'react-router-dom';
|
|
import { dashboardMetricCreate, withSiteId, metricCreate } from 'App/routes';
|
|
import { FilterKey } from 'Types/filter/filterType';
|
|
import MetricsLibraryModal from '../MetricsLibraryModal/MetricsLibraryModal';
|
|
import { observer } from 'mobx-react-lite';
|
|
|
|
interface TabItem {
|
|
icon: React.ReactNode;
|
|
title: string;
|
|
description: string;
|
|
type: string;
|
|
}
|
|
export const tabItems: Record<string, TabItem[]> = {
|
|
[CATEGORIES.product_analytics]: [
|
|
{
|
|
icon: <LineChart width={16} />,
|
|
title: 'Trends',
|
|
type: TIMESERIES,
|
|
description: 'Track session trends over time.',
|
|
},
|
|
{
|
|
icon: <Filter width={16} />,
|
|
title: 'Funnels',
|
|
type: FUNNEL,
|
|
description: 'Visualize user progression through critical steps.',
|
|
},
|
|
{
|
|
icon: (
|
|
<Icon name={'dashboards/user-journey'} color={'inherit'} size={16} />
|
|
),
|
|
title: 'Journeys',
|
|
type: USER_PATH,
|
|
description: 'Understand the paths users take through your product.',
|
|
},
|
|
// { TODO: 1.23+
|
|
// icon: <Icon name={'dashboards/cohort-chart'} color={'inherit'} size={16} />,
|
|
// title: 'Retention',
|
|
// type: RETENTION,
|
|
// description: 'Analyze user retention over specific time periods.',
|
|
// },
|
|
{
|
|
icon: <Icon name={'dashboards/heatmap-2'} color={'inherit'} size={16} />,
|
|
title: 'Heatmaps',
|
|
type: HEATMAP,
|
|
description: 'Visualize user interaction patterns on your pages.',
|
|
},
|
|
],
|
|
[CATEGORIES.monitors]: [
|
|
{
|
|
icon: (
|
|
<Icon name={'dashboards/circle-alert'} color={'inherit'} size={16} />
|
|
),
|
|
title: 'JS Errors',
|
|
type: FilterKey.ERRORS,
|
|
description: 'Monitor JS errors affecting user experience.',
|
|
},
|
|
{
|
|
icon: <ArrowUpDown width={16} />,
|
|
title: 'Top Network Requests',
|
|
type: FilterKey.FETCH,
|
|
description: 'Identify the most frequent network requests.',
|
|
},
|
|
{
|
|
icon: <WifiOff width={16} />,
|
|
title: '4xx/5xx Requests',
|
|
type: TIMESERIES + '_4xx_requests',
|
|
description: 'Track client and server errors for performance issues.',
|
|
},
|
|
{
|
|
icon: <Turtle width={16} />,
|
|
title: 'Slow Network Requests',
|
|
type: TIMESERIES + '_slow_network_requests',
|
|
description: 'Pinpoint the slowest network requests causing delays.',
|
|
},
|
|
],
|
|
[CATEGORIES.web_analytics]: [
|
|
{
|
|
icon: <FileStack width={16} />,
|
|
title: 'Top Pages',
|
|
type: FilterKey.LOCATION,
|
|
description: 'Discover the most visited pages on your site.',
|
|
},
|
|
{
|
|
icon: <AppWindow width={16} />,
|
|
title: 'Top Browsers',
|
|
type: FilterKey.USER_BROWSER,
|
|
description: 'Analyze the browsers your visitors are using the most.',
|
|
},
|
|
{
|
|
icon: <Combine width={16} />,
|
|
title: 'Top Referrer',
|
|
type: FilterKey.REFERRER,
|
|
description: 'See where your traffic is coming from.',
|
|
},
|
|
{
|
|
icon: <Users width={16} />,
|
|
title: 'Top Users',
|
|
type: FilterKey.USERID,
|
|
description: 'Identify the users with the most interactions.',
|
|
},
|
|
{
|
|
icon: <Globe width={16} />,
|
|
title: 'Top Countries',
|
|
type: FilterKey.USER_COUNTRY,
|
|
description: 'Track the geographical distribution of your audience.',
|
|
},
|
|
{
|
|
icon: <MonitorSmartphone width={16} />,
|
|
title: 'Top Devices',
|
|
type: FilterKey.USER_DEVICE,
|
|
description: 'Explore the devices used by your users.',
|
|
}
|
|
// { TODO: 1.23+ maybe
|
|
// icon: <ArrowDown10 width={16} />,
|
|
// title: 'Speed Index by Country',
|
|
// type: TABLE,
|
|
// description: 'Measure performance across different regions.',
|
|
// },
|
|
],
|
|
};
|
|
|
|
function CategoryTab({ tab, inCards }: { tab: string; inCards?: boolean }) {
|
|
const items = tabItems[tab];
|
|
const { metricStore, projectsStore, dashboardStore } = useStore();
|
|
const history = useHistory();
|
|
|
|
const handleCardSelection = (card: string) => {
|
|
metricStore.init();
|
|
const selectedCard = CARD_LIST.find((c) => c.key === card) as CardType;
|
|
const cardData: any = {
|
|
metricType: selectedCard.cardType,
|
|
name: selectedCard.title,
|
|
metricOf: selectedCard.metricOf,
|
|
category: card,
|
|
};
|
|
|
|
if (selectedCard.filters) {
|
|
cardData.series = [
|
|
new FilterSeries().fromJson({
|
|
name: 'Series 1',
|
|
filter: {
|
|
filters: selectedCard.filters,
|
|
},
|
|
}),
|
|
];
|
|
}
|
|
|
|
// TODO This code here makes 0 sense
|
|
if (selectedCard.cardType === FUNNEL) {
|
|
cardData.series = [];
|
|
cardData.series.push(new FilterSeries());
|
|
cardData.series[0].filter.addFunnelDefaultFilters();
|
|
cardData.series[0].filter.eventsOrder = 'then';
|
|
cardData.series[0].filter.eventsOrderSupport = ['then'];
|
|
}
|
|
|
|
metricStore.setCardCategory(tab);
|
|
metricStore.merge(cardData);
|
|
|
|
if (projectsStore.activeSiteId) {
|
|
if (inCards) {
|
|
history.push(withSiteId(metricCreate(), projectsStore.activeSiteId));
|
|
} else if (dashboardStore.selectedDashboard) {
|
|
history.push(
|
|
withSiteId(
|
|
dashboardMetricCreate(dashboardStore.selectedDashboard.dashboardId),
|
|
projectsStore.activeSiteId
|
|
)
|
|
);
|
|
}
|
|
}
|
|
};
|
|
return (
|
|
<div className={'flex flex-col gap-3'}>
|
|
{items.map((item, index) => (
|
|
<div
|
|
onClick={() => handleCardSelection(item.type)}
|
|
key={index}
|
|
className={
|
|
'flex items-start gap-2 p-2 hover:bg-active-blue rounded-xl hover:text-teal group cursor-pointer'
|
|
}
|
|
>
|
|
{item.icon}
|
|
<div className={'leading-none'}>
|
|
<div>{item.title}</div>
|
|
<div className={'text-disabled-text group-hover:text-teal/60 text-sm'}>
|
|
{item.description}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const AddCardSection = observer(
|
|
({ inCards, handleOpenChange }: { inCards?: boolean, handleOpenChange?: (isOpen: boolean) => void }) => {
|
|
const { showModal } = useModal();
|
|
const { metricStore, dashboardStore, projectsStore } = useStore();
|
|
const [tab, setTab] = React.useState('product_analytics');
|
|
const options = [
|
|
{ label: 'Product Analytics', value: 'product_analytics' },
|
|
{ label: 'Monitors', value: 'monitors' },
|
|
{ label: 'Web Analytics', value: 'web_analytics' },
|
|
];
|
|
|
|
const originStr = window.env.ORIGIN || window.location.origin;
|
|
const isSaas = /api\.openreplay\.com/.test(originStr);
|
|
const onExistingClick = () => {
|
|
const dashboardId = dashboardStore.selectedDashboard?.dashboardId;
|
|
const siteId = projectsStore.activeSiteId;
|
|
showModal(
|
|
<MetricsLibraryModal siteId={siteId} dashboardId={dashboardId} />,
|
|
{
|
|
right: true,
|
|
width: 800,
|
|
onClose: () => {
|
|
metricStore.updateKey('metricsSearch', '');
|
|
},
|
|
}
|
|
);
|
|
handleOpenChange?.(false);
|
|
};
|
|
return (
|
|
<div
|
|
className={
|
|
'pt-4 pb-6 px-6 rounded-xl bg-white border border-gray-lighter flex flex-col gap-2'
|
|
}
|
|
>
|
|
<div className={'flex justify-between p-2'}>
|
|
<div className={'text-xl font-medium mb-1'}>
|
|
What do you want to visualize?
|
|
</div>
|
|
{isSaas ? (
|
|
<div
|
|
className={'font-medium flex items-center gap-2 cursor-pointer'}
|
|
>
|
|
<Sparkles color={'#3C00FFD8'} size={16} />
|
|
<div className={'ai-gradient'}>Ask AI</div>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
<div>
|
|
<Segmented
|
|
options={options}
|
|
value={tab}
|
|
onChange={(value) => setTab(value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="py-2">
|
|
<CategoryTab tab={tab} inCards={inCards} />
|
|
</div>
|
|
{inCards ? null :
|
|
<div
|
|
className={
|
|
'w-full flex items-center justify-center border-t mt-auto border-t-gray-lighter gap-2 pt-2 cursor-pointer'
|
|
}
|
|
>
|
|
<Button
|
|
className="w-full mt-4 hover:bg-active-blue hover:text-teal"
|
|
type="text"
|
|
variant="text"
|
|
onClick={onExistingClick}
|
|
>
|
|
<FolderOutlined /> Add existing card
|
|
</Button>
|
|
</div>
|
|
}
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
|
|
export default AddCardSection;
|