From 170e85b505e2b52b0173f42c2986c5af457de95e Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Mon, 25 Nov 2024 17:44:49 +0100 Subject: [PATCH] ui: some changes for card creation flow, add series table to CustomMetricLineChart.tsx --- .../CustomMetricLineChart.tsx | 280 ++++++++++++++---- .../Dashboard/Widgets/common/Styles.js | 7 +- .../AddCardSection/AddCardSection.tsx | 102 +++++-- .../NewDashModal/ExampleCards.tsx | 4 +- .../DashboardWidgetGrid.tsx | 2 +- .../components/FilterSeries/FilterSeries.tsx | 6 +- .../MetricViewHeader/MetricViewHeader.tsx | 243 ++++++++------- .../components/WidgetChart/WidgetChart.tsx | 1 - .../components/WidgetForm/WidgetFormNew.tsx | 1 + .../components/WidgetView/WidgetView.tsx | 4 +- frontend/app/components/Overview/Overview.tsx | 13 +- .../shared/Filters/FilterList/FilterList.tsx | 2 +- .../Filters/FilterModal/FilterModal.tsx | 55 +--- .../FilterSelection/FilterSelection.tsx | 6 +- .../SessionsTabOverview.tsx | 8 +- .../components/Notes/NotesRoute.tsx | 21 ++ .../SessionHeader/SessionHeader.tsx | 11 - frontend/app/mstore/metricStore.ts | 1 + frontend/app/mstore/projectsStore.ts | 4 + frontend/app/mstore/types/widget.ts | 2 +- 20 files changed, 501 insertions(+), 272 deletions(-) create mode 100644 frontend/app/components/shared/SessionsTabOverview/components/Notes/NotesRoute.tsx diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx index f898da57c..8d3b424ef 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx @@ -1,74 +1,224 @@ -import React from 'react' -import {Styles} from '../../common'; -import {ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip} from 'recharts'; -import {LineChart, Line, Legend} from 'recharts'; +import React, { useState } from 'react'; +import { formatTimeOrDate } from 'App/date'; +import { Button, Table } from 'antd'; +import type { TableProps } from 'antd'; + +import { Eye, EyeOff } from 'lucide-react'; +import { Styles } from '../../common'; +import { + ResponsiveContainer, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + LineChart, + Line, + Legend, +} from 'recharts'; interface Props { - data: any; - params: any; - // seriesMap: any; - colors: any; - onClick?: (event, index) => void; - yaxis?: any; - label?: string; - hideLegend?: boolean; + data: any; + params: any; + colors: any; + onClick?: (event, index) => void; + yaxis?: any; + label?: string; + hideLegend?: boolean; } +const initTableProps = [{ + title: 'Series', + dataIndex: 'seriesName', + key: 'seriesName', +}, + { + title: 'Avg.', + dataIndex: 'average', + key: 'average', + } +] + function CustomMetricLineChart(props: Props) { - const { - data = {chart: [], namesMap: []}, - params, - colors, - onClick = () => null, - yaxis = {...Styles.yaxis}, - label = 'Number of Sessions', - hideLegend = false, - } = props; + const { + data = { chart: [], namesMap: [] }, + params, + colors, + onClick = () => null, + yaxis = { ...Styles.yaxis }, + label = 'Number of Sessions', + hideLegend = false, + } = props; + const [showTable, setShowTable] = useState(false); + const hasMultipleSeries = data.namesMap.length > 1; + const [tableData, setTableData] = useState([]); + const [tableProps, setTableProps] = useState(initTableProps); + // console.log(params.density / 7, data.chart) - return ( - - { + setTableProps(initTableProps) + const series = Object.keys(data.chart[0]) + .filter((key) => key !== 'time' && key !== 'timestamp') + columnNames.clear() + data.chart.forEach((p: any) => { + columnNames.add(p.time) + }) // for example: mon, tue, wed, thu, fri, sat, sun + const avg: any = {} // { seriesName: {itemsCount: 0, total: 0} } + const items: Record[] = []; // as many items (rows) as we have series in filter + series.forEach(s => { + items.push({ seriesName: s, average: 0 }) + avg[s] = { itemsCount: 0, total: 0 } + }) + const tableCols: { title: string, dataIndex: string, key: string }[] = []; + Array.from(columnNames).forEach((name: string) => { + tableCols.push({ + title: name, + dataIndex: name, + key: name, + }) + const values = data.chart.filter((p) => p.time === name) + series.forEach((s) => { + const toDateAvg = values.reduce((acc, curr) => acc + curr[s], 0) / values.length; + avg[s].itemsCount += 1 + avg[s].total += toDateAvg + const ind = items.findIndex((item) => item.seriesName === s) + if (ind === -1) return + items[ind][name] = (values.reduce((acc, curr) => acc + curr[s], 0) / values.length) + .toFixed(2) + }) + }) + Object.keys(avg).forEach((key) => { + const ind = items.findIndex((item) => item.seriesName === key) + if (ind === -1) return + items[ind].average = (avg[key].total / avg[key].itemsCount).toFixed(2) + }) + + setTableProps((prev) => [...prev, ...tableCols]) + setTableData(items) + }, [data.chart.length]) + + return ( +
+ + + {!hideLegend && ( + + )} + + + Styles.tickFormatter(val)} + label={{ + ...Styles.axisLabelLeft, + value: label || 'Number of Sessions', + }} + /> + + {Array.isArray(data.namesMap) && + data.namesMap.map((key, index) => ( + + ))} + + + {hasMultipleSeries ? ( +
+
+
+ +
+ {showTable ? ( + + ) : null} + + ) : null} + + ); } -export default CustomMetricLineChart +function CustomTooltip({ active, payload, label }) { + if (!active) return; + + const shownPayloads = payload.filter((p) => !p.hide); + return ( +
+ {shownPayloads.map((p, index) => ( + <> +
+
+
{index + 1}
+
+
{p.name}
+
+
+
+ {label}, {formatTimeOrDate(p.payload.timestamp)} +
+
{p.value}
+
+ + ))} +
+ ); +} + +export default CustomMetricLineChart; diff --git a/frontend/app/components/Dashboard/Widgets/common/Styles.js b/frontend/app/components/Dashboard/Widgets/common/Styles.js index a6f88bd26..eef6ef5b8 100644 --- a/frontend/app/components/Dashboard/Widgets/common/Styles.js +++ b/frontend/app/components/Dashboard/Widgets/common/Styles.js @@ -29,13 +29,13 @@ export default { axisLine: {stroke: '#CCCCCC'}, interval: 0, dataKey: "time", - tick: {fill: '#999999', fontSize: 9}, + tick: {fill: '#000000', fontSize: 9}, tickLine: {stroke: '#CCCCCC'}, strokeWidth: 0.5 }, yaxis: { axisLine: {stroke: '#CCCCCC'}, - tick: {fill: '#999999', fontSize: 9}, + tick: {fill: '#000000', fontSize: 9}, tickLine: {stroke: '#CCCCCC'}, }, axisLabelLeft: { @@ -50,9 +50,6 @@ export default { tickFormatterBytes: val => Math.round(val / 1024 / 1024), chartMargins: {left: 0, right: 20, top: 10, bottom: 5}, tooltip: { - cursor: { - fill: '#f6f6f6' - }, contentStyle: { padding: '5px', background: 'white', diff --git a/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx b/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx index ca2378642..91636732a 100644 --- a/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx +++ b/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx @@ -11,41 +11,59 @@ import { AppWindow, Combine, Users, - ArrowDown10, Sparkles, } from 'lucide-react'; import { Icon } from 'UI'; +import FilterSeries from "App/mstore/types/filterSeries"; +import { CARD_LIST, CardType } from "../DashboardList/NewDashModal/ExampleCards"; +import { useStore } from 'App/mstore'; +import { + HEATMAP, + FUNNEL, + TABLE, + TIMESERIES, + USER_PATH, +} from 'App/constants/card'; +import { useHistory } from "react-router-dom"; +import { dashboardMetricCreate, withSiteId, metricCreate } from 'App/routes' +import { FilterKey } from 'Types/filter/filterType'; interface TabItem { icon: React.ReactNode; title: string; description: string; + type: string; } const tabItems: Record = { product_analytics: [ { icon: , title: 'Trends', + type: TIMESERIES, description: 'Track session trends over time.', }, { icon: , - title: 'Funnel', + title: 'Funnels', + type: FUNNEL, description: 'Visualize user progression through critical steps.', }, { icon: , title: 'Journeys', + type: USER_PATH, description: 'Understand the paths users take through your product.', }, - { - icon: , - title: 'Retention', - description: 'Analyze user retention over specific time periods.', - }, + // { TODO: 1.23+ + // icon: , + // title: 'Retention', + // type: RETENTION, + // description: 'Analyze user retention over specific time periods.', + // }, { icon: , title: 'Heatmaps', + type: HEATMAP, description: 'Generate a report using by asking AI.', }, ], @@ -53,21 +71,25 @@ const tabItems: Record = { { icon: , title: 'JS Errors', + type: FilterKey.ERRORS, description: 'Monitor JS errors affecting user experience.', }, { icon: , title: 'Top Network Requests', + type: FilterKey.FETCH, description: 'Identify the most frequent network requests.', }, { icon: , title: '4xx/5xx Requests', + type: TIMESERIES + '_4xx_requests', description: 'Track client and server errors for performance issues.', }, { icon: , title: 'Slow Network Requests', + type: TIMESERIES + '_slow_network_requests', description: 'Pinpoint the slowest network requests causing delays.', }, ], @@ -75,37 +97,83 @@ const tabItems: Record = { { icon: , title: 'Top Pages', + type: FilterKey.LOCATION, description: 'Discover the most visited pages on your site.', }, { icon: , title: 'Top Browsers', + type: FilterKey.USER_BROWSER, description: 'Analyze the browsers your visitors are using the most.', }, { icon: , title: 'Top Referrer', + type: FilterKey.REFERRER, description: 'See where your traffic is coming from.', }, { icon: , title: 'Top Users', + type: FilterKey.USERID, description: 'Identify the users with the most interactions.', }, - { - icon: , - title: 'Speed Index by Country', - description: 'Measure performance across different regions.', - }, + // { TODO: 1.23+ maybe + // icon: , + // title: 'Speed Index by Country', + // type: TABLE, + // description: 'Measure performance across different regions.', + // }, ], }; -function CategoryTab({ tab }: { tab: string }) { +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 + }; + + if (selectedCard.filters) { + cardData.series = [ + new FilterSeries().fromJson({ + name: "Series 1", + filter: { + filters: selectedCard.filters, + } + }) + ]; + } + + if (selectedCard.cardType === FUNNEL) { + cardData.series = []; + cardData.series.filter = []; + } + + metricStore.merge(cardData); + metricStore.instance.resetDefaults(); + + 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 (
{items.map((item, index) => (
handleCardSelection(item.type)} key={index} className={ 'flex items-start gap-2 p-2 hover:bg-active-blue rounded-xl hover:text-blue group cursor-pointer' @@ -124,7 +192,7 @@ function CategoryTab({ tab }: { tab: string }) { ); } -function AddCardSection() { +function AddCardSection({ inCards }: { inCards?: boolean }) { const [tab, setTab] = React.useState('product_analytics'); const options = [ { label: 'Product Analytics', value: 'product_analytics' }, @@ -137,9 +205,9 @@ function AddCardSection() { return (
setTab(value)} />
- +
{ list?.length === 0 ? ( -
+
) : ( diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index dc0e225d7..24288fe59 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -124,7 +124,7 @@ function FilterSeries(props: Props) { canExclude = false, expandable = false, } = props; - const [expanded, setExpanded] = useState(!expandable); + const [expanded, setExpanded] = useState(hideHeader || !expandable); const { series, seriesIndex } = props; const [prevLength, setPrevLength] = useState(0); @@ -180,7 +180,7 @@ function FilterSeries(props: Props) { /> )} - {expandable && ( + {!hideHeader && expandable && ( setExpanded(!expanded)} @@ -212,7 +212,7 @@ function FilterSeries(props: Props) { onFilterMove={onFilterMove} excludeFilterKeys={excludeFilterKeys} onAddFilter={onAddFilter} - mergeUp + mergeUp={!hideHeader} /> ) : null}
diff --git a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx index ac9d69bdd..53b2fe3c0 100644 --- a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx @@ -1,70 +1,74 @@ import React, { useEffect } from 'react'; -import { PageTitle, Toggler, Icon } from "UI"; +import { PageTitle, Icon } from 'UI'; import { Segmented, Button } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; +import AddCardSection from '../AddCardSection/AddCardSection'; import MetricsSearch from '../MetricsSearch'; import Select from 'Shared/Select'; import { useStore } from 'App/mstore'; import { observer, useObserver } from 'mobx-react-lite'; import { DROPDOWN_OPTIONS } from 'App/constants/card'; -import AddCardModal from 'Components/Dashboard/components/AddCardModal'; -import { useModal } from 'Components/Modal'; -import AddCardSelectionModal from "Components/Dashboard/components/AddCardSelectionModal"; -import NewDashboardModal from "Components/Dashboard/components/DashboardList/NewDashModal"; +import { INDEXES } from "App/constants/zindex"; -function MetricViewHeader({ siteId }: { siteId: string }) { - const { metricStore } = useStore(); - const filter = metricStore.filter; - const { showModal } = useModal(); - const [showAddCardModal, setShowAddCardModal] = React.useState(false); +function MetricViewHeader() { + const { metricStore } = useStore(); + const filter = metricStore.filter; + const [showAddCardModal, setShowAddCardModal] = React.useState(false); + const modalBgRef = React.useRef(null); - // Set the default sort order to 'desc' - useEffect(() => { - metricStore.updateKey('sort', { by: 'desc' }); - }, [metricStore]); + // Set the default sort order to 'desc' + useEffect(() => { + metricStore.updateKey('sort', { by: 'desc' }); + }, [metricStore]); - return ( -
-
-
- -
-
- -
- -
-
-
+ return ( +
+
+
+ +
+
+ +
+ +
+
+
-
-
- + metricStore.updateKey('filter', { ...filter, type: value.value }) + } + plain={true} + isSearchable={true} + /> - - metricStore.updateKey('filter', { ...filter, dashboard: value }) - } - /> -
+ + metricStore.updateKey('filter', { ...filter, dashboard: value }) + } + /> +
-
- +
+ - {/* */} -
- - setShowAddCardModal(false)} - open={showAddCardModal} - isCreatingNewCard={true} - /> -
- ); + + {showAddCardModal ? ( +
{ + if (modalBgRef.current === e.target) { + setShowAddCardModal(false); + } + }} + className={ + 'fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-gray-lightest' + } + style={{ background: 'rgba(0,0,0,0.5)', zIndex: INDEXES.POPUP_GUIDE_BG }} + > + +
+ ) : null} +
+
+ ); } export default observer(MetricViewHeader); -function DashboardDropdown({ onChange, plain = false }: { plain?: boolean; onChange: any }) { - const { dashboardStore, metricStore } = useStore(); - const dashboardOptions = dashboardStore.dashboards.map((i: any) => ({ - key: i.id, - label: i.name, - value: i.dashboardId - })); +function DashboardDropdown({ + onChange, + plain = false, +}: { + plain?: boolean; + onChange: any; +}) { + const { dashboardStore, metricStore } = useStore(); + const dashboardOptions = dashboardStore.dashboards.map((i: any) => ({ + key: i.id, + label: i.name, + value: i.dashboardId, + })); - return ( - onChange(value)} + isMulti={true} + color="black" + /> + ); } function ListViewToggler() { - const { metricStore } = useStore(); - const listView = useObserver(() => metricStore.listView); - return ( -
- - -
List
-
, - value: 'list' - }, - { - label:
- -
Grid
-
, - value: 'grid' - } - ]} - onChange={(val) => { - metricStore.updateKey('listView', val === 'list') - }} - value={listView ? 'list' : 'grid'} - /> -
- ); + const { metricStore } = useStore(); + const listView = useObserver(() => metricStore.listView); + return ( +
+ + +
List
+
+ ), + value: 'list', + }, + { + label: ( +
+ +
Grid
+
+ ), + value: 'grid', + }, + ]} + onChange={(val) => { + metricStore.updateKey('listView', val === 'list'); + }} + value={listView ? 'list' : 'grid'} + /> +
+ ); } diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 960431b35..da6173eb1 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -57,7 +57,6 @@ function WidgetChart(props: Props) { const prevMetricRef = useRef(); const isMounted = useIsMounted(); const [data, setData] = useState(metric.data); - const isTableWidget = metric.metricType === 'table' && metric.viewType === 'table'; const isPieChart = metric.metricType === 'table' && metric.viewType === 'pieChart'; diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx index e2b2a60da..60b93ee0b 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx @@ -82,6 +82,7 @@ const FilterSection = observer(({ metric, excludeFilterKeys }: any) => { metric.updateKey('hasChanged', true) } + console.log(metric.series, isTable, isClickMap, isInsights, isPathAnalysis, isFunnel) return ( <> {metric.series.length > 0 && diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index 656eaffdc..ec6278a47 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -58,7 +58,9 @@ function WidgetView(props: Props) { } }); } else { - metricStore.init(); + if (!metricStore.instance) { + metricStore.init(); + } } }, []); diff --git a/frontend/app/components/Overview/Overview.tsx b/frontend/app/components/Overview/Overview.tsx index ec7ffe562..660cb9aa2 100644 --- a/frontend/app/components/Overview/Overview.tsx +++ b/frontend/app/components/Overview/Overview.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import withPageTitle from 'HOCs/withPageTitle'; import NoSessionsMessage from 'Shared/NoSessionsMessage'; import MainSearchBar from 'Shared/MainSearchBar'; @@ -12,6 +12,7 @@ import { withRouter, RouteComponentProps, useLocation } from 'react-router-dom'; import FlagView from 'Components/FFlags/FlagView/FlagView'; import { observer } from 'mobx-react-lite'; import { useStore } from '@/mstore'; +import NotesRoute from "../shared/SessionsTabOverview/components/Notes/NotesRoute"; // @ts-ignore interface IProps extends RouteComponentProps { @@ -34,8 +35,11 @@ function Overview({ match: { params } }: IProps) { }, [tab]); return ( - +
@@ -44,6 +48,9 @@ function Overview({ match: { params } }: IProps) {
+ + + diff --git a/frontend/app/components/shared/Filters/FilterList/FilterList.tsx b/frontend/app/components/shared/Filters/FilterList/FilterList.tsx index 002705eaf..093cb0591 100644 --- a/frontend/app/components/shared/Filters/FilterList/FilterList.tsx +++ b/frontend/app/components/shared/Filters/FilterList/FilterList.tsx @@ -52,7 +52,7 @@ export const FilterList = observer((props: Props) => { borderTopRightRadius: props.mergeUp ? 0 : undefined, }} > -
+
Filters
- {/* 1 ? "auto 200px" : 1 }}*/} - {/*>*/} - {/* {matchingCategories.map((key) => {*/} - {/* return (*/} - {/* */} - {/*
*/} - {/* {key}*/} - {/*
*/} - {/*
*/} - {/* {matchingFilters[key] &&*/} - {/* matchingFilters[key].map((filter: Record) => (*/} - {/* onFilterClick({ ...filter, value: [''] })}*/} - {/* >*/} - {/* {getNewIcon(filter)}*/} - {/* {filter.label}*/} - {/*
*/} - {/* ))}*/} - {/*
*/} - {/* */} - {/* );*/} - {/* })}*/} - {/**/} {showSearchList && (
diff --git a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx index 46577daaa..37b844293 100644 --- a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx +++ b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx @@ -4,6 +4,7 @@ import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; import { assist as assistRoute, isRoute } from 'App/routes'; import cn from 'classnames'; import { observer } from 'mobx-react-lite'; +import { getNewIcon } from "../FilterModal/FilterModal"; const ASSIST_ROUTE = assistRoute(); @@ -59,7 +60,7 @@ function FilterSelection(props: Props) { ) : (
setShowModal(true)} > +
+ {getNewIcon(filter)} +
{ if (event.key === 'Enter') { @@ -38,11 +36,7 @@ function SessionsTabOverview() {
- {!isNotesRoute ? ( - - ) : ( - - )} +
); } diff --git a/frontend/app/components/shared/SessionsTabOverview/components/Notes/NotesRoute.tsx b/frontend/app/components/shared/SessionsTabOverview/components/Notes/NotesRoute.tsx new file mode 100644 index 000000000..6affbaf35 --- /dev/null +++ b/frontend/app/components/shared/SessionsTabOverview/components/Notes/NotesRoute.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import NotesList from "./NoteList"; +import NoteTags from "./NoteTags"; + +function NotesRoute() { + return ( +
+
+
+
+

Notes

+ +
+
+ +
+
+ ) +} + +export default NotesRoute \ No newline at end of file diff --git a/frontend/app/components/shared/SessionsTabOverview/components/SessionHeader/SessionHeader.tsx b/frontend/app/components/shared/SessionsTabOverview/components/SessionHeader/SessionHeader.tsx index 9a4100d67..4fd8b0a84 100644 --- a/frontend/app/components/shared/SessionsTabOverview/components/SessionHeader/SessionHeader.tsx +++ b/frontend/app/components/shared/SessionsTabOverview/components/SessionHeader/SessionHeader.tsx @@ -17,9 +17,6 @@ function SessionHeader() { const period = Period({ start: startDate, end: endDate, rangeName: rangeValue }); const title = useMemo(() => { - if (activeTab.type === 'notes') { - return 'Notes'; - } if (activeTab.type === 'bookmarks') { return isEnterprise ? 'Vault' : 'Bookmarks'; } @@ -35,7 +32,6 @@ function SessionHeader() { return (

{title}

- {activeTab.type !== 'notes' ? (
{activeTab.type !== 'bookmarks' && ( <> @@ -48,13 +44,6 @@ function SessionHeader() { )}
- ) : null} - - {activeTab.type === 'notes' && ( -
- -
- )}
); } diff --git a/frontend/app/mstore/metricStore.ts b/frontend/app/mstore/metricStore.ts index 43eb6b223..9e7d9bd53 100644 --- a/frontend/app/mstore/metricStore.ts +++ b/frontend/app/mstore/metricStore.ts @@ -125,6 +125,7 @@ export default class MetricStore { } } + console.log('ch', obj) Object.assign(this.instance, obj); this.instance.updateKey('hasChanged', updateChangeFlag); } diff --git a/frontend/app/mstore/projectsStore.ts b/frontend/app/mstore/projectsStore.ts index c30e1f862..639823d3b 100644 --- a/frontend/app/mstore/projectsStore.ts +++ b/frontend/app/mstore/projectsStore.ts @@ -22,6 +22,10 @@ export default class ProjectsStore { return this.active ? ['ios', 'android'].includes(this.active.platform) : false; } + get activeSiteId() { + return this.active?.id || this.siteId; + } + getSiteId = () => { return { siteId: this.siteId, diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 5745a5a90..fe5b5b977 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -333,7 +333,7 @@ export default class Widget { return unique; }, []); } else { - const updatedData: any = this.calculateTotalSeries(data); + const updatedData: any = data; // we don't use total anymore this.calculateTotalSeries(data); _data['chart'] = getChartFormatter(period)(updatedData); _data['namesMap'] = Array.isArray(updatedData) ? updatedData