From 6c1c2295cb23b7a1938f718d20be6dacf274334c Mon Sep 17 00:00:00 2001 From: sylenien Date: Tue, 9 Aug 2022 16:16:52 +0200 Subject: [PATCH 01/24] fix(ui): small ui changes for dashboards and metrics --- .../MetricListItem/MetricListItem.tsx | 13 +++---- .../components/MetricsList/MetricsList.tsx | 17 +++++---- .../MetricsSearch/MetricsSearch.tsx | 4 +-- .../components/MetricsView/MetricsView.tsx | 10 ++++-- .../components/WidgetForm/WidgetForm.tsx | 33 ++++------------- .../WidgetPreview/WidgetPreview.tsx | 36 ++++++++++++++++--- frontend/app/components/ui/SVG.tsx | 4 ++- frontend/app/svg/icons/columns-gap-filled.svg | 3 ++ frontend/app/svg/icons/info-circle-fill.svg | 3 ++ frontend/app/utils.ts | 2 +- 10 files changed, 72 insertions(+), 53 deletions(-) create mode 100644 frontend/app/svg/icons/columns-gap-filled.svg create mode 100644 frontend/app/svg/icons/info-circle-fill.svg diff --git a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx index 492a41bd5..38af42702 100644 --- a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx +++ b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx @@ -51,8 +51,8 @@ function MetricTypeIcon({ type }: any) { return ( -
- +
+
) @@ -63,7 +63,7 @@ function MetricListItem(props: Props) { return ( -
+
{/*
@@ -76,17 +76,14 @@ function MetricListItem(props: Props) {
{/*
*/} -
- -
{metric.owner}
-
+
{metric.isPublic ? 'Team' : 'Private'}
-
{metric.lastModified && checkForRecent(metric.lastModified, 'LLL dd, yyyy, hh:mm a')}
+
{metric.lastModified && checkForRecent(metric.lastModified, 'LLL dd, yyyy, hh:mm a')}
); } diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 3cc6dff40..983d70603 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -27,6 +27,7 @@ function MetricsList(props: Props) { metricStore.updateKey('sessionsPage', 1); }, []) + console.log(list, list.length) return useObserver(() => ( } > -
-
-
Metric
+
+
+
Title
{/*
Type
*/} -
Dashboards
Owner
-
Visibility
-
Last Modified
+
Visibility
+
Last Modified
{sliceListPerPage(list, metricStore.page - 1, metricStore.pageSize).map((metric: any) => ( @@ -54,7 +54,10 @@ function MetricsList(props: Props) { ))}
-
+
+
+ Showing {Math.min(list.length, metricStore.pageSize)} out of {list.length} Sessions +
@@ -31,4 +31,4 @@ function MetricsSearch(props) { )); } -export default MetricsSearch; \ No newline at end of file +export default MetricsSearch; diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index a8c1d96c4..216d1369b 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -18,17 +18,21 @@ function MetricsView(props: Props) { metricStore.fetchList(); }, []); return useObserver(() => ( -
-
+
+
{metricsCount}
-
+
+
+ + Create custom Metrics to capture key interactions and track KPIs. +
)); diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx index 88e0a59b4..40e80a7c9 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { metricTypes, metricOf, issueOptions } from 'App/constants/filterOptions'; import { FilterKey } from 'Types/filter/filterType'; import { useStore } from 'App/mstore'; @@ -8,7 +8,6 @@ import FilterSeries from '../FilterSeries'; import { confirm, Popup } from 'UI'; import Select from 'Shared/Select' import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes' -import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelectionModal'; interface Props { history: any; @@ -17,8 +16,8 @@ interface Props { } function WidgetForm(props: Props) { - const [showDashboardSelectionModal, setShowDashboardSelectionModal] = useState(false); - const { history, match: { params: { siteId, dashboardId, metricId } } } = props; + + const { history, match: { params: { siteId, dashboardId } } } = props; const { metricStore, dashboardStore } = useStore(); const dashboards = dashboardStore.dashboards; const isSaving = useObserver(() => metricStore.isSaving); @@ -201,31 +200,13 @@ function WidgetForm(props: Props) {
{metric.exists() && ( - <> - - - + )}
- { canAddToDashboard && ( - setShowDashboardSelectionModal(false)} - /> - )}
)); } diff --git a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx index bde05f398..3cc02fd76 100644 --- a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx @@ -2,19 +2,22 @@ import React from 'react'; import cn from 'classnames'; import WidgetWrapper from '../WidgetWrapper'; import { useStore } from 'App/mstore'; -import { SegmentSelection } from 'UI'; +import { SegmentSelection, Button, Icon } from 'UI'; import { useObserver } from 'mobx-react-lite'; import SelectDateRange from 'Shared/SelectDateRange'; import { FilterKey } from 'Types/filter/filterType'; import WidgetDateRange from '../WidgetDateRange/WidgetDateRange'; // import Period, { LAST_24_HOURS, LAST_30_DAYS } from 'Types/app/period'; +import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelectionModal'; interface Props { className?: string; } function WidgetPreview(props: Props) { + const [showDashboardSelectionModal, setShowDashboardSelectionModal] = React.useState(false); const { className = '' } = props; const { metricStore, dashboardStore } = useStore(); + const dashboards = dashboardStore.dashboards; const metric: any = useObserver(() => metricStore.instance); const isTimeSeries = metric.metricType === 'timeseries'; const isTable = metric.metricType === 'table'; @@ -53,9 +56,12 @@ function WidgetPreview(props: Props) { } } + const canAddToDashboard = metric.exists() && dashboards.length > 0; + return useObserver(() => ( -
-
+ <> +
+

{getWidgetTitle()}

