From fe4bbcda6dde8786100add521bb8b8a9bf967a32 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Mon, 23 Dec 2024 03:56:45 -0500 Subject: [PATCH] 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 --- .../CustomMetricsWidgets/AreaChart.tsx | 9 +- .../Widgets/CustomMetricsWidgets/BarChart.tsx | 81 +++++---- .../CustomMetricsWidgets/BigNumChart.tsx | 4 +- .../CustomChartTooltip.tsx | 67 ++++---- .../CustomMetricsWidgets/CustomLegend.tsx | 39 +++++ .../CustomMetricLineChart.tsx | 161 ++++++++++++------ .../CustomMetricPieChart.tsx | 9 +- .../Dashboard/Widgets/common/Styles.js | 2 + .../DashboardHeader/DashboardHeader.tsx | 6 +- .../DashboardList/DashboardList.tsx | 18 +- .../DashboardList/DashboardSearch.tsx | 2 +- .../NewDashModal/Examples/AreaChartCard.tsx | 2 +- .../DashboardView/DashboardView.tsx | 2 +- .../DashboardWidgetGrid.tsx | 6 +- .../components/FilterSeries/FilterSeries.tsx | 2 + .../FilterSeries/SeriesName/SeriesName.tsx | 4 +- .../MetricListItem/MetricListItem.tsx | 6 +- .../MetricViewHeader/MetricViewHeader.tsx | 50 +++++- .../components/MetricsList/ListView.tsx | 12 +- .../components/MetricsList/MetricsList.tsx | 70 +++++--- .../MetricsSearch/MetricsSearch.tsx | 2 +- .../components/MetricsView/MetricsView.tsx | 2 + .../components/WidgetChart/WidgetChart.tsx | 2 +- .../WidgetDatatable/WidgetDatatable.tsx | 9 +- .../components/WidgetForm/WidgetFormNew.tsx | 27 ++- .../components/WidgetName/WidgetName.tsx | 1 - .../WidgetSessions/WidgetSessions.tsx | 48 ++++-- .../WidgetView/WidgetViewHeader.tsx | 29 ++-- .../Funnels/FunnelWidget/FunnelBar.tsx | 4 +- .../FilterSelection/FilterSelection.tsx | 4 +- 30 files changed, 444 insertions(+), 236 deletions(-) create mode 100644 frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomLegend.tsx diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/AreaChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/AreaChart.tsx index 67e93516a..04caa0c46 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/AreaChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/AreaChart.tsx @@ -44,9 +44,9 @@ function CustomAreaChart(props: Props) { )} { - const radius = Math.min(width / 2, height / 2); + const radius = 4; return ` M${x + radius},${y} H${x + width - radius} - A${radius},${radius} 0 0 1 ${x + width},${y + radius} - V${y + height - radius} - A${radius},${radius} 0 0 1 ${x + width - radius},${y + height} - H${x + radius} - A${radius},${radius} 0 0 1 ${x},${y + height - radius} + Q${x + width},${y} ${x + width},${y + radius} + V${y + height} + H${x} V${y + radius} - A${radius},${radius} 0 0 1 ${x + radius},${y} + Q${x},${y} ${x + radius},${y} Z `; }; @@ -45,17 +43,13 @@ const PillBar = (props) => { return ( - {striped && ( - @@ -64,8 +58,6 @@ const PillBar = (props) => { ); }; - - function CustomBarChart(props: Props) { const { data = { chart: [], namesMap: [] }, @@ -84,7 +76,6 @@ function CustomBarChart(props: Props) { return item; }); - // we mix 1 original, then 1 comparison, etc const mergedNameMap: { data: any, isComp: boolean, index: number }[] = []; for (let i = 0; i < data.namesMap.length; i++) { mergedNameMap.push({ data: data.namesMap[i], isComp: false, index: i }); @@ -92,34 +83,55 @@ function CustomBarChart(props: Props) { mergedNameMap.push({ data: compData.namesMap[i], isComp: true, index: i }); } } + + // Filter out comparison items for legend + const legendItems = mergedNameMap.filter(item => !item.isComp); + return ( - + - + {!hideLegend && ( - + ({ + value: item.data, + type: 'rect', + color: colors[item.index], + id: item.data + }))} + /> )} ( - + )} - legendType={'line'} + legendType="rect" activeBar={ - + } /> ))} @@ -158,4 +181,4 @@ function CustomBarChart(props: Props) { ); } -export default CustomBarChart; +export default CustomBarChart; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/BigNumChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/BigNumChart.tsx index c24ce8fd6..b16247688 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/BigNumChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/BigNumChart.tsx @@ -16,7 +16,7 @@ function BigNumChart(props: Props) { values, } = props; return ( -
+
{values.map((val, i) => ( +
{series}
diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomChartTooltip.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomChartTooltip.tsx index 0065eca3b..5d1f5fe5b 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomChartTooltip.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomChartTooltip.tsx @@ -8,49 +8,44 @@ interface PayloadItem { name: string; value: number; prevValue?: number; + color?: string; + payload?: any; } + interface Props { active: boolean; payload: PayloadItem[]; label: string; - activeKey?: string; + hoveredSeries: string | null; } function CustomTooltip(props: Props) { - const { active, payload, label, activeKey } = props; - if (!active || !payload?.length) return null; + const { active, payload, label, hoveredSeries } = props; + if (!active || !payload?.length || !hoveredSeries) return null; - const shownPayloads: PayloadItem[] = payload.filter((p) => !p.hide); - const currentSeries: PayloadItem[] = []; - const previousSeriesMap: Record = {}; + // Find the current and comparison payloads + const currentPayload = payload.find(p => p.name === hoveredSeries); + const comparisonPayload = payload.find(p => + p.name === `${hoveredSeries.replace(' (Comparison)', '')} (Comparison)` || + p.name === `${hoveredSeries} (Comparison)` + ); - shownPayloads.forEach((item) => { - if (item.name.startsWith('Previous ')) { - const originalName = item.name.replace('Previous ', ''); - previousSeriesMap[originalName] = item.value; - } else { - currentSeries.push(item); - } - }); + if (!currentPayload) return null; - const transformedArray = currentSeries.map((item) => { - const prevValue = previousSeriesMap[item.name] || null; - return { - ...item, - prevValue, - }; - }); + // Create transformed array with comparison data + const transformedArray = [{ + ...currentPayload, + prevValue: comparisonPayload ? comparisonPayload.value : null + }]; + + const isHigher = (item: { value: number; prevValue: number }) => + item.prevValue !== null && item.prevValue < item.value; + + const getPercentDelta = (val: number, prevVal: number) => + (((val - prevVal) / prevVal) * 100).toFixed(2); - const isHigher = (item: { value: number; prevValue: number }) => { - return item.prevValue !== null && item.prevValue < item.value; - }; - const getPercentDelta = (val, prevVal) => { - return (((val - prevVal) / prevVal) * 100).toFixed(2); - }; return ( -
+
{transformedArray.map((p, index) => (
@@ -64,20 +59,20 @@ function CustomTooltip(props: Props) {
-
+
{label}, {formatTimeOrDate(p.payload.timestamp)}
{p.value}
- {p.prevValue ? ( + {p.prevValue !== null && ( - ) : null} + )}
@@ -99,7 +94,7 @@ export function CompareTag({
{!isHigher ? : } @@ -109,4 +104,4 @@ export function CompareTag({ ); } -export default CustomTooltip; +export default CustomTooltip; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomLegend.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomLegend.tsx new file mode 100644 index 000000000..17c22b214 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomLegend.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { Legend } from 'recharts'; + +interface CustomLegendProps { + payload?: any[]; +} + +function CustomLegend({ payload }: CustomLegendProps) { + return ( +
+ {payload?.map((entry) => ( +
+ {entry.value.includes('(Comparison)') ? ( +
+ ) : ( +
+ )} + {entry.value} +
+ ))} +
+ ); +} + +export default CustomLegend; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx index 514b05081..6e64177de 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import CustomTooltip from "../CustomChartTooltip"; import { Styles } from '../../common'; import { @@ -37,10 +37,35 @@ function CustomMetricLineChart(props: Props) { inGrid, } = props; + const [hoveredSeries, setHoveredSeries] = useState(null); + + const handleMouseOver = (key) => () => { + setHoveredSeries(key); + }; + + const handleMouseLeave = () => { + setHoveredSeries(null); + }; + + // const resultChart = data.chart.map((item, i) => { + // if (compData && compData.chart[i]) return { ...compData.chart[i], ...item }; + // return item; + // }); + const resultChart = data.chart.map((item, i) => { - if (compData && compData.chart[i]) return { ...compData.chart[i], ...item } - return item - }) + if (compData && compData.chart[i]) { + const comparisonItem: Record = {}; + Object.keys(compData.chart[i]).forEach(key => { + if (key !== 'time') { + comparisonItem[`${key}_comparison`] = (compData.chart[i] as any)[key]; + } + }); + return { ...item, ...comparisonItem }; + } + return item; + }); + + return ( @@ -48,65 +73,99 @@ function CustomMetricLineChart(props: Props) { data={resultChart} margin={Styles.chartMargins} onClick={onClick} + onMouseLeave={handleMouseLeave} > {!hideLegend && ( - + ({ + value: key, + type: 'line', + color: colors[index], + id: key, + })) + } + /> )} - + Styles.tickFormatter(val)} - label={{ - ...Styles.axisLabelLeft, - value: label || 'Number of Sessions', - }} + label={{ ...Styles.axisLabelLeft, value: label || 'Number of Sessions' }} /> - + } /> + {Array.isArray(data.namesMap) && - data.namesMap.map((key, index) => key ? ( - - ) : null)} - {compData?.namesMap?.map((key, i) => data.namesMap[i] ? ( - - ) : null)} + data.namesMap.map((key, index) => + key ? ( + + ) : null + )} + + {compData?.namesMap?.map((key, i) => + data.namesMap[i] ? ( + + ) : null + )} ); } -export default observer(CustomMetricLineChart); +export default observer(CustomMetricLineChart); \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx index 61afa0f18..0b9896679 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx @@ -63,15 +63,14 @@ function CustomMetricPieChart(props: Props) { > - + ( ))} diff --git a/frontend/app/components/Dashboard/Widgets/common/Styles.js b/frontend/app/components/Dashboard/Widgets/common/Styles.js index 5147ba26a..2bf9c6090 100644 --- a/frontend/app/components/Dashboard/Widgets/common/Styles.js +++ b/frontend/app/components/Dashboard/Widgets/common/Styles.js @@ -8,6 +8,7 @@ const compareColors = ['#192EDB', '#6272FF', '#808DFF', '#B3BBFF', '#C9CFFF']; const compareColorsx = ["#222F99", "#2E3ECC", "#394EFF", "#6171FF", "#8895FF", "#B0B8FF", "#D7DCFF"].reverse(); const customMetricColors = ['#394EFF', '#3EAAAF', '#565D97']; const colorsPie = colors.concat(["#DDDDDD"]); +const safeColors = ['#394EFF', '#3EAAAF', '#9276da', '#ceba64', "#bc6f9d", '#966fbc', '#64ce86', '#e06da3', '#6dabe0']; const countView = count => { const isMoreThanK = count >= 1000; @@ -22,6 +23,7 @@ export default { colorsx, compareColors, compareColorsx, + safeColors, lineColor: '#2A7B7F', lineColorCompare: '#394EFF', strokeColor: compareColors[0], diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index acecd246b..f2dcefbbb 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -2,7 +2,8 @@ import React from 'react'; import BackButton from 'Shared/Breadcrumb/BackButton'; import { withSiteId } from 'App/routes'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { PageTitle, confirm, Tooltip } from 'UI'; +import { PageTitle, confirm } from 'UI'; +import { Tooltip } from 'antd'; import SelectDateRange from 'Shared/SelectDateRange'; import { useStore } from 'App/mstore'; import DashboardOptions from '../DashboardOptions'; @@ -53,7 +54,8 @@ function DashboardHeader(props: Props) { focusTitle={focusTitle} /> -
+ +
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 2a3130f88..cf4f9a1e6 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -1,4 +1,7 @@ -import { LockOutlined, TeamOutlined } from '@ant-design/icons'; + +import { observer } from 'mobx-react-lite'; +import React from 'react'; +import { useHistory } from 'react-router'; import { Empty, Switch, @@ -10,17 +13,13 @@ import { Dropdown, Button, } from 'antd'; -import { observer } from 'mobx-react-lite'; -import React from 'react'; -import { useHistory } from 'react-router'; - +import { LockOutlined, TeamOutlined, MoreOutlined } from '@ant-design/icons'; import { checkForRecent } from 'App/date'; import { useStore } from 'App/mstore'; import Dashboard from 'App/mstore/types/dashboard'; import { dashboardSelected, withSiteId } from 'App/routes'; import CreateDashboardButton from 'Components/Dashboard/components/CreateDashboardButton'; import { Icon, confirm } from 'UI'; -import { EllipsisVertical } from 'lucide-react'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import DashboardEditModal from '../DashboardEditModal'; @@ -106,6 +105,7 @@ function DashboardList() { } checkedChildren={'Team'} unCheckedChildren={'Private'} + className='toggle-team-private' />
@@ -124,7 +124,7 @@ function DashboardList() { }, { - title: 'Options', + title: '', dataIndex: 'dashboardId', width: '5%', render: (id) => ( @@ -161,7 +161,7 @@ function DashboardList() { }, }} > -
diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 8489547fd..dfde9ad8e 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -50,6 +50,7 @@ const FilterSeriesHeader = observer( onRemove: (seriesIndex: any) => void; canDelete: boolean | undefined; toggleExpand: () => void; + onChange: () => void; }) => { const onUpdate = (name: any) => { props.series.update('name', name); @@ -66,6 +67,7 @@ const FilterSeriesHeader = observer( seriesIndex={props.seriesIndex} name={props.series.name} onUpdate={onUpdate} + onChange={props.onChange} /> {!props.expanded && ( void; + onChange: () => void; seriesIndex?: number; } @@ -16,6 +16,7 @@ function SeriesName(props: Props) { const write = ({ target: { value } }) => { setName(value); + props.onChange(); }; const onBlur = () => { @@ -51,6 +52,7 @@ function SeriesName(props: Props) { onBlur={onBlur} onKeyDown={onKeyDown} className="bg-white text-lg border-transparent rounded-lg font-medium ps-2" + maxLength={22} /> ) : ( diff --git a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx index 15c116360..2e7c32ec9 100644 --- a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx +++ b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx @@ -23,7 +23,7 @@ interface Props extends RouteComponentProps { function MetricTypeIcon({ type }: any) { return ( {TYPE_NAMES[type]}
}> - } size="small" className="bg-tealx-lightest mr-2" /> + } size="default" className="bg-tealx-lightest mr-2 cursor-default avatar-card-list-item" /> ); } @@ -171,12 +171,12 @@ const MetricListItem: React.FC = ({ case 'options': return ( <> -
+
-
{renderModal()} diff --git a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx index 03877d352..c62cb4bda 100644 --- a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx @@ -2,6 +2,10 @@ import React, { useEffect } from 'react'; import { PageTitle } from 'UI'; import { Button, Popover } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; +import React, { useState } from 'react'; +import { PageTitle, Icon } from 'UI'; +import { Segmented, Button, Popover, Space, Dropdown, Menu } from 'antd'; +import { PlusOutlined, DownOutlined } from '@ant-design/icons'; import AddCardSection from '../AddCardSection/AddCardSection'; import MetricsSearch from '../MetricsSearch'; import { useStore } from 'App/mstore'; @@ -9,29 +13,63 @@ import { observer } from 'mobx-react-lite'; function MetricViewHeader() { const { metricStore } = useStore(); + const filter = metricStore.filter; + const [showAddCardModal, setShowAddCardModal] = useState(false); useEffect(() => { // Set the default sort order to 'desc' metricStore.updateKey('sort', { by: 'desc' }); }, [metricStore]); + // Handler for dropdown menu selection + const handleMenuClick = ({ key }) => { + metricStore.updateKey('filter', { ...filter, type: key }); + }; + + // Dropdown menu options + const menu = ( + + All Types + {DROPDOWN_OPTIONS.map((option) => ( + {option.label} + ))} + + ); return (
-
-
- +
+
+ + + + + +
-
- } trigger={'click'}> +
+ } + trigger="click" + > -
+ + + +
+
diff --git a/frontend/app/components/Dashboard/components/MetricsList/ListView.tsx b/frontend/app/components/Dashboard/components/MetricsList/ListView.tsx index f7374d1d2..7b92e4e7b 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/ListView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/ListView.tsx @@ -105,7 +105,7 @@ const ListView: React.FC = (props: Props) => { ), dataIndex: 'name', key: 'title', - className: 'cap-first', + className: 'cap-first pl-4', sorter: true, width: '25%', render: (text: string, metric: Metric) => ( @@ -233,13 +233,6 @@ const ListView: React.FC = (props: Props) => { } : undefined } - // footer={() => ( - //
- // - // Select All - // - //
- // )} pagination={{ current: pagination.current, pageSize: pagination.pageSize, @@ -248,7 +241,8 @@ const ListView: React.FC = (props: Props) => { className: 'px-4', showLessItems: true, showTotal: () => totalMessage, - showQuickJumper: true + size: 'small', + simple: 'true', }} /> ); diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 7dfcac286..7b8883f0b 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -1,6 +1,6 @@ -import { observer, useObserver } from 'mobx-react-lite'; +import { observer } from 'mobx-react-lite'; import React, { useEffect, useMemo, useState } from 'react'; -import { NoContent, Pagination, Loader } from 'UI'; +import { NoContent, Loader } from 'UI'; import { useStore } from 'App/mstore'; import { sliceListPerPage } from 'App/utils'; import GridView from './GridView'; @@ -16,6 +16,7 @@ function MetricsList({ }) { const { metricStore, dashboardStore } = useStore(); const metricsSearch = metricStore.filter.query; + const listView = metricStore.listView; const [selectedMetrics, setSelectedMetrics] = useState([]); const dashboard = dashboardStore.selectedDashboard; @@ -77,28 +78,51 @@ function MetricsList({
} - subtext="Utilize cards to visualize key user interactions or product performance metrics." + subtext={ + metricsSearch !== '' + ? '' + : 'Utilize cards to visualize key user interactions or product performance metrics.' + } > - - setSelectedMetrics( - checked - ? cards - .map((i: any) => i.metricId) - .slice(0, 30 - existingCardIds!.length) - : [] - ) - } - showOwn={showOwn} - toggleOwn={toggleOwn} - /> + {listView ? ( + + setSelectedMetrics(checked ? cards.map((i: any) => i.metricId).slice(0, 30 - existingCardIds!.length) : []) + } + /> + ) : ( + <> + +
+
+ Showing{' '} + {Math.min(cards.length, metricStore.pageSize)} out + of {cards.length} cards +
+ metricStore.updateKey('page', page)} + limit={metricStore.pageSize} + debounceRequest={100} + /> +
+ + )} ); diff --git a/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx b/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx index efb197dcc..308f59afd 100644 --- a/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx +++ b/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx @@ -27,7 +27,7 @@ function MetricsSearch() { value={query} allowClear name="metricsSearch" - className="w-full" + className="w-full input-search-card" placeholder="Filter by title or owner" onChange={write} /> diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index 9c799b225..98fa79052 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -11,7 +11,9 @@ function MetricsView({ siteId }: Props) { return (
+
+
); } diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 047fd38e6..c47115c66 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -56,7 +56,7 @@ function WidgetChart(props: Props) { const period = dashboardStore.period; const drillDownPeriod = dashboardStore.drillDownPeriod; const drillDownFilter = dashboardStore.drillDownFilter; - const colors = Styles.customMetricColors; + const colors = Styles.safeColors; const [loading, setLoading] = useState(true); const params = { density: dashboardStore.selectedDensity }; const metricParams = _metric.params; diff --git a/frontend/app/components/Dashboard/components/WidgetDatatable/WidgetDatatable.tsx b/frontend/app/components/Dashboard/components/WidgetDatatable/WidgetDatatable.tsx index e9a5f6e4e..75e66de0e 100644 --- a/frontend/app/components/Dashboard/components/WidgetDatatable/WidgetDatatable.tsx +++ b/frontend/app/components/Dashboard/components/WidgetDatatable/WidgetDatatable.tsx @@ -112,12 +112,13 @@ function WidgetDatatable(props: Props) { return (
)} ); diff --git a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx index bc503dfb7..38c9fd5d7 100644 --- a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx +++ b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx @@ -1,5 +1,4 @@ import React, { useState, useRef, useEffect } from 'react'; -import { Icon } from 'UI'; import { Input, Tooltip } from 'antd'; import cn from 'classnames'; diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index 782fc6a57..183ba3bd3 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -1,6 +1,8 @@ import React, { useEffect, useState } from 'react'; -import { NoContent, Loader, Pagination, Button } from 'UI'; -import Select from 'Shared/Select'; +import { NoContent, Loader, Pagination } from 'UI'; +import {Button, Tag, Tooltip, Select, Dropdown} from 'antd'; +import {UndoOutlined, DownOutlined} from '@ant-design/icons' +//import Select from 'Shared/Select'; import cn from 'classnames'; import { useStore } from 'App/mstore'; import SessionItem from 'Shared/SessionItem'; @@ -11,7 +13,6 @@ import useIsMounted from 'App/hooks/useIsMounted'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import { numberWithCommas } from 'App/utils'; import { HEATMAP } from 'App/constants/card'; -import { Tag } from 'antd'; interface Props { className?: string; @@ -34,6 +35,15 @@ function WidgetSessions(props: Props) { const filterText = filter.filters.length > 0 ? filter.filters[0].value : ''; const metaList = customFieldStore.list.map((i: any) => i.key); + const seriesDropdownItems = seriesOptions.map((option) => ({ + key: option.value, + label: ( +
setActiveSeries(option.value)}> + {option.label} +
+ ) + })); + const writeOption = ({ value }: any) => setActiveSeries(value.value); useEffect(() => { if (!data) return; @@ -119,27 +129,39 @@ function WidgetSessions(props: Props) {
-
+

{metricStore.clickMapSearch ? 'Clicks' : 'Sessions'}

{metricStore.clickMapLabel ? `on "${metricStore.clickMapLabel}" ` : null} between {startTime} and{' '} {endTime}{' '}
+ {hasFilters && }
- {hasFilters && widget.metricType === 'table' && -
{filterText}
} + {hasFilters && widget.metricType === 'table' &&
{filterText}
} +
- {hasFilters && } - {widget.metricType !== 'table' && widget.metricType !== HEATMAP && ( -
- Filter by Series -