@@ -99,13 +105,33 @@ function WidgetPreview(props: Props) { )}
+ {/* add to dashboard */} + {metric.exists() && ( + + )}
-
+
+ { canAddToDashboard && ( + setShowDashboardSelectionModal(false)} + /> + )} + )); } -export default WidgetPreview; \ No newline at end of file +export default WidgetPreview; diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index d5cd23f17..dd207816e 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -111,6 +111,7 @@ const SVG = (props: Props) => { case 'cog': return ; case 'cogs': return ; case 'collection': return ; + case 'columns-gap-filled': return ; case 'columns-gap': return ; case 'console/error': return ; case 'console/exception': return ; @@ -230,7 +231,8 @@ const SVG = (props: Props) => { case 'hourglass-start': return ; case 'id-card': return ; case 'image': return ; - case 'info-circle': return ; + case 'info-circle-fill': return ; + case 'info-circle': return ; case 'info-square': return ; case 'info': return ; case 'inspect': return ; diff --git a/frontend/app/svg/icons/columns-gap-filled.svg b/frontend/app/svg/icons/columns-gap-filled.svg new file mode 100644 index 000000000..4bb29842d --- /dev/null +++ b/frontend/app/svg/icons/columns-gap-filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app/svg/icons/info-circle-fill.svg b/frontend/app/svg/icons/info-circle-fill.svg new file mode 100644 index 000000000..9af7ae43b --- /dev/null +++ b/frontend/app/svg/icons/info-circle-fill.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app/utils.ts b/frontend/app/utils.ts index 9444e121e..142016d2b 100644 --- a/frontend/app/utils.ts +++ b/frontend/app/utils.ts @@ -347,4 +347,4 @@ export const compareJsonObjects = (obj1: any, obj2: any) => { export const getInitials = (name: any) => { const names = name.split(' '); return names.slice(0, 2).map((n: any) => n[0]).join(''); -} \ No newline at end of file +} From 0f3f883a2761e18780076edc7758a048d33a1224 Mon Sep 17 00:00:00 2001 From: sylenien Date: Tue, 9 Aug 2022 16:23:48 +0200 Subject: [PATCH 02/24] fix(ui): small ui changes for dashboards and metrics --- .../components/Dashboard/components/MetricsList/MetricsList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 983d70603..2171822c9 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -56,7 +56,7 @@ function MetricsList(props: Props) {
- Showing {Math.min(list.length, metricStore.pageSize)} out of {list.length} Sessions + Showing {Math.min(list.length, metricStore.pageSize)} out of {list.length} metrics
Date: Wed, 10 Aug 2022 10:51:49 +0200 Subject: [PATCH 03/24] fix(ui): change dashboards overview --- .../DashboardList/DashboardList.tsx | 73 +++++++++++ .../DashboardList/DashboardListItem.tsx | 55 +++++++++ .../DashboardList/DashboardSearch.tsx | 36 ++++++ .../DashboardList/DashboardsView.tsx | 28 +++++ .../components/DashboardList/index.ts | 1 + .../DashboardRouter/DashboardRouter.tsx | 5 +- .../DashboardSideMenu/DashboardSideMenu.tsx | 113 ++++-------------- .../DashboardView/DashboardView.tsx | 24 ++-- .../components/MetricsList/MetricsList.tsx | 15 +-- .../MetricsSearch/MetricsSearch.tsx | 2 +- .../app/components/ui/NoContent/NoContent.tsx | 2 +- .../ui/SideMenuitem/SideMenuitem.js | 4 +- frontend/app/mstore/dashboardStore.ts | 12 ++ frontend/app/mstore/types/dashboard.ts | 9 +- frontend/app/utils.ts | 4 +- 15 files changed, 261 insertions(+), 122 deletions(-) create mode 100644 frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardList/index.ts diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx new file mode 100644 index 000000000..93649babf --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -0,0 +1,73 @@ +import { observer } from 'mobx-react-lite'; +import React from 'react'; +import { NoContent, Pagination } from 'UI'; +import { useStore } from 'App/mstore'; +import { getRE } from 'App/utils'; +import { sliceListPerPage } from 'App/utils'; +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; +import DashboardListItem from './DashboardListItem'; + +const filterList = >(list: T[], searchQuery: string): T[] => { + const filterRE = getRE(searchQuery, 'i'); + console.log(filterRE) + let _list = list.filter((w: T) => { + console.log(w.name, w.owner, w.description, filterRE.test(w.name)) + return filterRE.test(w.name) || filterRE.test(w.owner) || filterRE.test(w.description); + }); + return _list +} + +function DashboardList() { + const { dashboardStore } = useStore(); + const [shownDashboards, setDashboards] = React.useState([]); + const dashboards = dashboardStore.dashboards; + const dashboardsSearch = dashboardStore.dashboardsSearch; + + React.useEffect(() => { + setDashboards(filterList(dashboards, dashboardsSearch)) + }, [dashboardsSearch]) + + const list = dashboardsSearch !== '' ? shownDashboards : dashboards; + const lenth = list.length; + + return ( + + +
No data available.
+
+ } + > +
+
+
Title
+
Visibility
+
Created
+
+ + {sliceListPerPage(list, dashboardStore.page - 1, dashboardStore.pageSize).map((dashboard: any) => ( + + + + ))} +
+ +
+
+ Showing {Math.min(list.length, dashboardStore.pageSize)} out of {list.length} Dashboards +
+ dashboardStore.updateKey('page', page)} + limit={dashboardStore.pageSize} + debounceRequest={100} + /> +
+ + ); +} + +export default observer(DashboardList); diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx new file mode 100644 index 000000000..8a40c2139 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { Icon } from 'UI'; +import { connect } from 'react-redux'; +import{ IDashboard } from "App/mstore/types/dashboard"; +import { checkForRecent } from 'App/date'; +import { withSiteId, dashboardSelected } from 'App/routes'; +import { useStore } from 'App/mstore'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; + +interface Props extends RouteComponentProps { + dashboard: IDashboard; + siteId: string; +} + +function DashboardListItem(props: Props) { + const { dashboard, siteId, history } = props; + const { dashboardStore } = useStore(); + + const onItemClick = () => { + dashboardStore.selectDashboardById(dashboard.dashboardId); + const path = withSiteId(dashboardSelected(dashboard.dashboardId), siteId); + history.push(path); + }; + return ( + <> +
+
+
+
+ +
+
+ {dashboard.name} +
+
+
+ {/*
*/} +
+
+ + {dashboard.isPublic ? 'Team' : 'Private'} +
+
+
+ {checkForRecent(dashboard.createdAt, 'LLL dd, yyyy, hh:mm a')} +
+
+
+ {dashboard.description} +
+ + ); +} + +export default connect(state => ({ siteId: state.getIn([ 'site', 'siteId' ]) }))(withRouter(DashboardListItem)) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx new file mode 100644 index 000000000..a3b13f1d3 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx @@ -0,0 +1,36 @@ +import React, { useEffect, useState } from 'react'; +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; +import { Icon } from 'UI'; +import { debounce } from 'App/utils'; + +let debounceUpdate: any = () => {} + +function DashboardSearch() { + const { dashboardStore } = useStore(); + const [query, setQuery] = useState(dashboardStore.dashboardsSearch); + useEffect(() => { + debounceUpdate = debounce((key: string, value: any) => dashboardStore.updateKey(key, value), 500); + }, []) + + // @ts-ignore + const write = ({ target: { value } }) => { + setQuery(value); + debounceUpdate('dashboardsSearch', value); + } + + return ( +
+ + +
+ ); +} + +export default observer(DashboardSearch); diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx new file mode 100644 index 000000000..5ebe9e150 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Button, PageTitle, Icon, Link } from 'UI'; +import withPageTitle from 'HOCs/withPageTitle'; +import DashboardList from './DashboardList'; +import DashboardSearch from './DashboardSearch'; + +function DashboardsView() { + return ( +
+
+
+ +
+ +
+ +
+
+
+ + A dashboard is a custom visualization using your OpenReplay data. +
+ +
+ ); +} + +export default withPageTitle('Dashboards - OpenReplay')(DashboardsView); diff --git a/frontend/app/components/Dashboard/components/DashboardList/index.ts b/frontend/app/components/Dashboard/components/DashboardList/index.ts new file mode 100644 index 000000000..61e485dc9 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/index.ts @@ -0,0 +1 @@ +export { default } from './DashboardsView'; diff --git a/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx b/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx index 4df856619..a7e71ffbd 100644 --- a/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx +++ b/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx @@ -16,6 +16,7 @@ import DashboardView from '../DashboardView'; import MetricsView from '../MetricsView'; import WidgetView from '../WidgetView'; import WidgetSubDetailsView from '../WidgetSubDetailsView'; +import DashboardsView from '../DashboardList'; function DashboardViewSelected({ siteId, dashboardId }) { return ( @@ -44,8 +45,8 @@ function DashboardRouter(props: Props) { - - + + diff --git a/frontend/app/components/Dashboard/components/DashboardSideMenu/DashboardSideMenu.tsx b/frontend/app/components/Dashboard/components/DashboardSideMenu/DashboardSideMenu.tsx index 00b462bbd..2c4a4091e 100644 --- a/frontend/app/components/Dashboard/components/DashboardSideMenu/DashboardSideMenu.tsx +++ b/frontend/app/components/Dashboard/components/DashboardSideMenu/DashboardSideMenu.tsx @@ -1,113 +1,40 @@ -//@ts-nocheck -import { useObserver } from 'mobx-react-lite'; import React from 'react'; -import { SideMenuitem, SideMenuHeader, Icon, Popup, Button } from 'UI'; -import { useStore } from 'App/mstore'; -import { withRouter } from 'react-router-dom'; -import { withSiteId, dashboardSelected, metrics } from 'App/routes'; -import { useModal } from 'App/components/Modal'; -import DashbaordListModal from '../DashbaordListModal'; -import DashboardModal from '../DashboardModal'; -import cn from 'classnames'; +import { SideMenuitem, SideMenuHeader } from 'UI'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { withSiteId, metrics, dashboard } from 'App/routes'; import { connect } from 'react-redux'; import { compose } from 'redux' import { setShowAlerts } from 'Duck/dashboard'; -// import stl from 'Shared/MainSearchBar/mainSearchBar.module.css'; -const SHOW_COUNT = 8; - -interface Props { +interface Props extends RouteComponentProps { siteId: string history: any setShowAlerts: (show: boolean) => void } -function DashboardSideMenu(props: RouteComponentProps) { +function DashboardSideMenu(props: Props) { const { history, siteId, setShowAlerts } = props; - const { hideModal, showModal } = useModal(); - const { dashboardStore } = useStore(); - const dashboardId = useObserver(() => dashboardStore.selectedDashboard?.dashboardId); - const dashboardsPicked = useObserver(() => dashboardStore.dashboards.slice(0, SHOW_COUNT)); - const remainingDashboardsCount = dashboardStore.dashboards.length - SHOW_COUNT; const isMetric = history.location.pathname.includes('metrics'); + const isDashboards = history.location.pathname.includes('dashboard'); - const redirect = (path) => { + const redirect = (path: string) => { history.push(path); } - const onItemClick = (dashboard) => { - dashboardStore.selectDashboardById(dashboard.dashboardId); - const path = withSiteId(dashboardSelected(dashboard.dashboardId), parseInt(siteId)); - history.push(path); - }; - - const onAddDashboardClick = (e) => { - dashboardStore.initDashboard(); - showModal(, { right: true }) - } - - const togglePinned = (dashboard, e) => { - e.stopPropagation(); - dashboardStore.updatePinned(dashboard.dashboardId); - } - - return useObserver(() => ( + return (
- <> - - Create - - - } + text="Preferences" /> - {dashboardsPicked.map((item: any) => ( - onItemClick(item)} - className="group" - leading = {( -
- {item.isPublic && ( - -
-
- )} - {item.isPinned &&
} - {!item.isPinned && ( - -
togglePinned(item, e)} - > - -
-
- )} -
- )} - /> - ))} -
- {remainingDashboardsCount > 0 && ( -
showModal(, {})} - > - {remainingDashboardsCount} More -
- )} -
+
+ redirect(withSiteId(dashboard(), siteId))} + /> +
) { />
- )); + ); } export default compose( withRouter, connect(null, { setShowAlerts }), -)(DashboardSideMenu) as React.FunctionComponent> +)(DashboardSideMenu) diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index 108d961a5..e3aa0c2f2 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -15,8 +15,10 @@ import withPageTitle from "HOCs/withPageTitle"; import withReport from "App/components/hocs/withReport"; import DashboardOptions from "../DashboardOptions"; import SelectDateRange from "Shared/SelectDateRange"; +// @ts-ignore import DashboardIcon from "../../../../svg/dashboard-icn.svg"; import { Tooltip } from "react-tippy"; +import Breadcrumb from 'Shared/Breadcrumb'; interface IProps { siteId: string; @@ -69,6 +71,10 @@ function DashboardView(props: Props) { dashboardStore.selectDefaultDashboard(); }, [siteId]) + useEffect(() => { + dashboardStore.selectDashboardById(dashboardId); + }, [dashboardId]) + const onAddWidgets = () => { dashboardStore.initDashboard(dashboard); showModal( @@ -138,15 +144,6 @@ function DashboardView(props: Props) {
} size="small" - subtext={ - - } >
setShowEditModal(false)} focusTitle={focusTitle} /> +
metricStore.metrics); const metricsSearch = useObserver(() => metricStore.metricsSearch); - const filterList = (list) => { + const filterList = >(list: T[]): T[] => { const filterRE = getRE(metricsSearch, 'i'); - let _list = list.filter(w => { - const dashbaordNames = w.dashboards.map(d => d.name).join(' '); + let _list = list.filter((w: T) => { + const dashbaordNames = w.dashboards.map((d: any) => d.name).join(' '); return filterRE.test(w.name) || filterRE.test(w.metricType) || filterRE.test(w.owner) || filterRE.test(dashbaordNames); }); return _list } - const list: any = metricsSearch !== '' ? filterList(metrics) : metrics; + const list = metricsSearch !== '' ? filterList(metrics) : metrics; const lenth = list.length; useEffect(() => { metricStore.updateKey('sessionsPage', 1); }, []) - console.log(list, list.length) return useObserver(() => ( - +
No data available.
} @@ -41,7 +39,6 @@ function MetricsList(props: Props) {
Title
- {/*
Type
*/}
Owner
Visibility
Last Modified
diff --git a/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx b/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx index 582851842..cf27661d9 100644 --- a/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx +++ b/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx @@ -12,7 +12,7 @@ function MetricsSearch(props) { debounceUpdate = debounce((key, value) => metricStore.updateKey(key, value), 500); }, []) - const write = ({ target: { name, value } }) => { + const write = ({ target: { value } }) => { setQuery(value); debounceUpdate('metricsSearch', value); } diff --git a/frontend/app/components/ui/NoContent/NoContent.tsx b/frontend/app/components/ui/NoContent/NoContent.tsx index 10a7e72e7..ae26731be 100644 --- a/frontend/app/components/ui/NoContent/NoContent.tsx +++ b/frontend/app/components/ui/NoContent/NoContent.tsx @@ -7,7 +7,7 @@ interface Props { subtext?: any; icon?: string; iconSize?: number; - size?: number; + size?: string; show?: boolean; children?: any; image?: any; diff --git a/frontend/app/components/ui/SideMenuitem/SideMenuitem.js b/frontend/app/components/ui/SideMenuitem/SideMenuitem.js index ffbd31cc4..c9dd32b46 100644 --- a/frontend/app/components/ui/SideMenuitem/SideMenuitem.js +++ b/frontend/app/components/ui/SideMenuitem/SideMenuitem.js @@ -7,13 +7,13 @@ function SideMenuitem({ iconBg = false, iconColor = "gray-dark", iconSize = 18, - className, + className = '', iconName = null, title, active = false, disabled = false, onClick, - deleteHandler, + deleteHandler = null, leading = null, ...props }) { diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 54fbe1972..232d4da4f 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -46,6 +46,11 @@ export interface IDashboardSotre { showAlertModal: boolean; + page: number + pageSize: number + dashboardsSearch: string + sort: any + selectWidgetsByCategory: (category: string) => void; toggleAllSelectedWidgets: (isSelected: boolean) => void; removeSelectedWidgetByCategory(category: string): void; @@ -115,6 +120,12 @@ export default class DashboardStore implements IDashboardSotre { sessionsLoading: boolean = false; showAlertModal: boolean = false; + // Pagination + page: number = 1 + pageSize: number = 15 + dashboardsSearch: string = '' + sort: any = {} + constructor() { makeAutoObservable(this); @@ -183,6 +194,7 @@ export default class DashboardStore implements IDashboardSotre { } updateKey(key: any, value: any) { + console.log(key, value) this[key] = value; } diff --git a/frontend/app/mstore/types/dashboard.ts b/frontend/app/mstore/types/dashboard.ts index 4c7ea801e..e172198ff 100644 --- a/frontend/app/mstore/types/dashboard.ts +++ b/frontend/app/mstore/types/dashboard.ts @@ -2,6 +2,7 @@ import { makeAutoObservable, observable, action, runInAction } from "mobx" import Widget, { IWidget } from "./widget" import { dashboardService } from "App/services" import { toast } from 'react-toastify'; +import { DateTime } from 'luxon'; export interface IDashboard { dashboardId: any @@ -14,6 +15,7 @@ export interface IDashboard { isPinned: boolean currentWidget: IWidget config: any + createdAt: Date update(data: any): void toJson(): any @@ -44,6 +46,7 @@ export default class Dashboard implements IDashboard { isPinned: boolean = false currentWidget: IWidget = new Widget() config: any = {} + createdAt: Date = new Date() constructor() { makeAutoObservable(this) @@ -63,8 +66,7 @@ export default class Dashboard implements IDashboard { dashboardId: this.dashboardId, name: this.name, isPublic: this.isPublic, - // widgets: this.widgets.map(w => w.toJson()) - // widgets: this.widgets + createdAt: this.createdAt, metrics: this.metrics, description: this.description, } @@ -77,7 +79,8 @@ export default class Dashboard implements IDashboard { this.description = json.description this.isPublic = json.isPublic this.isPinned = json.isPinned - this.widgets = json.widgets ? json.widgets.map(w => new Widget().fromJson(w)).sort((a, b) => a.position - b.position) : [] + this.createdAt = DateTime.fromMillis(new Date(json.createdAt).getTime()) + this.widgets = json.widgets ? json.widgets.map((w: Widget) => new Widget().fromJson(w)).sort((a: Widget, b: Widget) => a.position - b.position) : [] }) return this } diff --git a/frontend/app/utils.ts b/frontend/app/utils.ts index 142016d2b..d0bfb9b56 100644 --- a/frontend/app/utils.ts +++ b/frontend/app/utils.ts @@ -239,10 +239,10 @@ export const isGreaterOrEqualVersion = (version, compareTo) => { return major > majorC || (major === majorC && minor > minorC) || (major === majorC && minor === minorC && patch >= patchC); }; -export const sliceListPerPage = (list, page, perPage = 10) => { +export const sliceListPerPage = >(list: T, page: number, perPage = 10): T => { const start = page * perPage; const end = start + perPage; - return list.slice(start, end); + return list.slice(start, end) as T; }; export const positionOfTheNumber = (min, max, value, length) => { From 58a42c72d557a92fdf85fa7ced3358a0d5333b9c Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 10 Aug 2022 11:06:36 +0200 Subject: [PATCH 04/24] fix(ui): add typing to filter function --- .../components/DashboardList/DashboardList.tsx | 14 ++------------ .../components/MetricsList/MetricsList.tsx | 18 +++++++++--------- frontend/app/utils.ts | 15 ++++++++++++++- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 93649babf..5ce208da8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -2,21 +2,11 @@ import { observer } from 'mobx-react-lite'; import React from 'react'; import { NoContent, Pagination } from 'UI'; import { useStore } from 'App/mstore'; -import { getRE } from 'App/utils'; +import { filterList } from 'App/utils'; import { sliceListPerPage } from 'App/utils'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import DashboardListItem from './DashboardListItem'; -const filterList = >(list: T[], searchQuery: string): T[] => { - const filterRE = getRE(searchQuery, 'i'); - console.log(filterRE) - let _list = list.filter((w: T) => { - console.log(w.name, w.owner, w.description, filterRE.test(w.name)) - return filterRE.test(w.name) || filterRE.test(w.owner) || filterRE.test(w.description); - }); - return _list -} - function DashboardList() { const { dashboardStore } = useStore(); const [shownDashboards, setDashboards] = React.useState([]); @@ -24,7 +14,7 @@ function DashboardList() { const dashboardsSearch = dashboardStore.dashboardsSearch; React.useEffect(() => { - setDashboards(filterList(dashboards, dashboardsSearch)) + setDashboards(filterList(dashboards, dashboardsSearch, ['name', 'owner', 'description'])) }, [dashboardsSearch]) const list = dashboardsSearch !== '' ? shownDashboards : dashboards; diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 2b236564e..166be1b40 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -2,24 +2,24 @@ import { useObserver } from 'mobx-react-lite'; import React, { useEffect } from 'react'; import { NoContent, Pagination } from 'UI'; import { useStore } from 'App/mstore'; -import { getRE } from 'App/utils'; +import { getRE, filterList } from 'App/utils'; import MetricListItem from '../MetricListItem'; import { sliceListPerPage } from 'App/utils'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; +import { IWidget } from 'App/mstore/types/widget'; function MetricsList() { const { metricStore } = useStore(); const metrics = useObserver(() => metricStore.metrics); const metricsSearch = useObserver(() => metricStore.metricsSearch); - const filterList = >(list: T[]): T[] => { - const filterRE = getRE(metricsSearch, 'i'); - let _list = list.filter((w: T) => { - const dashbaordNames = w.dashboards.map((d: any) => d.name).join(' '); - return filterRE.test(w.name) || filterRE.test(w.metricType) || filterRE.test(w.owner) || filterRE.test(dashbaordNames); - }); - return _list + + const filterByDashboard = (item: IWidget, searchRE: RegExp) => { + const dashboardsStr = item.dashboards.map((d: any) => d.name).join(' ') + return searchRE.test(dashboardsStr) } - const list = metricsSearch !== '' ? filterList(metrics) : metrics; + const list = metricsSearch !== '' + ? filterList(metrics, metricsSearch, ['name', 'metricType', 'owner'], filterByDashboard) + : metrics; const lenth = list.length; useEffect(() => { diff --git a/frontend/app/utils.ts b/frontend/app/utils.ts index d0bfb9b56..7694f245a 100644 --- a/frontend/app/utils.ts +++ b/frontend/app/utils.ts @@ -53,7 +53,7 @@ export const cutURL = (url, prefix = '.../') => `${prefix + url.split('/').slice export const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -export function getRE(string, options) { +export function getRE(string: string, options: string) { let re; try { re = new RegExp(string, options); @@ -63,6 +63,19 @@ export function getRE(string, options) { return re; } +export const filterList = >( + list: T[], + searchQuery: string, + testKeys: string[], + searchCb?: (listItem: T, query: string | RegExp +) => boolean): T[] => { + const filterRE = getRE(searchQuery, 'i'); + let _list = list.filter((listItem: T) => { + return testKeys.some((key) => filterRE.test(listItem[key]) || searchCb?.(listItem, filterRE)); + }); + return _list + } + export const getStateColor = (state) => { switch (state) { case 'passed': From 7806c158068a8a5dde47d67341cfe9b81c98a947 Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 10 Aug 2022 15:39:03 +0200 Subject: [PATCH 05/24] fix(ui): add new metric selection modals, fix dashboard view --- .../app/components/Dashboard/NewDashboard.tsx | 20 +- .../DashboardList/DashboardsView.tsx | 23 +- .../DashboardMetricSelection.tsx | 11 +- .../DashboardModal/DashboardModal.tsx | 9 +- .../DashboardRouter/DashboardRouter.tsx | 12 +- .../DashboardView/DashboardView.tsx | 228 ++++++++---------- .../DashboardWidgetGrid/AddMetric.tsx | 98 ++++++++ .../AddMetricContainer.tsx | 83 +++++++ .../AddPredefinedMetric.tsx | 152 ++++++++++++ .../DashboardWidgetGrid.tsx | 11 +- .../components/MetricsView/MetricsView.tsx | 3 - .../app/components/Header/SiteDropdown.js | 3 +- frontend/app/components/ui/Button/Button.tsx | 1 + frontend/app/mstore/dashboardStore.ts | 15 +- 14 files changed, 503 insertions(+), 166 deletions(-) create mode 100644 frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx diff --git a/frontend/app/components/Dashboard/NewDashboard.tsx b/frontend/app/components/Dashboard/NewDashboard.tsx index 89af30897..af0e1ed88 100644 --- a/frontend/app/components/Dashboard/NewDashboard.tsx +++ b/frontend/app/components/Dashboard/NewDashboard.tsx @@ -9,12 +9,20 @@ import cn from 'classnames'; import { withSiteId } from 'App/routes'; import withPermissions from 'HOCs/withPermissions' -function NewDashboard(props: RouteComponentProps<{}>) { - const { history, match: { params: { siteId, dashboardId, metricId } } } = props; +interface RouterProps { + siteId: string; + dashboardId: string; + metricId: string; +} + +function NewDashboard(props: RouteComponentProps) { + const { history, match: { params: { siteId, dashboardId } } } = props; const { dashboardStore } = useStore(); const loading = useObserver(() => dashboardStore.isLoading); const isMetricDetails = history.location.pathname.includes('/metrics/') || history.location.pathname.includes('/metric/'); + const isDashboardDetails = history.location.pathname.includes('/dashboard/') + const shouldHideMenu = isMetricDetails || isDashboardDetails; useEffect(() => { dashboardStore.fetchList().then((resp) => { if (parseInt(dashboardId) > 0) { @@ -33,16 +41,16 @@ function NewDashboard(props: RouteComponentProps<{}>) { return useObserver(() => (
-
+
- +
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx index 5ebe9e150..2564cea2b 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -1,17 +1,32 @@ import React from 'react'; -import { Button, PageTitle, Icon, Link } from 'UI'; +import { Button, PageTitle, Icon } from 'UI'; import withPageTitle from 'HOCs/withPageTitle'; +import { useStore } from 'App/mstore'; +import { withSiteId } from 'App/routes'; + import DashboardList from './DashboardList'; import DashboardSearch from './DashboardSearch'; - -function DashboardsView() { + +function DashboardsView({ history, siteId }: { history: any, siteId: string }) { + const { dashboardStore } = useStore(); + + const onAddDashboardClick = () => { + dashboardStore.initDashboard(); + dashboardStore + .save(dashboardStore.dashboardInstance) + .then(async (syncedDashboard) => { + dashboardStore.selectDashboardById(syncedDashboard.dashboardId); + history.push(withSiteId(`/dashboard/${syncedDashboard.dashboardId}`, siteId)) + }) + } + return (
- +
diff --git a/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx b/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx index d612efe0b..cca7c51c1 100644 --- a/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx +++ b/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx @@ -6,9 +6,16 @@ import cn from 'classnames'; import { useStore } from 'App/mstore'; import { Loader } from 'UI'; -function WidgetCategoryItem({ category, isSelected, onClick, selectedWidgetIds }) { +interface IWiProps { + category: Record + onClick: (category: Record) => void + isSelected: boolean + selectedWidgetIds: string[] +} + +export function WidgetCategoryItem({ category, isSelected, onClick, selectedWidgetIds }: IWiProps) { const selectedCategoryWidgetsCount = useObserver(() => { - return category.widgets.filter(widget => selectedWidgetIds.includes(widget.metricId)).length; + return category.widgets.filter((widget: any) => selectedWidgetIds.includes(widget.metricId)).length; }); return (
void; } -function DashboardModal(props) { +function DashboardModal(props: Props) { const { history, siteId, dashboardId } = props; const { dashboardStore } = useStore(); const selectedWidgetsCount = useObserver(() => dashboardStore.selectedWidgets.length); const { hideModal } = useModal(); - const loadingTemplates = useObserver(() => dashboardStore.loadingTemplates); const dashboard = useObserver(() => dashboardStore.dashboardInstance); const loading = useObserver(() => dashboardStore.isSaving); diff --git a/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx b/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx index a7e71ffbd..f18415f27 100644 --- a/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx +++ b/frontend/app/components/Dashboard/components/DashboardRouter/DashboardRouter.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Switch, Route } from 'react-router'; -import { withRouter } from 'react-router-dom'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; import { metrics, @@ -18,18 +18,18 @@ import WidgetView from '../WidgetView'; import WidgetSubDetailsView from '../WidgetSubDetailsView'; import DashboardsView from '../DashboardList'; -function DashboardViewSelected({ siteId, dashboardId }) { +function DashboardViewSelected({ siteId, dashboardId }: { siteId: string, dashboardId: string }) { return ( ) } -interface Props { - history: any +interface Props extends RouteComponentProps { match: any } function DashboardRouter(props: Props) { - const { match: { params: { siteId, dashboardId, metricId } } } = props; + const { match: { params: { siteId, dashboardId } }, history } = props; + return (
@@ -46,7 +46,7 @@ function DashboardRouter(props: Props) { - + diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index e3aa0c2f2..b81cef7b9 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from "react"; import { observer } from "mobx-react-lite"; import { useStore } from "App/mstore"; -import { Button, PageTitle, Loader, NoContent } from "UI"; +import { Button, PageTitle, Loader } from "UI"; import { withSiteId } from "App/routes"; import withModal from "App/components/Modal/withModal"; import DashboardWidgetGrid from "../DashboardWidgetGrid"; @@ -15,8 +15,6 @@ import withPageTitle from "HOCs/withPageTitle"; import withReport from "App/components/hocs/withReport"; import DashboardOptions from "../DashboardOptions"; import SelectDateRange from "Shared/SelectDateRange"; -// @ts-ignore -import DashboardIcon from "../../../../svg/dashboard-icn.svg"; import { Tooltip } from "react-tippy"; import Breadcrumb from 'Shared/Breadcrumb'; @@ -31,23 +29,18 @@ type Props = IProps & RouteComponentProps; function DashboardView(props: Props) { const { siteId, dashboardId } = props; const { dashboardStore } = useStore(); + const { showModal } = useModal(); + const [focusTitle, setFocusedInput] = React.useState(true); const [showEditModal, setShowEditModal] = React.useState(false); - const { showModal } = useModal(); const showAlertModal = dashboardStore.showAlertModal; const loading = dashboardStore.fetchingDashboard; - const dashboards = dashboardStore.dashboards; const dashboard: any = dashboardStore.selectedDashboard; const period = dashboardStore.period; const queryParams = new URLSearchParams(props.location.search); - useEffect(() => { - if (!dashboard || !dashboard.dashboardId) return; - dashboardStore.fetch(dashboard.dashboardId); - }, [dashboard]); - const trimQuery = () => { if (!queryParams.has("modal")) return; queryParams.delete("modal"); @@ -60,21 +53,24 @@ function DashboardView(props: Props) { }; useEffect(() => { - if (!dashboardId || (!dashboard && dashboardStore.dashboards.length > 0)) dashboardStore.selectDefaultDashboard(); - if (queryParams.has("modal")) { onAddWidgets(); trimQuery(); } }, []); - useEffect(() => { - dashboardStore.selectDefaultDashboard(); - }, [siteId]) useEffect(() => { - dashboardStore.selectDashboardById(dashboardId); + const isExists = dashboardStore.getDashboardById(dashboardId); + if (!isExists) { + props.history.push(withSiteId(`/dashboard`, siteId)) + } }, [dashboardId]) + useEffect(() => { + if (!dashboard || !dashboard.dashboardId) return; + dashboardStore.fetch(dashboard.dashboardId); + }, [dashboard]); + const onAddWidgets = () => { dashboardStore.initDashboard(dashboard); showModal( @@ -87,11 +83,6 @@ function DashboardView(props: Props) { ); }; - const onAddDashboardClick = () => { - dashboardStore.initDashboard(); - showModal(, { right: true }) - } - const onEdit = (isTitle: boolean) => { dashboardStore.initDashboard(dashboard); setFocusedInput(isTitle); @@ -107,131 +98,104 @@ function DashboardView(props: Props) { }) ) { dashboardStore.deleteDashboard(dashboard).then(() => { - dashboardStore.selectDefaultDashboard().then( - ({ dashboardId }) => { - props.history.push( - withSiteId(`/dashboard/${dashboardId}`, siteId) - ); - }, - () => { - props.history.push(withSiteId("/dashboard", siteId)); - } - ); + props.history.push(withSiteId(`/dashboard`, siteId)); }); } }; + if (!dashboard) return null; + return ( - - + setShowEditModal(false)} + focusTitle={focusTitle} + /> + +
+
+ + {dashboard?.name} + + } + onDoubleClick={() => onEdit(true)} + className="mr-3 select-none hover:border-dotted hover:border-b border-gray-medium cursor-pointer" + actionButton={ + + } /> - - Gather and analyze
important metrics in one - place. -
- } - size="small" - > -
- setShowEditModal(false)} - focusTitle={focusTitle} - /> - -
-
- - {dashboard?.name} - - } - onDoubleClick={() => onEdit(true)} - className="mr-3 select-none hover:border-dotted hover:border-b border-gray-medium cursor-pointer" - actionButton={ - +
+
+ + dashboardStore.setPeriod(period) } + right={true} />
-
-
- - dashboardStore.setPeriod(period) - } - right={true} - /> -
-
-
- -
+
+
+
-
-

- {dashboard?.description} -

-
- - - dashboardStore.updateKey("showAlertModal", false) - } - />
- +
+

onEdit(false)} + > + {dashboard?.description || "Describe the purpose of this dashboard"} +

+
+ + + dashboardStore.updateKey("showAlertModal", false) + } + /> +
); } diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx new file mode 100644 index 000000000..ccdc033fe --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { observer } from 'mobx-react-lite'; +import { Button } from 'UI'; +import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper'; +import { useStore } from 'App/mstore'; +import { useModal } from 'App/components/Modal'; +import { dashboardMetricCreate, withSiteId } from 'App/routes'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; + +interface IProps extends RouteComponentProps { + metrics: any[]; + siteId: string; + title: string; + description: string; +} + +function AddMetric({ metrics, history, siteId, title, description }: IProps) { + const { dashboardStore } = useStore(); + const { hideModal } = useModal(); + + const dashboard = dashboardStore.selectedDashboard; + const selectedWidgetIds = dashboardStore.selectedWidgets.map((widget: any) => widget.metricId); + const queryParams = new URLSearchParams(location.search); + + const onSave = () => { + if (selectedWidgetIds.length === 0) return; + dashboardStore + .save(dashboard) + .then(async (syncedDashboard) => { + if (dashboard.exists()) { + await dashboardStore.fetch(dashboard.dashboardId); + } + dashboardStore.selectDashboardById(syncedDashboard.dashboardId); + }) + .then(hideModal); + }; + + const onCreateNew = () => { + const path = withSiteId(dashboardMetricCreate(dashboard.dashboardId), siteId); + if (!queryParams.has('modal')) history.push('?modal=addMetric'); + history.push(path); + hideModal(); + }; + + return ( +
+
+
+
+

{title}

+
{description}
+
+ {title.includes('Custom') ? ( +
+ + + Create new + +
+ ) : ( +
+ Don’t find the one you need? + + + Create custom metric + +
+ )} +
+ +
+ {metrics.map((metric: any) => ( + dashboardStore.toggleWidgetSelection(metric)} + /> + ))} +
+ +
+
+ {'Selected '} + {selectedWidgetIds.length} + {' out of '} + {metrics.length} +
+ +
+
+
+ ); +} + +export default withRouter(observer(AddMetric)); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx new file mode 100644 index 000000000..c796ecc5f --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import { observer } from 'mobx-react-lite'; +import { Icon } from 'UI'; +import { useModal } from 'App/components/Modal'; +import { useStore } from 'App/mstore'; +import AddMetric from './AddMetric'; +import AddPredefinedMetric from './AddPredefinedMetric'; + +interface AddMetricButtonProps { + iconName: string; + title: string; + description: string; + onClick: () => void; +} + +function AddMetricButton({ iconName, title, description, onClick }: AddMetricButtonProps) { + return ( +
+
+ +
+
{title}
+
{description}
+
+ ); +} + +function AddMetricContainer({ siteId }: any) { + const { showModal } = useModal(); + const [categories, setCategories] = React.useState[]>([]); + const { dashboardStore } = useStore(); + + React.useEffect(() => { + dashboardStore?.fetchTemplates(true).then((cats) => setCategories(cats)); + }, []); + + const onAddCustomMetrics = () => { + dashboardStore.initDashboard(dashboardStore.selectedDashboard); + showModal( + category.name === 'custom')?.widgets} + />, + { right: true } + ); + }; + + const onAddPredefinedMetrics = () => { + dashboardStore.initDashboard(dashboardStore.selectedDashboard); + showModal( + category.name !== 'custom')} + />, + { right: true } + ); + }; + return ( +
+ + +
+ ); +} + +export default observer(AddMetricContainer); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx new file mode 100644 index 000000000..13cd1047b --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx @@ -0,0 +1,152 @@ +import React from 'react'; +import { observer } from 'mobx-react-lite'; +import { Button } from 'UI'; +import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper'; +import { useStore } from 'App/mstore'; +import { useModal } from 'App/components/Modal'; +import { dashboardMetricCreate, withSiteId } from 'App/routes'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { WidgetCategoryItem } from 'App/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection'; + +interface IProps extends RouteComponentProps { + categories: Record[]; + siteId: string; + title: string; + description: string; +} + +function AddPredefinedMetric({ categories, history, siteId, title, description }: IProps) { + const { dashboardStore } = useStore(); + const { hideModal } = useModal(); + const [allCheck, setAllCheck] = React.useState(false); + const [activeCategory, setActiveCategory] = React.useState>(); + + const scrollContainer = React.useRef(null); + + const dashboard = dashboardStore.selectedDashboard; + const selectedWidgetIds = dashboardStore.selectedWidgets.map((widget: any) => widget.metricId); + const queryParams = new URLSearchParams(location.search); + const totalMetricCount = categories.reduce((acc, category) => acc + category.widgets.length, 0); + + React.useEffect(() => { + dashboardStore?.fetchTemplates(true).then((categories) => { + const defaultCategory = categories.filter((category: any) => category.name !== 'custom')[0]; + setActiveCategory(defaultCategory); + }); + }, []); + + React.useEffect(() => { + if (scrollContainer.current) { + scrollContainer.current.scrollTop = 0; + } + }, [activeCategory, scrollContainer.current]); + + const handleWidgetCategoryClick = (category: any) => { + setActiveCategory(category); + setAllCheck(false); + }; + + const onSave = () => { + if (selectedWidgetIds.length === 0) return; + dashboardStore + .save(dashboard) + .then(async (syncedDashboard) => { + if (dashboard.exists()) { + await dashboardStore.fetch(dashboard.dashboardId); + } + dashboardStore.selectDashboardById(syncedDashboard.dashboardId); + }) + .then(hideModal); + }; + + const onCreateNew = () => { + const path = withSiteId(dashboardMetricCreate(dashboard.dashboardId), siteId); + if (!queryParams.has('modal')) history.push('?modal=addMetric'); + history.push(path); + hideModal(); + }; + + const toggleAllMetrics = ({ target: { checked } }: any) => { + setAllCheck(checked); + if (checked) { + dashboardStore.selectWidgetsByCategory(activeCategory.name); + } else { + dashboardStore.removeSelectedWidgetByCategory(activeCategory); + } + }; + + return ( +
+
+
+
+

{title}

+
{description}
+
+ {title.includes('Custom') ? ( +
+ + + Create new + +
+ ) : ( +
+ Don’t find the one you need? + + + Create custom metric + +
+ )} +
+ +
+
+
+ {activeCategory && + categories.map((category) => ( + + ))} +
+
+ +
+ {activeCategory && + activeCategory.widgets.map((metric: any) => ( + dashboardStore.toggleWidgetSelection(metric)} + /> + ))} +
+
+ +
+
+ {'Selected '} + {selectedWidgetIds.length} + {' out of '} + {totalMetricCount} +
+ +
+
+
+ ); +} + +export default withRouter(observer(AddPredefinedMetric)); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index 442ee46e6..7750c8241 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { useStore } from 'App/mstore'; import WidgetWrapper from '../WidgetWrapper'; -import { NoContent, Button, Loader } from 'UI'; +import { NoContent, Loader } from 'UI'; import { useObserver } from 'mobx-react-lite'; +import AddMetricContainer from './AddMetricContainer' interface Props { siteId: string, @@ -18,16 +19,14 @@ function DashboardWidgetGrid(props: Props) { const list: any = useObserver(() => dashboard?.widgets); return useObserver(() => ( + // @ts-ignore -

Metrics helps you visualize trends from sessions captured by OpenReplay

- -
+ } >
diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index 216d1369b..288b9e1f0 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -10,9 +10,7 @@ interface Props{ siteId: number; } function MetricsView(props: Props) { - const { siteId } = props; const { metricStore } = useStore(); - const metricsCount = useObserver(() => metricStore.metrics.length); React.useEffect(() => { metricStore.fetchList(); @@ -22,7 +20,6 @@ function MetricsView(props: Props) {
- {metricsCount}
diff --git a/frontend/app/components/Header/SiteDropdown.js b/frontend/app/components/Header/SiteDropdown.js index 87fe2a0c2..7f89eee82 100644 --- a/frontend/app/components/Header/SiteDropdown.js +++ b/frontend/app/components/Header/SiteDropdown.js @@ -54,7 +54,8 @@ export default class SiteDropdown extends React.PureComponent { this.props.clearSearchLive(); mstore.initClient(); - }; + mstore.dashboardStore.selectDefaultDashboard(); + } render() { const { diff --git a/frontend/app/components/ui/Button/Button.tsx b/frontend/app/components/ui/Button/Button.tsx index d3e3acd15..eb9396682 100644 --- a/frontend/app/components/ui/Button/Button.tsx +++ b/frontend/app/components/ui/Button/Button.tsx @@ -8,6 +8,7 @@ interface Props { onClick?: () => void; disabled?: boolean; type?: 'button' | 'submit' | 'reset'; + variant?: 'default' | 'primary' | 'text' | 'text-primary' | 'text-red' | 'outline' loading?: boolean; icon?: string; rounded?: boolean; diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 232d4da4f..8abef7ea8 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -53,7 +53,7 @@ export interface IDashboardSotre { selectWidgetsByCategory: (category: string) => void; toggleAllSelectedWidgets: (isSelected: boolean) => void; - removeSelectedWidgetByCategory(category: string): void; + removeSelectedWidgetByCategory(category: Record): void; toggleWidgetSelection(widget: IWidget): void; initDashboard(dashboard?: IDashboard): void; @@ -72,6 +72,7 @@ export interface IDashboardSotre { getDashboardCount(): void; updateDashboard(dashboard: IDashboard): void; selectDashboardById(dashboardId: string): void; + getDashboardById(dashboardId: string): boolean; setSiteId(siteId: any): void; selectDefaultDashboard(): Promise; @@ -372,6 +373,18 @@ export default class DashboardStore implements IDashboardSotre { new Dashboard(); }; + getDashboardById = (dashboardId: string) => { + const dashboard = this.dashboards.find((d) => d.dashboardId == dashboardId) + + if (dashboard) { + this.selectedDashboard = dashboard + return true; + } else { + this.selectedDashboard = null + return false; + } + } + setSiteId = (siteId: any) => { this.siteId = siteId; }; From a9819589403a3a1114167f594a096a1d8fa6a918 Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 10 Aug 2022 16:48:59 +0200 Subject: [PATCH 06/24] fix(ui): minor style fixes --- frontend/app/components/Dashboard/NewDashboard.tsx | 7 ------- .../Dashboard/components/DashboardList/DashboardList.tsx | 2 +- .../components/DashboardList/DashboardListItem.tsx | 2 +- .../Dashboard/components/DashboardList/DashboardsView.tsx | 4 ++-- .../Dashboard/components/MetricListItem/MetricListItem.tsx | 6 +----- .../Dashboard/components/MetricsList/MetricsList.tsx | 2 +- .../Dashboard/components/MetricsView/MetricsView.tsx | 4 ++-- 7 files changed, 8 insertions(+), 19 deletions(-) diff --git a/frontend/app/components/Dashboard/NewDashboard.tsx b/frontend/app/components/Dashboard/NewDashboard.tsx index af0e1ed88..2f9496591 100644 --- a/frontend/app/components/Dashboard/NewDashboard.tsx +++ b/frontend/app/components/Dashboard/NewDashboard.tsx @@ -29,13 +29,6 @@ function NewDashboard(props: RouteComponentProps) { dashboardStore.selectDashboardById(dashboardId); } }); - if (!dashboardId && location.pathname.includes('dashboard')) { - dashboardStore.selectDefaultDashboard().then(({ dashboardId }) => { - props.history.push(withSiteId(`/dashboard/${dashboardId}`, siteId)); - }, () => { - props.history.push(withSiteId('/dashboard', siteId)); - }) - } }, [siteId]); return useObserver(() => ( diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 5ce208da8..466103dc8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -31,7 +31,7 @@ function DashboardList() { } >
-
+
Title
Visibility
Created
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx index 8a40c2139..5e82ac2b6 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx @@ -23,7 +23,7 @@ function DashboardListItem(props: Props) { }; return ( <> -
+
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx index 2564cea2b..10bbfc50d 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -22,7 +22,7 @@ function DashboardsView({ history, siteId }: { history: any, siteId: string }) { return (
-
+
@@ -31,7 +31,7 @@ function DashboardsView({ history, siteId }: { history: any, siteId: string }) {
-
+
A dashboard is a custom visualization using your OpenReplay data.
diff --git a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx index 38af42702..52747a86c 100644 --- a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx +++ b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx @@ -63,19 +63,15 @@ function MetricListItem(props: Props) { return ( -
+
- {/*
- -
*/} {metric.name}
- {/*
*/}
{metric.owner}
diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 166be1b40..8c453688e 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -37,7 +37,7 @@ function MetricsList() { } >
-
+
Title
Owner
Visibility
diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index 288b9e1f0..abdf2e5e2 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -17,7 +17,7 @@ function MetricsView(props: Props) { }, []); return useObserver(() => (
-
+
@@ -26,7 +26,7 @@ function MetricsView(props: Props) {
-
+
Create custom Metrics to capture key interactions and track KPIs.
From a70058cf5d8f2ecb2c29afa6dd7598d8dd1be98d Mon Sep 17 00:00:00 2001 From: sylenien Date: Wed, 10 Aug 2022 17:59:54 +0200 Subject: [PATCH 07/24] fix(ui): fix crashes --- .../components/DashboardList/DashboardListItem.tsx | 2 +- .../Dashboard/components/DashboardWidgetGrid/AddMetric.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx index 5e82ac2b6..1fffe9f30 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx @@ -51,5 +51,5 @@ function DashboardListItem(props: Props) { ); } - +// @ts-ignore export default connect(state => ({ siteId: state.getIn([ 'site', 'siteId' ]) }))(withRouter(DashboardListItem)) diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx index ccdc033fe..af46de0c2 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx @@ -67,7 +67,7 @@ function AddMetric({ metrics, history, siteId, title, description }: IProps) {
- {metrics.map((metric: any) => ( + {metrics ? metrics.map((metric: any) => ( dashboardStore.toggleWidgetSelection(metric)} /> - ))} + )) : ( +
No custom metrics created.
+ )}
From 73c45dae3e1e3dc0546f2553636bfd0a929027bd Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 11 Aug 2022 13:50:07 +0200 Subject: [PATCH 08/24] fix(player): add border to dashboards, fix font size and tooltip --- .../DashboardList/DashboardsView.tsx | 8 +++--- .../MetricListItem/MetricListItem.tsx | 27 +++++++------------ .../components/MetricsView/MetricsView.tsx | 8 +++--- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx index 10bbfc50d..75b4aaf4e 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -21,18 +21,18 @@ function DashboardsView({ history, siteId }: { history: any, siteId: string }) { } return ( -
+
-
+
-
- +
+ A dashboard is a custom visualization using your OpenReplay data.
diff --git a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx index 52747a86c..18f580851 100644 --- a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx +++ b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { Icon, NoContent, Label, Link, Pagination, Popup } from 'UI'; -import { checkForRecent, formatDateTimeDefault, convertTimestampToUtcTimestamp } from 'App/date'; -import { getIcon } from 'react-toastify/dist/components'; +import { Icon, Link, Popup } from 'UI'; +import { checkForRecent } from 'App/date'; +import { Tooltip } from 'react-tippy' interface Props { metric: any; @@ -25,19 +25,6 @@ function DashboardLink({ dashboards}: any) { } function MetricTypeIcon({ type }: any) { - const PopupWrapper = (props: any) => { - return ( - {type}
} - position="top center" - on="hover" - hideOnScroll={true} - > - {props.children} - - ); - } - const getIcon = () => { switch (type) { case 'funnel': @@ -50,11 +37,15 @@ function MetricTypeIcon({ type }: any) { } return ( - + {type}
} + position="top" + arrow + >
- + ) } diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index abdf2e5e2..afe0dd337 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -16,18 +16,18 @@ function MetricsView(props: Props) { metricStore.fetchList(); }, []); return useObserver(() => ( -
+
-
+
-
- +
+ Create custom Metrics to capture key interactions and track KPIs.
From 3f14d4b766b363969a1cf35d4e16936722fff061 Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 11 Aug 2022 15:58:23 +0200 Subject: [PATCH 09/24] fix(player): change card colors and borders, fix icons --- .../DashboardView/DashboardView.tsx | 135 +++++++----------- .../AddMetricContainer.tsx | 35 +++-- .../DashboardWidgetGrid.tsx | 5 +- .../components/WidgetName/WidgetName.tsx | 7 +- frontend/app/components/ui/SVG.tsx | 2 + frontend/app/mstore/types/dashboard.ts | 2 +- frontend/app/mstore/types/widget.ts | 2 +- frontend/app/svg/icons/bar-pencil.svg | 16 +++ frontend/app/svg/icons/grid-check.svg | 3 + frontend/app/theme/colors.js | 13 ++ 10 files changed, 121 insertions(+), 99 deletions(-) create mode 100644 frontend/app/svg/icons/bar-pencil.svg create mode 100644 frontend/app/svg/icons/grid-check.svg diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index b81cef7b9..e75fe6823 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -1,21 +1,21 @@ -import React, { useEffect } from "react"; -import { observer } from "mobx-react-lite"; -import { useStore } from "App/mstore"; -import { Button, PageTitle, Loader } from "UI"; -import { withSiteId } from "App/routes"; -import withModal from "App/components/Modal/withModal"; -import DashboardWidgetGrid from "../DashboardWidgetGrid"; -import { confirm } from "UI"; -import { withRouter, RouteComponentProps } from "react-router-dom"; -import { useModal } from "App/components/Modal"; -import DashboardModal from "../DashboardModal"; -import DashboardEditModal from "../DashboardEditModal"; -import AlertFormModal from "App/components/Alerts/AlertFormModal"; -import withPageTitle from "HOCs/withPageTitle"; -import withReport from "App/components/hocs/withReport"; -import DashboardOptions from "../DashboardOptions"; -import SelectDateRange from "Shared/SelectDateRange"; -import { Tooltip } from "react-tippy"; +import React, { useEffect } from 'react'; +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; +import { Button, PageTitle, Loader } from 'UI'; +import { withSiteId } from 'App/routes'; +import withModal from 'App/components/Modal/withModal'; +import DashboardWidgetGrid from '../DashboardWidgetGrid'; +import { confirm } from 'UI'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { useModal } from 'App/components/Modal'; +import DashboardModal from '../DashboardModal'; +import DashboardEditModal from '../DashboardEditModal'; +import AlertFormModal from 'App/components/Alerts/AlertFormModal'; +import withPageTitle from 'HOCs/withPageTitle'; +import withReport from 'App/components/hocs/withReport'; +import DashboardOptions from '../DashboardOptions'; +import SelectDateRange from 'Shared/SelectDateRange'; +import { Tooltip } from 'react-tippy'; import Breadcrumb from 'Shared/Breadcrumb'; interface IProps { @@ -42,18 +42,18 @@ function DashboardView(props: Props) { const queryParams = new URLSearchParams(props.location.search); const trimQuery = () => { - if (!queryParams.has("modal")) return; - queryParams.delete("modal"); + if (!queryParams.has('modal')) return; + queryParams.delete('modal'); props.history.replace({ search: queryParams.toString(), }); }; const pushQuery = () => { - if (!queryParams.has("modal")) props.history.push("?modal=addMetric"); + if (!queryParams.has('modal')) props.history.push('?modal=addMetric'); }; useEffect(() => { - if (queryParams.has("modal")) { + if (queryParams.has('modal')) { onAddWidgets(); trimQuery(); } @@ -62,9 +62,9 @@ function DashboardView(props: Props) { useEffect(() => { const isExists = dashboardStore.getDashboardById(dashboardId); if (!isExists) { - props.history.push(withSiteId(`/dashboard`, siteId)) + props.history.push(withSiteId(`/dashboard`, siteId)); } - }, [dashboardId]) + }, [dashboardId]); useEffect(() => { if (!dashboard || !dashboard.dashboardId) return; @@ -73,14 +73,7 @@ function DashboardView(props: Props) { const onAddWidgets = () => { dashboardStore.initDashboard(dashboard); - showModal( - , - { right: true } - ); + showModal(, { right: true }); }; const onEdit = (isTitle: boolean) => { @@ -92,8 +85,8 @@ function DashboardView(props: Props) { const onDelete = async () => { if ( await confirm({ - header: "Confirm", - confirmButton: "Yes, delete", + header: 'Confirm', + confirmButton: 'Yes, delete', confirmation: `Are you sure you want to permanently delete this Dashboard?`, }) ) { @@ -107,60 +100,41 @@ function DashboardView(props: Props) { return ( -
- setShowEditModal(false)} - focusTitle={focusTitle} - /> +
+ setShowEditModal(false)} focusTitle={focusTitle} />
+ // @ts-ignore + {dashboard?.name} } onDoubleClick={() => onEdit(true)} - className="mr-3 select-none hover:border-dotted hover:border-b border-gray-medium cursor-pointer" + className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer" actionButton={ - } />
-
-
+
+
- dashboardStore.setPeriod(period) - } + onChange={(period: any) => dashboardStore.setPeriod(period)} right={true} />
@@ -176,30 +150,21 @@ function DashboardView(props: Props) {
-

onEdit(false)} - > - {dashboard?.description || "Describe the purpose of this dashboard"} -

+ {/* @ts-ignore */} + +

onEdit(false)} + > + {dashboard?.description || 'Describe the purpose of this dashboard'} +

+
- - - dashboardStore.updateKey("showAlertModal", false) - } - /> + + dashboardStore.updateKey('showAlertModal', false)} />
); } -export default withPageTitle("Dashboards - OpenReplay")( - withReport(withRouter(withModal(observer(DashboardView)))) -); +export default withPageTitle('Dashboards - OpenReplay')(withReport(withRouter(withModal(observer(DashboardView))))); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx index c796ecc5f..7cba9ac52 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx @@ -5,25 +5,41 @@ import { useModal } from 'App/components/Modal'; import { useStore } from 'App/mstore'; import AddMetric from './AddMetric'; import AddPredefinedMetric from './AddPredefinedMetric'; +import cn from 'classnames'; interface AddMetricButtonProps { iconName: string; title: string; description: string; + isPremade?: boolean; onClick: () => void; } -function AddMetricButton({ iconName, title, description, onClick }: AddMetricButtonProps) { +function AddMetricButton({ iconName, title, description, onClick, isPremade }: AddMetricButtonProps) { return (
-
- +
+
-
{title}
-
{description}
+
{title}
+
{description}
); } @@ -63,17 +79,18 @@ function AddMetricContainer({ siteId }: any) { ); }; return ( -
+
diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index 7750c8241..74c1d5c3d 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -24,9 +24,9 @@ function DashboardWidgetGrid(props: Props) { Build your dashboard} subtext={ - +
} >
@@ -41,6 +41,7 @@ function DashboardWidgetGrid(props: Props) { isWidget={true} /> ))} +
diff --git a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx index 67be4930d..d0d673df2 100644 --- a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx +++ b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx @@ -68,7 +68,12 @@ function WidgetName(props: Props) {
setEditing(true)} - className={cn("text-2xl h-8 flex items-center border-transparent", canEdit && 'cursor-pointer select-none hover:border-dotted hover:border-b border-gray-medium')} + className={ + cn( + "text-2xl h-8 flex items-center border-transparent", + canEdit && 'cursor-pointer select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium' + ) + } > { name }
diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index dd207816e..4a6582789 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -64,6 +64,7 @@ const SVG = (props: Props) => { case 'avatar/icn_wild_bore': return ; case 'ban': return ; case 'bar-chart-line': return ; + case 'bar-pencil': return ; case 'bell-plus': return ; case 'bell': return ; case 'binoculars': return ; @@ -221,6 +222,7 @@ const SVG = (props: Props) => { case 'github': return ; case 'graph-up-arrow': return ; case 'grid-3x3': return ; + case 'grid-check': return ; case 'grip-horizontal': return ; case 'hash': return ; case 'hdd-stack': return ; diff --git a/frontend/app/mstore/types/dashboard.ts b/frontend/app/mstore/types/dashboard.ts index e172198ff..5b8c40b17 100644 --- a/frontend/app/mstore/types/dashboard.ts +++ b/frontend/app/mstore/types/dashboard.ts @@ -37,7 +37,7 @@ export interface IDashboard { export default class Dashboard implements IDashboard { public static get ID_KEY():string { return "dashboardId" } dashboardId: any = undefined - name: string = "New Dashboard" + name: string = "Untitled Dashboard" description: string = "" isPublic: boolean = true widgets: IWidget[] = [] diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 10e1e68f4..3d824c68f 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -60,7 +60,7 @@ export default class Widget implements IWidget { public static get ID_KEY():string { return "metricId" } metricId: any = undefined widgetId: any = undefined - name: string = "New Metric" + name: string = "Untitled Metric" // metricType: string = "timeseries" metricType: string = "timeseries" metricOf: string = "sessionCount" diff --git a/frontend/app/svg/icons/bar-pencil.svg b/frontend/app/svg/icons/bar-pencil.svg new file mode 100644 index 000000000..1b9916e25 --- /dev/null +++ b/frontend/app/svg/icons/bar-pencil.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/grid-check.svg b/frontend/app/svg/icons/grid-check.svg new file mode 100644 index 000000000..3e899f840 --- /dev/null +++ b/frontend/app/svg/icons/grid-check.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app/theme/colors.js b/frontend/app/theme/colors.js index 51be4289d..297e044bd 100644 --- a/frontend/app/theme/colors.js +++ b/frontend/app/theme/colors.js @@ -43,5 +43,18 @@ module.exports = { 'gray-light-shade': '#EEEEEE', 'primary': '#3490dc', 'transparent': 'transparent', + }, + + // actual theme colors - use this for new components + figmaColors: { + 'accent-secondary': 'rgba(62, 170, 175, 1)', + 'main': 'rgba(57, 78, 255, 1)', + 'primary-outlined-hover-background': 'rgba(62, 170, 175, 0.08)', + 'primary-outlined-resting-border': 'rgba(62, 170, 175, 0.5)', + 'secondary-outlined-hover-background': 'rgba(63, 81, 181, 0.08)', + 'secondary-outlined-resting-border': 'rgba(63, 81, 181, 0.5)', + 'text-disabled': 'rgba(0,0,0, 0.38)', + 'text-primary': 'rgba(0,0,0, 0.87)', + 'outlined-border': 'rgba(0,0,0, 0.23)', } } From 3cbd5e1154767237b0722055893f03af6b924702 Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 11 Aug 2022 16:09:25 +0200 Subject: [PATCH 10/24] fix(player): fix shadow clipping --- .../components/DashboardWidgetGrid/AddMetricContainer.tsx | 2 +- .../components/DashboardWidgetGrid/AddPredefinedMetric.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx index 7cba9ac52..d3caf987a 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx @@ -79,7 +79,7 @@ function AddMetricContainer({ siteId }: any) { ); }; return ( -
+
{activeCategory && From c9338fd1160e7f134a834e86736600cf38bc70d2 Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 11 Aug 2022 16:40:40 +0200 Subject: [PATCH 11/24] fix(ui): fix grid rows height --- .../Dashboard/components/DashboardWidgetGrid/AddMetric.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx index af46de0c2..a07c57016 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx @@ -66,7 +66,7 @@ function AddMetric({ metrics, history, siteId, title, description }: IProps) { )}
-
+
{metrics ? metrics.map((metric: any) => ( Date: Thu, 11 Aug 2022 16:43:48 +0200 Subject: [PATCH 12/24] fix(ui): fix predef modal height --- .../components/DashboardWidgetGrid/AddPredefinedMetric.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx index 0e4b726d2..5be789a2d 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx @@ -99,7 +99,7 @@ function AddPredefinedMetric({ categories, history, siteId, title, description } )}
-
+
{activeCategory && From 901539f27d413af3e5df01ccf3b74248d2afe054 Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 11 Aug 2022 17:50:10 +0200 Subject: [PATCH 13/24] fix(ui): fix colors for metric picker --- .../DashboardList/DashboardList.tsx | 2 +- .../DashboardList/DashboardListItem.tsx | 28 ++++++-------- .../DashboardView/DashboardView.module.css | 5 +++ .../DashboardView/DashboardView.tsx | 23 ++++++++++-- .../DashboardWidgetGrid/AddMetric.tsx | 19 +++------- .../AddMetricContainer.tsx | 37 ++++++++++++------- .../AddPredefinedMetric.tsx | 23 ++++-------- .../OutsideClickDetectingDiv.js | 8 ++-- frontend/app/styles/general.css | 5 ++- 9 files changed, 80 insertions(+), 70 deletions(-) create mode 100644 frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 466103dc8..4aa5a43e5 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -31,7 +31,7 @@ function DashboardList() { } >
-
+
Title
Visibility
Created
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx index 1fffe9f30..057b22d9a 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { Icon } from 'UI'; import { connect } from 'react-redux'; -import{ IDashboard } from "App/mstore/types/dashboard"; +import { IDashboard } from 'App/mstore/types/dashboard'; import { checkForRecent } from 'App/date'; import { withSiteId, dashboardSelected } from 'App/routes'; import { useStore } from 'App/mstore'; import { withRouter, RouteComponentProps } from 'react-router-dom'; interface Props extends RouteComponentProps { - dashboard: IDashboard; - siteId: string; + dashboard: IDashboard; + siteId: string; } function DashboardListItem(props: Props) { @@ -22,34 +22,28 @@ function DashboardListItem(props: Props) { history.push(path); }; return ( - <> +
-
+
-
- {dashboard.name} -
+
{dashboard.name}
{/*
*/}
- + {dashboard.isPublic ? 'Team' : 'Private'}
-
- {checkForRecent(dashboard.createdAt, 'LLL dd, yyyy, hh:mm a')} -
+
{checkForRecent(dashboard.createdAt, 'LLL dd, yyyy, hh:mm a')}
-
- {dashboard.description} -
- + {dashboard.description ?
{dashboard.description}
: null} +
); } // @ts-ignore -export default connect(state => ({ siteId: state.getIn([ 'site', 'siteId' ]) }))(withRouter(DashboardListItem)) +export default connect((state) => ({ siteId: state.getIn(['site', 'siteId']) }))(withRouter(DashboardListItem)); diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css new file mode 100644 index 000000000..42045607f --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css @@ -0,0 +1,5 @@ +.tooltipContainer { + & > tippy-popper > tippy-tooltip { + padding: 0!important; + } +} diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index e75fe6823..8c6d7f54b 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -17,6 +17,10 @@ import DashboardOptions from '../DashboardOptions'; import SelectDateRange from 'Shared/SelectDateRange'; import { Tooltip } from 'react-tippy'; import Breadcrumb from 'Shared/Breadcrumb'; +import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; +import AddMetricContainer from '../DashboardWidgetGrid/AddMetricContainer'; +// @ts-ignore +import stl from './DashboardView.module.css'; interface IProps { siteId: string; @@ -27,6 +31,7 @@ interface IProps { type Props = IProps & RouteComponentProps; function DashboardView(props: Props) { + const [isTooltipShown, setTooltip] = React.useState(false); const { siteId, dashboardId } = props; const { dashboardStore } = useStore(); const { showModal } = useModal(); @@ -123,9 +128,21 @@ function DashboardView(props: Props) { onDoubleClick={() => onEdit(true)} className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer" actionButton={ - + setTooltip(false)}> + {/* @ts-ignore */} +
} + > + + + } />
diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx index a07c57016..472d98d0f 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetric.tsx @@ -50,20 +50,11 @@ function AddMetric({ metrics, history, siteId, title, description }: IProps) {

{title}

{description}
- {title.includes('Custom') ? ( -
- - + Create new - -
- ) : ( -
- Don’t find the one you need? - - + Create custom metric - -
- )} + + +
diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx index d3caf987a..30f48f58e 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddMetricContainer.tsx @@ -12,39 +12,42 @@ interface AddMetricButtonProps { title: string; description: string; isPremade?: boolean; + isPopup?: boolean; onClick: () => void; } -function AddMetricButton({ iconName, title, description, onClick, isPremade }: AddMetricButtonProps) { +function AddMetricButton({ iconName, title, description, onClick, isPremade, isPopup }: AddMetricButtonProps) { return (
- + +
+
+
{title}
+
+ {description} +
-
{title}
-
{description}
); } -function AddMetricContainer({ siteId }: any) { +function AddMetricContainer({ siteId, isPopup }: any) { const { showModal } = useModal(); const [categories, setCategories] = React.useState[]>([]); const { dashboardStore } = useStore(); @@ -78,20 +81,26 @@ function AddMetricContainer({ siteId }: any) { { right: true } ); }; + + const classes = isPopup + ? 'bg-white border rounded p-4 grid grid-rows-2 gap-4' + : 'bg-white border border-dashed hover:!border-gray-medium rounded p-8 grid grid-cols-2 gap-8'; return ( -
+
); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx index 5be789a2d..c27646b2f 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/AddPredefinedMetric.tsx @@ -83,23 +83,16 @@ function AddPredefinedMetric({ categories, history, siteId, title, description }

{title}

{description}
- {title.includes('Custom') ? ( -
- - + Create new - -
- ) : ( -
- Don’t find the one you need? - - + Create custom metric - -
- )} + +
+ Don’t find the one you need? + +
-
+
{activeCategory && diff --git a/frontend/app/components/shared/OutsideClickDetectingDiv/OutsideClickDetectingDiv.js b/frontend/app/components/shared/OutsideClickDetectingDiv/OutsideClickDetectingDiv.js index 954566480..a6ec97c40 100644 --- a/frontend/app/components/shared/OutsideClickDetectingDiv/OutsideClickDetectingDiv.js +++ b/frontend/app/components/shared/OutsideClickDetectingDiv/OutsideClickDetectingDiv.js @@ -29,8 +29,7 @@ function handleClickOutside(e) { document.addEventListener('click', handleClickOutside); - -export default React.memo(function OutsideClickDetectingDiv({ onClickOutside, children, ...props}) { +function OutsideClickDetectingDiv({ onClickOutside, children, ...props}) { const ref = useRef(null); useLayoutEffect(() => { function handleClickOutside(event) { @@ -44,7 +43,6 @@ export default React.memo(function OutsideClickDetectingDiv({ onClickOutside, ch }, [ ref ]); return
{children}
; -}); - - +} +export default React.memo(OutsideClickDetectingDiv); diff --git a/frontend/app/styles/general.css b/frontend/app/styles/general.css index f0b80a54d..dd84006a2 100644 --- a/frontend/app/styles/general.css +++ b/frontend/app/styles/general.css @@ -278,6 +278,9 @@ p { .tippy-tooltip.openreplay-theme .tippy-backdrop { background-color: $tealx; } +.tippy-tooltip[data-theme~='nopadding'], .nopadding-theme { + padding: 0!important +} @media print { .no-print { @@ -302,4 +305,4 @@ p { .recharts-legend-item-text { white-space: nowrap !important; -} \ No newline at end of file +} From 3136ce5a2baefef07e70d24938bfd2b18f25ec26 Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 10:57:28 +0200 Subject: [PATCH 14/24] fix(ui): fix empty metric text, fix metric min height, fix rows etc --- .../BreakdownOfLoadedResources.js | 1 + .../Widgets/CallWithErrors/CallWithErrors.js | 1 + .../Widgets/CallsErrors4xx/CallsErrors4xx.js | 1 + .../Widgets/CallsErrors5xx/CallsErrors5xx.js | 1 + .../Dashboard/Widgets/CpuLoad/CpuLoad.js | 1 + .../Dashboard/Widgets/Crashes/Crashes.js | 1 + .../CustomMetricPieChart.tsx | 2 +- .../CustomMetricTable/CustomMetricTable.tsx | 4 ++-- .../CustomMetricWidget/CustomMetricWidget.tsx | 1 + .../Widgets/DomBuildingTime/DomBuildingTime.js | 2 ++ .../Widgets/ErrorsByOrigin/ErrorsByOrigin.js | 1 + .../Widgets/ErrorsByType/ErrorsByType.js | 1 + .../Widgets/ErrorsPerDomain/ErrorsPerDomain.js | 1 + .../components/Dashboard/Widgets/FPS/FPS.js | 1 + .../LastFrustrations/LastFrustrations.js | 1 + .../MemoryConsumption/MemoryConsumption.js | 1 + .../MostImpactfulErrors/MostImpactfulErrors.js | 1 + .../BreakdownOfLoadedResources.tsx | 3 ++- .../PredefinedWidgets/CPULoad/CPULoad.tsx | 3 ++- .../CallWithErrors/CallWithErrors.tsx | 1 + .../CallsErrors4xx/CallsErrors4xx.tsx | 3 ++- .../CallsErrors5xx/CallsErrors5xx.tsx | 3 ++- .../PredefinedWidgets/Crashes/Crashes.tsx | 3 ++- .../DomBuildingTime/DomBuildingTime.tsx | 3 ++- .../ErrorsByOrigin/ErrorsByOrigin.tsx | 3 ++- .../ErrorsByType/ErrorsByType.tsx | 3 ++- .../ErrorsPerDomain/ErrorsPerDomain.tsx | 3 ++- .../Widgets/PredefinedWidgets/FPS/FPS.tsx | 3 ++- .../MemoryConsumption/MemoryConsumption.tsx | 3 ++- .../ResourceLoadedVsResponseEnd.tsx | 1 + .../ResourceLoadedVsVisuallyComplete.tsx | 3 ++- .../ResourceLoadingTime.tsx | 3 ++- .../ResponseTime/ResponseTime.tsx | 3 ++- .../ResponseTimeDistribution.tsx | 3 ++- .../SessionsAffectedByJSErrors.tsx | 3 ++- .../SessionsImpactedBySlowRequests.tsx | 3 ++- .../SessionsPerBrowser/SessionsPerBrowser.tsx | 3 ++- .../SlowestDomains/SlowestDomains.tsx | 1 + .../SpeedIndexByLocation.tsx | 2 +- .../TimeToRender/TimeToRender.tsx | 3 ++- .../ResourceLoadedVsResponseEnd.js | 1 + .../ResourceLoadedVsVisuallyComplete.js | 1 + .../ResourceLoadingTime/ResourceLoadingTime.js | 2 ++ .../Widgets/ResponseTime/ResponseTime.js | 1 + .../ResponseTimeDistribution.js | 1 + .../SessionsAffectedByJSErrors.js | 1 + .../SessionsImpactedBySlowRequests.js | 1 + .../SessionsPerBrowser/SessionsPerBrowser.js | 3 ++- .../Widgets/SlowestDomains/SlowestDomains.js | 1 + .../Widgets/SlowestImages/SlowestImages.js | 1 + .../SlowestResources/SlowestResources.js | 1 + .../Widgets/TimeToRender/TimeToRender.js | 1 + .../Dashboard/Widgets/TopDomains/TopDomains.js | 1 + .../components/DashboardView/DashboardView.tsx | 18 ++++++++---------- .../DashboardWidgetGrid/AddMetric.tsx | 2 +- .../DashboardWidgetGrid/AddMetricContainer.tsx | 2 +- .../AddPredefinedMetric.tsx | 16 ++++++++-------- .../components/WidgetChart/WidgetChart.tsx | 2 +- .../app/components/Errors/Error/SideSection.js | 4 +--- .../Funnels/FunnelWidget/FunnelWidget.tsx | 2 +- .../components/Session/IOSPlayer/Crashes.js | 3 ++- .../app/components/Session/IOSPlayer/Logs.js | 3 ++- .../Session_/Exceptions/Exceptions.js | 3 ++- .../app/components/Session_/GraphQL/GraphQL.js | 1 + .../components/Session_/LongTasks/LongTasks.js | 1 + .../Session_/TimeTable/TimeTable.tsx | 2 +- frontend/app/dateRange.js | 2 +- frontend/app/types/app/period.js | 2 +- 68 files changed, 108 insertions(+), 55 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/BreakdownOfLoadedResources/BreakdownOfLoadedResources.js b/frontend/app/components/Dashboard/Widgets/BreakdownOfLoadedResources/BreakdownOfLoadedResources.js index 10ab766a7..99ffc931b 100644 --- a/frontend/app/components/Dashboard/Widgets/BreakdownOfLoadedResources/BreakdownOfLoadedResources.js +++ b/frontend/app/components/Dashboard/Widgets/BreakdownOfLoadedResources/BreakdownOfLoadedResources.js @@ -30,6 +30,7 @@ export default class BreakdownOfLoadedResources extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/CallWithErrors/CallWithErrors.js b/frontend/app/components/Dashboard/Widgets/CallWithErrors/CallWithErrors.js index 8bf8b90c2..4b3cadef6 100644 --- a/frontend/app/components/Dashboard/Widgets/CallWithErrors/CallWithErrors.js +++ b/frontend/app/components/Dashboard/Widgets/CallWithErrors/CallWithErrors.js @@ -64,6 +64,7 @@ export default class CallWithErrors extends React.PureComponent {
diff --git a/frontend/app/components/Dashboard/Widgets/CallsErrors5xx/CallsErrors5xx.js b/frontend/app/components/Dashboard/Widgets/CallsErrors5xx/CallsErrors5xx.js index a0e0d05a0..3c655da5f 100644 --- a/frontend/app/components/Dashboard/Widgets/CallsErrors5xx/CallsErrors5xx.js +++ b/frontend/app/components/Dashboard/Widgets/CallsErrors5xx/CallsErrors5xx.js @@ -37,6 +37,7 @@ export default class CallsErrors5xx extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/CpuLoad/CpuLoad.js b/frontend/app/components/Dashboard/Widgets/CpuLoad/CpuLoad.js index 0579480fb..ee448dac2 100644 --- a/frontend/app/components/Dashboard/Widgets/CpuLoad/CpuLoad.js +++ b/frontend/app/components/Dashboard/Widgets/CpuLoad/CpuLoad.js @@ -27,6 +27,7 @@ export default class CpuLoad extends React.PureComponent {
diff --git a/frontend/app/components/Dashboard/Widgets/Crashes/Crashes.js b/frontend/app/components/Dashboard/Widgets/Crashes/Crashes.js index 16f96a07c..576c9c13f 100644 --- a/frontend/app/components/Dashboard/Widgets/Crashes/Crashes.js +++ b/frontend/app/components/Dashboard/Widgets/Crashes/Crashes.js @@ -30,6 +30,7 @@ export default class Crashes extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx index 76b8697c1..0765d7940 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx @@ -34,7 +34,7 @@ function CustomMetricPieChart(props: Props) { } } return ( - + - +
+
diff --git a/frontend/app/components/Dashboard/Widgets/DomBuildingTime/DomBuildingTime.js b/frontend/app/components/Dashboard/Widgets/DomBuildingTime/DomBuildingTime.js index 27cc682ff..970bfdbad 100644 --- a/frontend/app/components/Dashboard/Widgets/DomBuildingTime/DomBuildingTime.js +++ b/frontend/app/components/Dashboard/Widgets/DomBuildingTime/DomBuildingTime.js @@ -44,6 +44,7 @@ export default class DomBuildingTime extends React.PureComponent { return ( @@ -60,6 +61,7 @@ export default class DomBuildingTime extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/ErrorsByOrigin/ErrorsByOrigin.js b/frontend/app/components/Dashboard/Widgets/ErrorsByOrigin/ErrorsByOrigin.js index 399908f74..d77bac5f4 100644 --- a/frontend/app/components/Dashboard/Widgets/ErrorsByOrigin/ErrorsByOrigin.js +++ b/frontend/app/components/Dashboard/Widgets/ErrorsByOrigin/ErrorsByOrigin.js @@ -29,6 +29,7 @@ export default class ErrorsByOrigin extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/ErrorsByType/ErrorsByType.js b/frontend/app/components/Dashboard/Widgets/ErrorsByType/ErrorsByType.js index 3bca2406c..4421a3fbb 100644 --- a/frontend/app/components/Dashboard/Widgets/ErrorsByType/ErrorsByType.js +++ b/frontend/app/components/Dashboard/Widgets/ErrorsByType/ErrorsByType.js @@ -31,6 +31,7 @@ export default class ErrorsByType extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/ErrorsPerDomain/ErrorsPerDomain.js b/frontend/app/components/Dashboard/Widgets/ErrorsPerDomain/ErrorsPerDomain.js index 68752c46b..11af3f7d7 100644 --- a/frontend/app/components/Dashboard/Widgets/ErrorsPerDomain/ErrorsPerDomain.js +++ b/frontend/app/components/Dashboard/Widgets/ErrorsPerDomain/ErrorsPerDomain.js @@ -15,6 +15,7 @@ export default class ErrorsPerDomain extends React.PureComponent {
diff --git a/frontend/app/components/Dashboard/Widgets/FPS/FPS.js b/frontend/app/components/Dashboard/Widgets/FPS/FPS.js index d91379188..843cea3db 100644 --- a/frontend/app/components/Dashboard/Widgets/FPS/FPS.js +++ b/frontend/app/components/Dashboard/Widgets/FPS/FPS.js @@ -26,6 +26,7 @@ export default class FPS extends React.PureComponent { return ( diff --git a/frontend/app/components/Dashboard/Widgets/LastFrustrations/LastFrustrations.js b/frontend/app/components/Dashboard/Widgets/LastFrustrations/LastFrustrations.js index 23f5731d9..fcd36d98e 100644 --- a/frontend/app/components/Dashboard/Widgets/LastFrustrations/LastFrustrations.js +++ b/frontend/app/components/Dashboard/Widgets/LastFrustrations/LastFrustrations.js @@ -12,6 +12,7 @@ export default class LastFeedbacks extends React.PureComponent { { sessions.map(({ diff --git a/frontend/app/components/Dashboard/Widgets/MemoryConsumption/MemoryConsumption.js b/frontend/app/components/Dashboard/Widgets/MemoryConsumption/MemoryConsumption.js index 839db02bc..14ed08d93 100644 --- a/frontend/app/components/Dashboard/Widgets/MemoryConsumption/MemoryConsumption.js +++ b/frontend/app/components/Dashboard/Widgets/MemoryConsumption/MemoryConsumption.js @@ -26,6 +26,7 @@ export default class MemoryConsumption extends React.PureComponent {
diff --git a/frontend/app/components/Dashboard/Widgets/MostImpactfulErrors/MostImpactfulErrors.js b/frontend/app/components/Dashboard/Widgets/MostImpactfulErrors/MostImpactfulErrors.js index 6f2d300a1..a86e23220 100644 --- a/frontend/app/components/Dashboard/Widgets/MostImpactfulErrors/MostImpactfulErrors.js +++ b/frontend/app/components/Dashboard/Widgets/MostImpactfulErrors/MostImpactfulErrors.js @@ -48,6 +48,7 @@ export default class MostImpactfulErrors extends React.PureComponent {
@@ -46,4 +47,4 @@ function BreakdownOfLoadedResources(props: Props) { ); } -export default BreakdownOfLoadedResources; \ No newline at end of file +export default BreakdownOfLoadedResources; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CPULoad/CPULoad.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CPULoad/CPULoad.tsx index 53356bf0d..311b481c6 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CPULoad/CPULoad.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CPULoad/CPULoad.tsx @@ -19,6 +19,7 @@ function CPULoad(props: Props) { return ( @@ -54,4 +55,4 @@ function CPULoad(props: Props) { ); } -export default CPULoad; \ No newline at end of file +export default CPULoad; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallWithErrors/CallWithErrors.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallWithErrors/CallWithErrors.tsx index 45673614f..d85512786 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallWithErrors/CallWithErrors.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallWithErrors/CallWithErrors.tsx @@ -61,6 +61,7 @@ function CallWithErrors(props: Props) { diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors4xx/CallsErrors4xx.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors4xx/CallsErrors4xx.tsx index afaaeb37d..ce62bedff 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors4xx/CallsErrors4xx.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors4xx/CallsErrors4xx.tsx @@ -16,6 +16,7 @@ function CallsErrors4xx(props: Props) { return ( @@ -46,4 +47,4 @@ function CallsErrors4xx(props: Props) { ); } -export default CallsErrors4xx; \ No newline at end of file +export default CallsErrors4xx; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors5xx/CallsErrors5xx.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors5xx/CallsErrors5xx.tsx index cc87d5c26..9792e9fce 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors5xx/CallsErrors5xx.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/CallsErrors5xx/CallsErrors5xx.tsx @@ -16,6 +16,7 @@ function CallsErrors5xx(props: Props) { return ( @@ -46,4 +47,4 @@ function CallsErrors5xx(props: Props) { ); } -export default CallsErrors5xx; \ No newline at end of file +export default CallsErrors5xx; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/Crashes/Crashes.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/Crashes/Crashes.tsx index 0fa472db9..69a7c2f6b 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/Crashes/Crashes.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/Crashes/Crashes.tsx @@ -18,6 +18,7 @@ function Crashes(props: Props) { return ( @@ -52,4 +53,4 @@ function Crashes(props: Props) { ); } -export default Crashes; \ No newline at end of file +export default Crashes; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/DomBuildingTime/DomBuildingTime.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/DomBuildingTime/DomBuildingTime.tsx index f14dc5cd7..7eea40a8a 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/DomBuildingTime/DomBuildingTime.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/DomBuildingTime/DomBuildingTime.tsx @@ -33,6 +33,7 @@ function DomBuildingTime(props: Props) { return ( <> @@ -87,4 +88,4 @@ export default withRequest({ requestName: "fetchOptions", endpoint: '/dashboard/' + toUnderscore(WIDGET_KEY) + '/search', method: 'GET' -})(DomBuildingTime) \ No newline at end of file +})(DomBuildingTime) diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByOrigin/ErrorsByOrigin.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByOrigin/ErrorsByOrigin.tsx index f50859051..dded3aef0 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByOrigin/ErrorsByOrigin.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByOrigin/ErrorsByOrigin.tsx @@ -17,6 +17,7 @@ function ErrorsByOrigin(props: Props) { return ( @@ -49,4 +50,4 @@ function ErrorsByOrigin(props: Props) { ); } -export default ErrorsByOrigin; \ No newline at end of file +export default ErrorsByOrigin; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByType/ErrorsByType.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByType/ErrorsByType.tsx index 8d01941c8..f3d4a6f0b 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByType/ErrorsByType.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsByType/ErrorsByType.tsx @@ -16,6 +16,7 @@ function ErrorsByType(props: Props) { return ( @@ -48,4 +49,4 @@ function ErrorsByType(props: Props) { ); } -export default ErrorsByType; \ No newline at end of file +export default ErrorsByType; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx index fab8ced65..d58effb2b 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx @@ -17,6 +17,7 @@ function ErrorsPerDomain(props: Props) { size="small" show={ metric.data.chart.length === 0 } style={{ height: '240px'}} + title="No recordings found" >
{metric.data.chart.map((item, i) => @@ -34,4 +35,4 @@ function ErrorsPerDomain(props: Props) { ); } -export default ErrorsPerDomain; \ No newline at end of file +export default ErrorsPerDomain; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/FPS/FPS.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/FPS/FPS.tsx index e246d3c3f..baea7156d 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/FPS/FPS.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/FPS/FPS.tsx @@ -19,6 +19,7 @@ function FPS(props: Props) { return ( <> @@ -57,4 +58,4 @@ function FPS(props: Props) { ); } -export default FPS; \ No newline at end of file +export default FPS; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/MemoryConsumption/MemoryConsumption.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/MemoryConsumption/MemoryConsumption.tsx index 80e1f4d9c..4889f05f7 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/MemoryConsumption/MemoryConsumption.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/MemoryConsumption/MemoryConsumption.tsx @@ -22,6 +22,7 @@ function MemoryConsumption(props: Props) { <>
@@ -60,4 +61,4 @@ function MemoryConsumption(props: Props) { ); } -export default MemoryConsumption; \ No newline at end of file +export default MemoryConsumption; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.tsx index 4bd0c2b52..74ae4c997 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.tsx @@ -17,6 +17,7 @@ function ResourceLoadedVsResponseEnd(props: Props) { <>
@@ -119,4 +120,4 @@ export default withRequest({ requestName: "fetchOptions", endpoint: '/dashboard/' + toUnderscore(WIDGET_KEY) + '/search', method: 'GET' -})(ResourceLoadingTime) \ No newline at end of file +})(ResourceLoadingTime) diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTime/ResponseTime.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTime/ResponseTime.tsx index 0d6587386..6ed001ff1 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTime/ResponseTime.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTime/ResponseTime.tsx @@ -34,6 +34,7 @@ function ResponseTime(props: Props) { return ( <> @@ -88,4 +89,4 @@ export default withRequest({ requestName: "fetchOptions", endpoint: '/dashboard/' + toUnderscore(WIDGET_KEY) + '/search', method: 'GET' -})(ResponseTime) \ No newline at end of file +})(ResponseTime) diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTimeDistribution/ResponseTimeDistribution.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTimeDistribution/ResponseTimeDistribution.tsx index 5190157ae..8021b9f7d 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTimeDistribution/ResponseTimeDistribution.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ResponseTimeDistribution/ResponseTimeDistribution.tsx @@ -49,6 +49,7 @@ function ResponseTimeDistribution(props: Props) { return ( @@ -125,4 +126,4 @@ function ResponseTimeDistribution(props: Props) { ); } -export default ResponseTimeDistribution; \ No newline at end of file +export default ResponseTimeDistribution; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.tsx index 55434e2a9..495ac5126 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.tsx @@ -15,6 +15,7 @@ function SessionsAffectedByJSErrors(props: Props) { const { data, metric } = props; return ( @@ -52,4 +53,4 @@ function SessionsImpactedBySlowRequests(props: Props) { ); } -export default SessionsImpactedBySlowRequests; \ No newline at end of file +export default SessionsImpactedBySlowRequests; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx index 6b155364d..48db4f67c 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx @@ -19,6 +19,7 @@ function SessionsPerBrowser(props: Props) { return (
@@ -38,4 +39,4 @@ function SessionsPerBrowser(props: Props) { ); } -export default SessionsPerBrowser; \ No newline at end of file +export default SessionsPerBrowser; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx index c6adbeff6..1291305ed 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx @@ -16,6 +16,7 @@ function SlowestDomains(props: Props) { size="small" show={ metric.data.chart.length === 0 } style={{ maxHeight: '240px' }} + title="No recordings found" >
{metric.data.chart.map((item, i) => diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx index e87a66b24..6661623c2 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx @@ -63,7 +63,7 @@ function SpeedIndexByLocation(props: Props) { }; return ( - +
diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/TimeToRender/TimeToRender.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/TimeToRender/TimeToRender.tsx index 7fceb853d..94334ee5d 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/TimeToRender/TimeToRender.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/TimeToRender/TimeToRender.tsx @@ -35,6 +35,7 @@ function TimeToRender(props: Props) { <>
@@ -88,4 +89,4 @@ export default withRequest({ requestName: "fetchOptions", endpoint: '/dashboard/' + toUnderscore(WIDGET_KEY) + '/search', method: 'GET' -})(TimeToRender) \ No newline at end of file +})(TimeToRender) diff --git a/frontend/app/components/Dashboard/Widgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.js b/frontend/app/components/Dashboard/Widgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.js index c30375aa7..d04a5cef5 100644 --- a/frontend/app/components/Dashboard/Widgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.js +++ b/frontend/app/components/Dashboard/Widgets/ResourceLoadedVsResponseEnd/ResourceLoadedVsResponseEnd.js @@ -28,6 +28,7 @@ export default class ResourceLoadedVsResponseEnd extends React.PureComponent { diff --git a/frontend/app/components/Dashboard/Widgets/ResourceLoadingTime/ResourceLoadingTime.js b/frontend/app/components/Dashboard/Widgets/ResourceLoadingTime/ResourceLoadingTime.js index 262312f1b..8f95a3479 100644 --- a/frontend/app/components/Dashboard/Widgets/ResourceLoadingTime/ResourceLoadingTime.js +++ b/frontend/app/components/Dashboard/Widgets/ResourceLoadingTime/ResourceLoadingTime.js @@ -66,6 +66,7 @@ export default class ResourceLoadingTime extends React.PureComponent {
@@ -96,6 +97,7 @@ export default class ResourceLoadingTime extends React.PureComponent {
diff --git a/frontend/app/components/Dashboard/Widgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.js b/frontend/app/components/Dashboard/Widgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.js index 747247872..057122195 100644 --- a/frontend/app/components/Dashboard/Widgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.js +++ b/frontend/app/components/Dashboard/Widgets/SessionsAffectedByJSErrors/SessionsAffectedByJSErrors.js @@ -36,6 +36,7 @@ export default class SessionsAffectedByJSErrors extends React.PureComponent {
{data.chart.map((item, i) => @@ -40,4 +41,4 @@ export default class SessionsPerBrowser extends React.PureComponent { ); } -} \ No newline at end of file +} diff --git a/frontend/app/components/Dashboard/Widgets/SlowestDomains/SlowestDomains.js b/frontend/app/components/Dashboard/Widgets/SlowestDomains/SlowestDomains.js index b31b93891..9f85ae412 100644 --- a/frontend/app/components/Dashboard/Widgets/SlowestDomains/SlowestDomains.js +++ b/frontend/app/components/Dashboard/Widgets/SlowestDomains/SlowestDomains.js @@ -16,6 +16,7 @@ export default class ResponseTime extends React.PureComponent {
{data.partition && data.partition.map((item, i) => diff --git a/frontend/app/components/Dashboard/Widgets/SlowestImages/SlowestImages.js b/frontend/app/components/Dashboard/Widgets/SlowestImages/SlowestImages.js index 87cf5478f..7bfc0cfd9 100644 --- a/frontend/app/components/Dashboard/Widgets/SlowestImages/SlowestImages.js +++ b/frontend/app/components/Dashboard/Widgets/SlowestImages/SlowestImages.js @@ -41,6 +41,7 @@ export default class SlowestImages extends React.PureComponent {
diff --git a/frontend/app/components/Dashboard/Widgets/TimeToRender/TimeToRender.js b/frontend/app/components/Dashboard/Widgets/TimeToRender/TimeToRender.js index 956174cba..1ac489588 100644 --- a/frontend/app/components/Dashboard/Widgets/TimeToRender/TimeToRender.js +++ b/frontend/app/components/Dashboard/Widgets/TimeToRender/TimeToRender.js @@ -59,6 +59,7 @@ export default class TimeToRender extends React.PureComponent { -
+
onEdit(true)} className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer" actionButton={ - setTooltip(false)}> - {/* @ts-ignore */} + /* @ts-ignore */
} > - - } />
@@ -166,7 +164,7 @@ function DashboardView(props: Props) {
-
+
{/* @ts-ignore */}

-
+
{metrics ? metrics.map((metric: any) => ( {description}
-
- Don’t find the one you need? - -
+

-
+
{activeCategory && categories.map((category) => ( {activeCategory && activeCategory.widgets.map((metric: any) => ( diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 31e73fda3..7a6df145f 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -179,7 +179,7 @@ function WidgetChart(props: Props) { } return ( - {renderChart()} +
{renderChart()}
); } diff --git a/frontend/app/components/Errors/Error/SideSection.js b/frontend/app/components/Errors/Error/SideSection.js index 6c1702c78..da6e5803b 100644 --- a/frontend/app/components/Errors/Error/SideSection.js +++ b/frontend/app/components/Errors/Error/SideSection.js @@ -87,7 +87,7 @@ export default class SideSection extends React.PureComponent {

Overview

( - +
{ !isWidget && ( stages.map((filter: any, index: any) => ( diff --git a/frontend/app/components/Session/IOSPlayer/Crashes.js b/frontend/app/components/Session/IOSPlayer/Crashes.js index 9fe3d9ad0..015dece96 100644 --- a/frontend/app/components/Session/IOSPlayer/Crashes.js +++ b/frontend/app/components/Session/IOSPlayer/Crashes.js @@ -31,6 +31,7 @@ function Crashes({ player }) { @@ -48,4 +49,4 @@ function Crashes({ player }) { ); } -export default observer(Crashes); \ No newline at end of file +export default observer(Crashes); diff --git a/frontend/app/components/Session/IOSPlayer/Logs.js b/frontend/app/components/Session/IOSPlayer/Logs.js index 2469a7e1a..e9fe033d7 100644 --- a/frontend/app/components/Session/IOSPlayer/Logs.js +++ b/frontend/app/components/Session/IOSPlayer/Logs.js @@ -45,6 +45,7 @@ function Logs({ player }) { { filtered.map(log => @@ -57,4 +58,4 @@ function Logs({ player }) { ); } -export default observer(Logs); \ No newline at end of file +export default observer(Logs); diff --git a/frontend/app/components/Session_/Exceptions/Exceptions.js b/frontend/app/components/Session_/Exceptions/Exceptions.js index e08145ad7..b2d57457a 100644 --- a/frontend/app/components/Session_/Exceptions/Exceptions.js +++ b/frontend/app/components/Session_/Exceptions/Exceptions.js @@ -97,6 +97,7 @@ export default class Exceptions extends React.PureComponent { { filtered.map(e => ( @@ -115,4 +116,4 @@ export default class Exceptions extends React.PureComponent { ); } -} \ No newline at end of file +} diff --git a/frontend/app/components/Session_/GraphQL/GraphQL.js b/frontend/app/components/Session_/GraphQL/GraphQL.js index 2d3a112e4..cb7b46b7f 100644 --- a/frontend/app/components/Session_/GraphQL/GraphQL.js +++ b/frontend/app/components/Session_/GraphQL/GraphQL.js @@ -100,6 +100,7 @@ export default class GraphQL extends React.PureComponent { {
- +
{timeColumns.map((_, index) => ( diff --git a/frontend/app/dateRange.js b/frontend/app/dateRange.js index 70f674665..77f2c3d2e 100644 --- a/frontend/app/dateRange.js +++ b/frontend/app/dateRange.js @@ -9,7 +9,7 @@ export const CUSTOM_RANGE = "CUSTOM_RANGE"; const DATE_RANGE_LABELS = { // LAST_30_MINUTES: '30 Minutes', // TODAY: 'Today', - LAST_24_HOURS: "Last 24 Hours", + LAST_24_HOURS: "Past 24 Hours", // YESTERDAY: 'Yesterday', LAST_7_DAYS: "Past 7 Days", LAST_30_DAYS: "Past 30 Days", diff --git a/frontend/app/types/app/period.js b/frontend/app/types/app/period.js index da69519b0..8ab9869e0 100644 --- a/frontend/app/types/app/period.js +++ b/frontend/app/types/app/period.js @@ -18,7 +18,7 @@ const RANGE_LABELS = { [LAST_30_MINUTES]: "Last 30 Minutes", [TODAY]: "Today", [YESTERDAY]: "Yesterday", - [LAST_24_HOURS]: "Last 24 Hours", + [LAST_24_HOURS]: "Past 24 Hours", [LAST_7_DAYS]: "Last 7 Days", [LAST_30_DAYS]: "Last 30 Days", [THIS_MONTH]: "This Month", From db16f2b89bd8c90e04872ff1e771d8cad68f7082 Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 11:25:13 +0200 Subject: [PATCH 15/24] fix(ui): metric rows, paddings, dashboard nav link --- .../DashboardList/DashboardList.tsx | 2 +- .../DashboardList/DashboardListItem.tsx | 4 +- .../DashboardList/DashboardsView.tsx | 4 +- .../MetricListItem/MetricListItem.tsx | 43 ++++++++----------- .../components/MetricsList/MetricsList.tsx | 4 +- .../components/MetricsView/MetricsView.tsx | 6 +-- frontend/app/components/Header/Header.js | 5 +++ 7 files changed, 32 insertions(+), 36 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 4aa5a43e5..466103dc8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -31,7 +31,7 @@ function DashboardList() { } >
-
+
Title
Visibility
Created
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx index 057b22d9a..61aeb15b9 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx @@ -22,14 +22,14 @@ function DashboardListItem(props: Props) { history.push(path); }; return ( -
+
-
{dashboard.name}
+
{dashboard.name}
{/*
*/} diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx index 75b4aaf4e..c9b98a745 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -21,10 +21,10 @@ function DashboardsView({ history, siteId }: { history: any, siteId: string }) { } return ( -
+
- +
diff --git a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx index 18f580851..23bcedb2e 100644 --- a/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx +++ b/frontend/app/components/Dashboard/components/MetricListItem/MetricListItem.tsx @@ -1,27 +1,13 @@ import React from 'react'; -import { Icon, Link, Popup } from 'UI'; +import { Icon, Link } from 'UI'; import { checkForRecent } from 'App/date'; import { Tooltip } from 'react-tippy' +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { withSiteId } from 'App/routes'; -interface Props { +interface Props extends RouteComponentProps { metric: any; -} - -function DashboardLink({ dashboards}: any) { - return ( - dashboards.map((dashboard: any) => ( - - -
-
- -
- {dashboard.name} -
- -
- )) - ); + siteId: string; } function MetricTypeIcon({ type }: any) { @@ -49,18 +35,23 @@ function MetricTypeIcon({ type }: any) { ) } -function MetricListItem(props: Props) { - const { metric } = props; - + +function MetricListItem(props: Props) { + const { metric, history, siteId } = props; + + const onItemClick = () => { + const path = withSiteId(`/metrics/${metric.metricId}`, siteId); + history.push(path); + }; return ( -
+
- +
{metric.name} - +
{metric.owner}
@@ -75,4 +66,4 @@ function MetricListItem(props: Props) { ); } -export default MetricListItem; +export default withRouter(MetricListItem); diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 8c453688e..dea6c4a4f 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -8,7 +8,7 @@ import { sliceListPerPage } from 'App/utils'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import { IWidget } from 'App/mstore/types/widget'; -function MetricsList() { +function MetricsList({ siteId }: { siteId: string }) { const { metricStore } = useStore(); const metrics = useObserver(() => metricStore.metrics); const metricsSearch = useObserver(() => metricStore.metricsSearch); @@ -46,7 +46,7 @@ function MetricsList() { {sliceListPerPage(list, metricStore.page - 1, metricStore.pageSize).map((metric: any) => ( - + ))}
diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index afe0dd337..85cefe70d 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -9,14 +9,14 @@ import { useObserver } from 'mobx-react-lite'; interface Props{ siteId: number; } -function MetricsView(props: Props) { +function MetricsView({ siteId }: Props) { const { metricStore } = useStore(); React.useEffect(() => { metricStore.fetchList(); }, []); return useObserver(() => ( -
+
@@ -30,7 +30,7 @@ function MetricsView(props: Props) { Create custom Metrics to capture key interactions and track KPIs.
- +
)); } diff --git a/frontend/app/components/Header/Header.js b/frontend/app/components/Header/Header.js index 1b5b97c22..f06c7321e 100644 --- a/frontend/app/components/Header/Header.js +++ b/frontend/app/components/Header/Header.js @@ -4,6 +4,7 @@ import { NavLink, withRouter } from 'react-router-dom'; import cn from 'classnames'; import { sessions, + metrics, assist, client, dashboard, @@ -27,6 +28,7 @@ import { useStore } from 'App/mstore'; import { useObserver } from 'mobx-react-lite'; const DASHBOARD_PATH = dashboard(); +const METRICS_PATH = metrics(); const SESSIONS_PATH = sessions(); const ASSIST_PATH = assist(); const CLIENT_PATH = client(CLIENT_DEFAULT_TAB); @@ -94,6 +96,9 @@ const Header = (props) => { to={ withSiteId(DASHBOARD_PATH, siteId) } className={ styles.nav } activeClassName={ styles.active } + isActive={ (_, location) => { + return location.pathname.includes(DASHBOARD_PATH) || location.pathname.includes(METRICS_PATH); + }} > { 'Dashboards' } From 2d87da1b996da4ec9e9650a51deb4fbde913d961 Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 11:54:14 +0200 Subject: [PATCH 16/24] fix(ui): fix for breadcrumb hover, empty metric icon etc --- .../CustomMetricTableErrors.tsx | 10 ++++------ .../components/DashboardList/DashboardList.tsx | 7 +++---- .../Dashboard/components/MetricsList/MetricsList.tsx | 9 ++++----- .../components/WidgetPreview/WidgetPreview.tsx | 2 +- .../app/components/shared/Breadcrumb/Breadcrumb.tsx | 2 +- frontend/app/components/ui/SVG.tsx | 4 +++- frontend/app/svg/icons/no-dashboard.svg | 12 ++++++++++++ frontend/app/svg/icons/no-metrics.svg | 12 ++++++++++++ 8 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 frontend/app/svg/icons/no-dashboard.svg create mode 100644 frontend/app/svg/icons/no-metrics.svg diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx index 55fcb29eb..1add0810c 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx @@ -1,11 +1,10 @@ import React, { useEffect } from "react"; -import { Pagination, NoContent } from "UI"; +import { Pagination, NoContent, Icon } from "UI"; import ErrorListItem from "App/components/Dashboard/components/Errors/ErrorListItem"; import { withRouter, RouteComponentProps } from "react-router-dom"; import { useModal } from "App/components/Modal"; import ErrorDetailsModal from "App/components/Dashboard/components/Errors/ErrorDetailsModal"; import { useStore } from "App/mstore"; -import { overPastString } from "App/dateRange"; interface Props { metric: any; data: any; @@ -18,7 +17,6 @@ function CustomMetricTableErrors(props: RouteComponentProps & Props) { const errorId = new URLSearchParams(props.location.search).get("errorId"); const { showModal, hideModal } = useModal(); const { dashboardStore } = useStore(); - const period = dashboardStore.period; const onErrorClick = (e: any, error: any) => { e.stopPropagation(); @@ -46,9 +44,9 @@ function CustomMetricTableErrors(props: RouteComponentProps & Props) { return ( No errors found in the selected time range
} + show={!data.errors || data.errors.length === 0} + size="small" >
{data.errors && diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 466103dc8..6498bcf6a 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -1,10 +1,9 @@ import { observer } from 'mobx-react-lite'; import React from 'react'; -import { NoContent, Pagination } from 'UI'; +import { NoContent, Pagination, Icon } from 'UI'; import { useStore } from 'App/mstore'; import { filterList } from 'App/utils'; import { sliceListPerPage } from 'App/utils'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import DashboardListItem from './DashboardListItem'; function DashboardList() { @@ -25,8 +24,8 @@ function DashboardList() { show={lenth === 0} title={
- -
No data available.
+ +
You haven't created any dashboards yet
} > diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index dea6c4a4f..438ea09ce 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -1,11 +1,10 @@ import { useObserver } from 'mobx-react-lite'; import React, { useEffect } from 'react'; -import { NoContent, Pagination } from 'UI'; +import { NoContent, Pagination, Icon } from 'UI'; import { useStore } from 'App/mstore'; -import { getRE, filterList } from 'App/utils'; +import { filterList } from 'App/utils'; import MetricListItem from '../MetricListItem'; import { sliceListPerPage } from 'App/utils'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import { IWidget } from 'App/mstore/types/widget'; function MetricsList({ siteId }: { siteId: string }) { @@ -31,8 +30,8 @@ function MetricsList({ siteId }: { siteId: string }) { show={lenth === 0} title={
- -
No data available.
+ +
You haven't created any metrics yet
} > diff --git a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx index 3cc02fd76..9e5465382 100644 --- a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx @@ -61,7 +61,7 @@ function WidgetPreview(props: Props) { return useObserver(() => ( <>
-
+

{getWidgetTitle()}

diff --git a/frontend/app/components/shared/Breadcrumb/Breadcrumb.tsx b/frontend/app/components/shared/Breadcrumb/Breadcrumb.tsx index 35c0ea45f..7a48dedf5 100644 --- a/frontend/app/components/shared/Breadcrumb/Breadcrumb.tsx +++ b/frontend/app/components/shared/Breadcrumb/Breadcrumb.tsx @@ -16,7 +16,7 @@ function Breadcrumb(props: Props) { ); } return ( -
+
{index === 0 && } {item.label} diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index 4a6582789..732c7d403 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -234,7 +234,7 @@ const SVG = (props: Props) => { case 'id-card': return ; case 'image': return ; case 'info-circle-fill': return ; - case 'info-circle': return ; + case 'info-circle': return ; case 'info-square': return ; case 'info': return ; case 'inspect': return ; @@ -285,7 +285,9 @@ const SVG = (props: Props) => { case 'mobile': return ; case 'mouse-alt': return ; case 'next1': return ; + case 'no-dashboard': return ; case 'no-metrics-chart': return ; + case 'no-metrics': return ; case 'os/android': return ; case 'os/chrome_os': return ; case 'os/fedora': return ; diff --git a/frontend/app/svg/icons/no-dashboard.svg b/frontend/app/svg/icons/no-dashboard.svg new file mode 100644 index 000000000..2e849b192 --- /dev/null +++ b/frontend/app/svg/icons/no-dashboard.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/no-metrics.svg b/frontend/app/svg/icons/no-metrics.svg new file mode 100644 index 000000000..6809e0f79 --- /dev/null +++ b/frontend/app/svg/icons/no-metrics.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + From ee065619ba856625ab3411515a6ecc5ffba013e1 Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 12:25:41 +0200 Subject: [PATCH 17/24] fix(ui): fix metric creation title, sessions list --- .../WidgetPreview/WidgetPreview.tsx | 24 +++---------------- .../WidgetSessions/WidgetSessions.tsx | 4 ++-- .../components/WidgetView/WidgetView.tsx | 2 +- .../WidgetWrapper/WidgetWrapper.tsx | 3 ++- 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx index 9e5465382..98bb11a1b 100644 --- a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx @@ -4,7 +4,6 @@ import WidgetWrapper from '../WidgetWrapper'; import { useStore } from 'App/mstore'; import { SegmentSelection, Button, Icon } from 'UI'; import { useObserver } from 'mobx-react-lite'; -import SelectDateRange from 'Shared/SelectDateRange'; import { FilterKey } from 'Types/filter/filterType'; import WidgetDateRange from '../WidgetDateRange/WidgetDateRange'; // import Period, { LAST_24_HOURS, LAST_30_DAYS } from 'Types/app/period'; @@ -12,6 +11,7 @@ import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelecti interface Props { className?: string; + name: string; } function WidgetPreview(props: Props) { const [showDashboardSelectionModal, setShowDashboardSelectionModal] = React.useState(false); @@ -38,24 +38,6 @@ function WidgetPreview(props: Props) { // }) // } - const getWidgetTitle = () => { - if (isTimeSeries) { - return 'Time Series'; - } else if (isTable) { - if (metric.metricOf === FilterKey.SESSIONS) { - // return 'Table of Sessions'; - return
Sessions {metric.data.total}
; - } else if (metric.metricOf === FilterKey.ERRORS) { - // return 'Table of Errors'; - return
Errors {metric.data.total}
; - } else { - return 'Table'; - } - } else if (metric.metricType === 'funnel') { - return 'Funnel'; - } - } - const canAddToDashboard = metric.exists() && dashboards.length > 0; return useObserver(() => ( @@ -63,7 +45,7 @@ function WidgetPreview(props: Props) {

- {getWidgetTitle()} + {props.name}

{isTimeSeries && ( @@ -120,7 +102,7 @@ function WidgetPreview(props: Props) {
- +
{ canAddToDashboard && ( diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index e3de553d2..d1e10d10a 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -62,7 +62,7 @@ function WidgetSessions(props: Props) { }, [filter.startTimestamp, filter.endTimestamp, filter.filters, depsString, metricStore.sessionsPage]); return useObserver(() => ( -
+

Sessions

@@ -80,7 +80,7 @@ function WidgetSessions(props: Props) { )}
-
+
}
- + {widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ( <> {(widget.metricType === 'table' || widget.metricType === 'timeseries') && } diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapper.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapper.tsx index a9b6e2046..6354af350 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapper.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapper.tsx @@ -25,6 +25,7 @@ interface Props { history?: any onClick?: () => void; isWidget?: boolean; + hideName?: boolean; } function WidgetWrapper(props: Props & RouteComponentProps) { const { dashboardStore } = useStore(); @@ -112,7 +113,7 @@ function WidgetWrapper(props: Props & RouteComponentProps) {
-
{widget.name}
+ {!props.hideName ?
{widget.name}
: null} {isWidget && (
{!isPredefined && isTimeSeries && ( From 5bf2d1008ba0cd6f222fe2a08d92b00ca67e2e14 Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 13:20:34 +0200 Subject: [PATCH 18/24] fix(ui): fix Icon typing --- frontend/app/components/ui/Icon/Icon.tsx | 6 +++--- frontend/app/components/ui/SVG.tsx | 7 ++++++- frontend/app/svg/icons/funnel-new.svg | 3 +++ frontend/app/svg/icons/graph-up.svg | 3 +++ frontend/app/svg/icons/table-new.svg | 3 +++ frontend/scripts/icons.ts | 4 +++- 6 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 frontend/app/svg/icons/funnel-new.svg create mode 100644 frontend/app/svg/icons/graph-up.svg create mode 100644 frontend/app/svg/icons/table-new.svg diff --git a/frontend/app/components/ui/Icon/Icon.tsx b/frontend/app/components/ui/Icon/Icon.tsx index 745d6412d..74e91e1ed 100644 --- a/frontend/app/components/ui/Icon/Icon.tsx +++ b/frontend/app/components/ui/Icon/Icon.tsx @@ -1,10 +1,10 @@ import React from 'react'; import cn from 'classnames'; -import SVG from 'UI/SVG'; +import SVG, { IconNames } from 'UI/SVG'; import styles from './icon.module.css'; -interface IProps { - name: string +interface IProps { + name: IconNames size?: number | string height?: number width?: number diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index 732c7d403..1ed4ed218 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -1,8 +1,10 @@ import React from 'react'; +export type IconNames = 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-clockwise' | 'arrow-down' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_bear' | 'avatar/icn_beaver' | 'avatar/icn_bird' | 'avatar/icn_bison' | 'avatar/icn_camel' | 'avatar/icn_chameleon' | 'avatar/icn_deer' | 'avatar/icn_dog' | 'avatar/icn_dolphin' | 'avatar/icn_elephant' | 'avatar/icn_fish' | 'avatar/icn_fox' | 'avatar/icn_gorilla' | 'avatar/icn_hippo' | 'avatar/icn_horse' | 'avatar/icn_hyena' | 'avatar/icn_kangaroo' | 'avatar/icn_lemur' | 'avatar/icn_mammel' | 'avatar/icn_monkey' | 'avatar/icn_moose' | 'avatar/icn_panda' | 'avatar/icn_penguin' | 'avatar/icn_porcupine' | 'avatar/icn_quail' | 'avatar/icn_rabbit' | 'avatar/icn_rhino' | 'avatar/icn_sea_horse' | 'avatar/icn_sheep' | 'avatar/icn_snake' | 'avatar/icn_squirrel' | 'avatar/icn_tapir' | 'avatar/icn_turtle' | 'avatar/icn_vulture' | 'avatar/icn_wild1' | 'avatar/icn_wild_bore' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'bell-plus' | 'bell' | 'binoculars' | 'book' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-square-quote' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'clipboard-list-check' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-front' | 'cubes' | 'dashboard-icn' | 'desktop' | 'device' | 'diagram-3' | 'dizzy' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'enter' | 'envelope' | 'event/click' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/link' | 'event/location' | 'event/resize' | 'event/view' | 'exclamation-circle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'file-code' | 'file-medical-alt' | 'file' | 'filter' | 'filters/arrow-return-right' | 'filters/browser' | 'filters/click' | 'filters/clickrage' | 'filters/code' | 'filters/console' | 'filters/country' | 'filters/cpu-load' | 'filters/custom' | 'filters/device' | 'filters/dom-complete' | 'filters/duration' | 'filters/error' | 'filters/fetch-failed' | 'filters/fetch' | 'filters/file-code' | 'filters/graphql' | 'filters/i-cursor' | 'filters/input' | 'filters/lcpt' | 'filters/link' | 'filters/location' | 'filters/memory-load' | 'filters/metadata' | 'filters/os' | 'filters/perfromance-network-request' | 'filters/platform' | 'filters/referrer' | 'filters/resize' | 'filters/rev-id' | 'filters/state-action' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'fullscreen' | 'funnel/cpu-fill' | 'funnel/cpu' | 'funnel/dizzy' | 'funnel/emoji-angry-fill' | 'funnel/emoji-angry' | 'funnel/emoji-dizzy-fill' | 'funnel/exclamation-circle-fill' | 'funnel/exclamation-circle' | 'funnel/file-earmark-break-fill' | 'funnel/file-earmark-break' | 'funnel/file-earmark-minus-fill' | 'funnel/file-earmark-minus' | 'funnel/file-medical-alt' | 'funnel/file-x' | 'funnel/hdd-fill' | 'funnel/hourglass-top' | 'funnel/image-fill' | 'funnel/image' | 'funnel/microchip' | 'funnel/mouse' | 'funnel/patch-exclamation-fill' | 'funnel/sd-card' | 'funnel-fill' | 'funnel-new' | 'funnel' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-3x3' | 'grid-check' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'inspect' | 'integrations/assist' | 'integrations/bugsnag-text' | 'integrations/bugsnag' | 'integrations/cloudwatch-text' | 'integrations/cloudwatch' | 'integrations/datadog' | 'integrations/elasticsearch-text' | 'integrations/elasticsearch' | 'integrations/github' | 'integrations/graphql' | 'integrations/jira-text' | 'integrations/jira' | 'integrations/mobx' | 'integrations/newrelic-text' | 'integrations/newrelic' | 'integrations/ngrx' | 'integrations/openreplay-text' | 'integrations/openreplay' | 'integrations/redux' | 'integrations/rollbar-text' | 'integrations/rollbar' | 'integrations/segment' | 'integrations/sentry-text' | 'integrations/sentry' | 'integrations/slack-bw' | 'integrations/slack' | 'integrations/stackdriver' | 'integrations/sumologic-text' | 'integrations/sumologic' | 'integrations/vuejs' | 'journal-code' | 'layer-group' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-ul' | 'list' | 'lock-alt' | 'map-marker-alt' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'percent' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plus-circle' | 'plus' | 'prev1' | 'puzzle-piece' | 'question-circle' | 'quote-left' | 'quote-right' | 'redo-back' | 'redo' | 'remote-control' | 'replay-10' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slash-circle' | 'sliders' | 'social/slack' | 'social/trello' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'text-paragraph' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; + interface Props { - name: string; + name: IconNames; size?: number | string; width?: number | string; height?: number | string; @@ -217,10 +219,12 @@ const SVG = (props: Props) => { case 'funnel/patch-exclamation-fill': return ; case 'funnel/sd-card': return ; case 'funnel-fill': return ; + case 'funnel-new': return ; case 'funnel': return ; case 'geo-alt-fill-custom': return ; case 'github': return ; case 'graph-up-arrow': return ; + case 'graph-up': return ; case 'grid-3x3': return ; case 'grid-check': return ; case 'grip-horizontal': return ; @@ -347,6 +351,7 @@ const SVG = (props: Props) => { case 'stopwatch': return ; case 'store': return ; case 'sync-alt': return ; + case 'table-new': return ; case 'table': return ; case 'tablet-android': return ; case 'tachometer-slow': return ; diff --git a/frontend/app/svg/icons/funnel-new.svg b/frontend/app/svg/icons/funnel-new.svg new file mode 100644 index 000000000..36cb3c15c --- /dev/null +++ b/frontend/app/svg/icons/funnel-new.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app/svg/icons/graph-up.svg b/frontend/app/svg/icons/graph-up.svg new file mode 100644 index 000000000..7b12d457e --- /dev/null +++ b/frontend/app/svg/icons/graph-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app/svg/icons/table-new.svg b/frontend/app/svg/icons/table-new.svg new file mode 100644 index 000000000..702e7a05b --- /dev/null +++ b/frontend/app/svg/icons/table-new.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/scripts/icons.ts b/frontend/scripts/icons.ts index a89a8c3a3..4ad35692d 100644 --- a/frontend/scripts/icons.ts +++ b/frontend/scripts/icons.ts @@ -68,8 +68,10 @@ const plugins = (removeFill = true) => { fs.writeFileSync(`${UI_DIRNAME}/SVG.tsx`, ` import React from 'react'; +export type IconNames = ${icons.map(icon => "'"+ icon.slice(0, -4) + "'").join(' | ')}; + interface Props { - name: string; + name: IconNames; size?: number | string; width?: number | string; height?: number | string; From 50f82c2fd98a655f8569907aac88a9c45e8c71e1 Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 16:17:44 +0200 Subject: [PATCH 19/24] fix(player): fix filereader buffer --- .../app/player/MessageDistributor/MessageDistributor.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/app/player/MessageDistributor/MessageDistributor.ts b/frontend/app/player/MessageDistributor/MessageDistributor.ts index cd48f54da..2d73081fb 100644 --- a/frontend/app/player/MessageDistributor/MessageDistributor.ts +++ b/frontend/app/player/MessageDistributor/MessageDistributor.ts @@ -92,6 +92,7 @@ export default class MessageDistributor extends StatedScreen { private readonly lists = initLists(); private activityManager: ActivityManager | null = null; + private fileReader: MFileReader; private sessionStart: number; private navigationStartOffset: number = 0; @@ -151,11 +152,13 @@ export default class MessageDistributor extends StatedScreen { private readAndDistributeMessages(byteArray: Uint8Array, onReadCb?: (msg: Message) => void) { const msgs: Array = [] - const reader = new MFileReader(new Uint8Array(), this.sessionStart) + if (!this.fileReader) { + this.fileReader = new MFileReader(new Uint8Array(), this.sessionStart) + } - reader.append(byteArray) + this.fileReader.append(byteArray) let next: ReturnType - while (next = reader.next()) { + while (next = this.fileReader.next()) { const [msg, index] = next this.distributeMessage(msg, index) msgs.push(msg) From a0a09f293e061cf3ec8ecc1935f23f291afd155a Mon Sep 17 00:00:00 2001 From: sylenien Date: Fri, 12 Aug 2022 17:53:24 +0200 Subject: [PATCH 20/24] fix(ui): fix button focusing and nocontent icon size --- frontend/.prettierrc | 4 +- .../DashboardList/DashboardList.tsx | 4 +- .../components/MetricsList/MetricsList.tsx | 4 +- .../Session_/Player/Controls/Controls.js | 5 +- .../Controls/components/PlayerControls.tsx | 128 +++++++++++------- 5 files changed, 86 insertions(+), 59 deletions(-) diff --git a/frontend/.prettierrc b/frontend/.prettierrc index 761a3e639..4c38cc4c4 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,6 +1,6 @@ { - "tabWidth": 4, + "tabWidth": 2, "useTabs": false, - "printWidth": 150, + "printWidth": 100, "singleQuote": true } diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 6498bcf6a..4a0049df3 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -24,8 +24,8 @@ function DashboardList() { show={lenth === 0} title={
- -
You haven't created any dashboards yet
+ +
You haven't created any dashboards yet
} > diff --git a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx index 438ea09ce..e64026822 100644 --- a/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx +++ b/frontend/app/components/Dashboard/components/MetricsList/MetricsList.tsx @@ -30,8 +30,8 @@ function MetricsList({ siteId }: { siteId: string }) { show={lenth === 0} title={
- -
You haven't created any metrics yet
+ +
You haven't created any metrics yet
} > diff --git a/frontend/app/components/Session_/Player/Controls/Controls.js b/frontend/app/components/Session_/Player/Controls/Controls.js index 73371c6e1..951e2eead 100644 --- a/frontend/app/components/Session_/Player/Controls/Controls.js +++ b/frontend/app/components/Session_/Player/Controls/Controls.js @@ -8,7 +8,6 @@ import { selectStorageListNow, } from 'Player/store'; import LiveTag from 'Shared/LiveTag'; -import { session as sessionRoute, withSiteId } from 'App/routes'; import { toggleTimetravel, jumpToLive, @@ -31,7 +30,7 @@ import { EXCEPTIONS, INSPECTOR, } from 'Duck/components/player'; -import { ReduxTime, AssistDuration } from './Time'; +import { AssistDuration } from './Time'; import Timeline from './Timeline'; import ControlButton from './ControlButton'; import PlayerControls from './components/PlayerControls' @@ -121,7 +120,6 @@ function getStorageName(type) { toggleBottomBlock, }) export default class Controls extends React.Component { - componentDidMount() { document.addEventListener('keydown', this.onKeyDown); } @@ -318,6 +316,7 @@ export default class Controls extends React.Component { toggleSkip={toggleSkip} playButton={this.renderPlayBtn()} controlIcon={this.controlIcon} + ref={this.speedRef} /> )} diff --git a/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx b/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx index be3ac24b3..1361c6c7b 100644 --- a/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx +++ b/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx @@ -1,10 +1,10 @@ -import React from 'react' +import React from 'react'; import { Tooltip } from 'react-tippy'; import { ReduxTime } from '../Time'; import { Icon } from 'UI'; import cn from 'classnames'; // @ts-ignore -import styles from '../controls.module.css' +import styles from '../controls.module.css'; interface Props { live: boolean; @@ -16,22 +16,51 @@ interface Props { forthTenSeconds: () => void; toggleSpeed: () => void; toggleSkip: () => void; - controlIcon: (icon: string, size: number, action: () => void, isBackwards: boolean, additionalClasses: string) => JSX.Element; + controlIcon: ( + icon: string, + size: number, + action: () => void, + isBackwards: boolean, + additionalClasses: string + ) => JSX.Element; } function PlayerControls(props: Props) { - const { - live, - skip, - speed, - disabled, - playButton, - backTenSeconds, - forthTenSeconds, - toggleSpeed, - toggleSkip, - controlIcon + const { + live, + skip, + speed, + disabled, + playButton, + backTenSeconds, + forthTenSeconds, + toggleSpeed, + toggleSkip, + controlIcon, } = props; + + const speedRef = React.useRef(null); + const arrowBackRef = React.useRef(null); + const arrowForwardRef = React.useRef(null); + + React.useEffect(() => { + const handleKeyboard = (e: KeyboardEvent) => { + if (e.key === 'ArrowRight') { + arrowForwardRef.current.focus(); + } + if (e.key === 'ArrowLeft') { + arrowBackRef.current.focus(); + } + if (e.key === 'ArrowDown') { + speedRef.current.focus(); + } + if (e.key === 'ArrowUp') { + speedRef.current.focus(); + } + }; + document.addEventListener('keydown', handleKeyboard); + return () => document.removeEventListener('keydown', handleKeyboard); + }, [speedRef, arrowBackRef, arrowForwardRef]); return (
{playButton} @@ -47,46 +76,41 @@ function PlayerControls(props: Props) {
{/* @ts-ignore */} - - {controlIcon( - "skip-forward-fill", - 18, - backTenSeconds, - true, - 'hover:bg-active-blue-border color-main h-full flex items-center' - )} + + -
10s
+
+ 10s +
{/* @ts-ignore */} - - {controlIcon( - "skip-forward-fill", - 18, - forthTenSeconds, - false, - 'hover:bg-active-blue-border color-main h-full flex items-center' - )} + +
- {!live && -
+ {!live && ( +
{/* @ts-ignore */} - +
- } + )}
- ) + ); } export default PlayerControls; From c8bede6108abcc6f6069fb7866365fbf2d2f922a Mon Sep 17 00:00:00 2001 From: sylenien Date: Tue, 16 Aug 2022 09:58:11 +0200 Subject: [PATCH 21/24] fix(ui): remove logs --- .../components/Assist/components/AssistActions/AssistActions.tsx | 1 - frontend/app/mstore/dashboardStore.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx index 90afa772a..0e24e10f9 100644 --- a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx +++ b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx @@ -91,7 +91,6 @@ function AssistActions({ React.useEffect(() => { if (!onCall && isCallActive && agentIds) { - logger.log('joinig the party', agentIds) setPrestart(true); call(agentIds) } diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 8abef7ea8..617a54fa2 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -195,7 +195,6 @@ export default class DashboardStore implements IDashboardSotre { } updateKey(key: any, value: any) { - console.log(key, value) this[key] = value; } From c05a418a93aeff8e1c94b41c511c8ce82f2b3d77 Mon Sep 17 00:00:00 2001 From: sylenien Date: Tue, 16 Aug 2022 11:25:25 +0200 Subject: [PATCH 22/24] feat(ui): change metric type selector component --- .../components/WidgetForm/WidgetForm.tsx | 24 ++++++++++++++----- .../ui/SegmentSelection/SegmentSelection.js | 3 ++- .../segmentSelection.module.css | 20 +++++++++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx index 40e80a7c9..685da85a5 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx @@ -3,7 +3,7 @@ import { metricTypes, metricOf, issueOptions } from 'App/constants/filterOptions import { FilterKey } from 'Types/filter/filterType'; import { useStore } from 'App/mstore'; import { useObserver } from 'mobx-react-lite'; -import { Button, Icon } from 'UI' +import { Button, Icon, SegmentSelection } from 'UI' import FilterSeries from '../FilterSeries'; import { confirm, Popup } from 'UI'; import Select from 'Shared/Select' @@ -15,6 +15,12 @@ interface Props { onDelete: () => void; } +const metricIcons = { + timeseries: 'graph-up', + table: 'table', + funnel: 'funnel', +} + function WidgetForm(props: Props) { const { history, match: { params: { siteId, dashboardId } } } = props; @@ -64,13 +70,15 @@ function WidgetForm(props: Props) { metricStore.merge(obj); }; + const onSelect = (_: any, option: Record) => writeOption({ value: { value: option.value }, name: option.name}) + const onSave = () => { const wasCreating = !metric.exists() metricStore.save(metric, dashboardId) .then((metric: any) => { if (wasCreating) { if (parseInt(dashboardId) > 0) { - history.replace(withSiteId(dashboardMetricDetails(parseInt(dashboardId), metric.metricId), siteId)); + history.replace(withSiteId(dashboardMetricDetails(dashboardId, metric.metricId), siteId)); } else { history.replace(withSiteId(metricDetails(metric.metricId), siteId)); } @@ -93,11 +101,15 @@ function WidgetForm(props: Props) {
-
No errors found in the selected time range} + title={
No data for the selected time period
} show={!data.errors || data.errors.length === 0} size="small" > diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx index c5aa85e0f..ffb489b11 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx @@ -3,7 +3,7 @@ import React from "react"; import SessionItem from "Shared/SessionItem"; import { Pagination, NoContent } from "UI"; import { useStore } from "App/mstore"; -import { overPastString } from "App/dateRange"; +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; interface Props { metric: any; @@ -26,7 +26,13 @@ function CustomMetricTableSessions(props: Props) { data.sessions.length === 0 } size="small" - title={`No sessions found ${overPastString(period)}`} + title={ +
+ +
+
No relevant sessions found for the selected time period.
+
+ } >
{data.sessions &&