diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 000000000..5a938ce18 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 4, + "useTabs": false +} diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx index 8885edcf6..9e42f9ea6 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors/CustomMetricTableErrors.tsx @@ -1,59 +1,75 @@ -import React, { useEffect } from 'react'; -import { Pagination, NoContent } 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 React, { useEffect } from "react"; +import { Pagination, NoContent } 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, - isEdit: any, - history: any, - location: any, + metric: any; + isEdit: any; + history: any; + location: any; } function CustomMetricTableErrors(props: RouteComponentProps) { const { metric, isEdit = false } = 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(); - props.history.replace({search: (new URLSearchParams({errorId : error.errorId})).toString()}); - } + props.history.replace({ + search: new URLSearchParams({ errorId: error.errorId }).toString(), + }); + }; useEffect(() => { if (!errorId) return; - showModal(, { right: true, onClose: () => { - if (props.history.location.pathname.includes("/dashboard")) { - props.history.replace({search: ""}); - } - }}); + showModal(, { + right: true, + onClose: () => { + if (props.history.location.pathname.includes("/dashboard")) { + props.history.replace({ search: "" }); + } + }, + }); return () => { hideModal(); - } - }, [errorId]) + }; + }, [errorId]); return (
- {metric.data.errors && metric.data.errors.map((error: any, index: any) => ( -
- onErrorClick(e, error)} /> -
- ))} + {metric.data.errors && + metric.data.errors.map((error: any, index: any) => ( +
+ onErrorClick(e, error)} + /> +
+ ))} {isEdit && (
metric.updateKey('page', page)} + totalPages={Math.ceil( + metric.data.total / metric.limit + )} + onPageChange={(page: any) => + metric.updateKey("page", page) + } limit={metric.limit} debounceRequest={500} /> @@ -68,14 +84,17 @@ function CustomMetricTableErrors(props: RouteComponentProps) { ); } -export default withRouter(CustomMetricTableErrors) as React.FunctionComponent>; +export default withRouter(CustomMetricTableErrors) as React.FunctionComponent< + RouteComponentProps +>; -const ViewMore = ({ total, limit }: any) => total > limit && ( -
-
-
- All {total} errors +const ViewMore = ({ total, limit }: any) => + total > limit && ( +
+
+
+ All {total} errors +
-
-); \ No newline at end of file + ); diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx index faf725da6..4ca953dcc 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx @@ -1,7 +1,9 @@ -import { useObserver } from 'mobx-react-lite'; -import React from 'react'; -import SessionItem from 'Shared/SessionItem'; -import { Pagination, NoContent } from 'UI'; +import { useObserver } from "mobx-react-lite"; +import React from "react"; +import SessionItem from "Shared/SessionItem"; +import { Pagination, NoContent } from "UI"; +import { useStore } from "App/mstore"; +import { overPastString } from "App/dateRange"; interface Props { metric: any; @@ -11,26 +13,41 @@ interface Props { function CustomMetricTableSessions(props: Props) { const { isEdit = false, metric } = props; - + const { dashboardStore } = useStore(); + const period = dashboardStore.period; + return useObserver(() => (
- {metric.data.sessions && metric.data.sessions.map((session: any, index: any) => ( -
- -
- ))} - + {metric.data.sessions && + metric.data.sessions.map((session: any, index: any) => ( +
+ +
+ ))} + {isEdit && (
metric.updateKey('page', page)} + totalPages={Math.ceil( + metric.data.total / metric.limit + )} + onPageChange={(page: any) => + metric.updateKey("page", page) + } limit={metric.data.total} debounceRequest={500} /> @@ -47,12 +64,13 @@ function CustomMetricTableSessions(props: Props) { export default CustomMetricTableSessions; -const ViewMore = ({ total, limit }: any) => total > limit && ( -
-
-
- All {total} sessions +const ViewMore = ({ total, limit }: any) => + total > limit && ( +
+
+
+ All {total} sessions +
-
-); \ No newline at end of file + ); diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index 756b7e240..88f859c42 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -1,27 +1,27 @@ -import React, { useEffect } from 'react'; -import { observer } from 'mobx-react-lite'; -import { useStore } from 'App/mstore'; -import { Button, PageTitle, Loader, NoContent } 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 DashboardIcon from '../../../../svg/dashboard-icn.svg'; -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, NoContent } 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 DashboardIcon from "../../../../svg/dashboard-icn.svg"; +import { Tooltip } from "react-tippy"; interface IProps { siteId: string; - dashboardId: any - renderReport?: any + dashboardId: any; + renderReport?: any; } type Props = IProps & RouteComponentProps; @@ -39,76 +39,108 @@ function DashboardView(props: Props) { const dashboard: any = dashboardStore.selectedDashboard; const period = dashboardStore.period; - const queryParams = new URLSearchParams(props.location.search) + const queryParams = new URLSearchParams(props.location.search); useEffect(() => { if (!dashboard || !dashboard.dashboardId) return; - dashboardStore.fetch(dashboard.dashboardId) + dashboardStore.fetch(dashboard.dashboardId); }, [dashboard]); 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 (!dashboardId) dashboardStore.selectDefaultDashboard(); - if (queryParams.has('modal')) { + if (queryParams.has("modal")) { onAddWidgets(); trimQuery(); } }, []); const onAddWidgets = () => { - dashboardStore.initDashboard(dashboard) - showModal(, { right: true }) - } + dashboardStore.initDashboard(dashboard); + showModal( + , + { right: true } + ); + }; const onEdit = (isTitle: boolean) => { - dashboardStore.initDashboard(dashboard) + dashboardStore.initDashboard(dashboard); setFocusedInput(isTitle); - setShowEditModal(true) - } + setShowEditModal(true); + }; const onDelete = async () => { - if (await confirm({ - header: 'Confirm', - confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this Dashboard?` - })) { + if ( + await confirm({ + header: "Confirm", + confirmButton: "Yes, delete", + confirmation: `Are you sure you want to permanently delete this Dashboard?`, + }) + ) { dashboardStore.deleteDashboard(dashboard).then(() => { - dashboardStore.selectDefaultDashboard().then(({ dashboardId }) => { - props.history.push(withSiteId(`/dashboard/${dashboardId}`, siteId)); - }, () => { - props.history.push(withSiteId('/dashboard', siteId)); - }) + dashboardStore.selectDefaultDashboard().then( + ({ dashboardId }) => { + props.history.push( + withSiteId(`/dashboard/${dashboardId}`, siteId) + ); + }, + () => { + props.history.push(withSiteId("/dashboard", siteId)); + } + ); }); } - } + }; return ( - - Gather and analyze
important metrics in one place.
+ + + Gather and analyze
important metrics in one + place. +
} size="small" subtext={ - + } > -
+
setShowEditModal(false)} @@ -118,23 +150,41 @@ function DashboardView(props: Props) {
{dashboard?.name}} + title={ + + {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)} + onChange={(period: any) => + dashboardStore.setPeriod(period) + } right={true} />
@@ -150,7 +200,9 @@ function DashboardView(props: Props) {
-

{dashboard?.description}

+

+ {dashboard?.description} +

dashboardStore.updateKey('showAlertModal', false)} + onClose={() => + dashboardStore.updateKey("showAlertModal", false) + } />
@@ -168,6 +222,6 @@ function DashboardView(props: Props) { ); } -export default withPageTitle('Dashboards - OpenReplay')( +export default withPageTitle("Dashboards - OpenReplay")( withReport(withRouter(withModal(observer(DashboardView)))) ); diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index d93893008..66a4654e3 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -1,21 +1,21 @@ -import React, { useEffect, useState } from 'react'; -import { NoContent, Loader, Pagination } from 'UI'; -import Select from 'Shared/Select'; -import cn from 'classnames'; -import { useStore } from 'App/mstore'; -import SessionItem from 'Shared/SessionItem'; -import { observer, useObserver } from 'mobx-react-lite'; -import { DateTime } from 'luxon'; -import { debounce } from 'App/utils'; -import useIsMounted from 'App/hooks/useIsMounted' -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; +import React, { useEffect, useState } from "react"; +import { NoContent, Loader, Pagination } from "UI"; +import Select from "Shared/Select"; +import cn from "classnames"; +import { useStore } from "App/mstore"; +import SessionItem from "Shared/SessionItem"; +import { observer, useObserver } from "mobx-react-lite"; +import { DateTime } from "luxon"; +import { debounce } from "App/utils"; +import useIsMounted from "App/hooks/useIsMounted"; +import AnimatedSVG, { ICONS } from "Shared/AnimatedSVG/AnimatedSVG"; interface Props { className?: string; } function WidgetSessions(props: Props) { - const { className = '' } = props; - const [activeSeries, setActiveSeries] = useState('all'); + const { className = "" } = props; + const [activeSeries, setActiveSeries] = useState("all"); const [data, setData] = useState([]); const isMounted = useIsMounted(); const [loading, setLoading] = useState(false); @@ -23,15 +23,14 @@ function WidgetSessions(props: Props) { const { dashboardStore, metricStore } = useStore(); const filter = useObserver(() => dashboardStore.drillDownFilter); const widget: any = useObserver(() => metricStore.instance); - // const drillDownPeriod = useObserver(() => dashboardStore.drillDownPeriod); - const startTime = DateTime.fromMillis(filter.startTimestamp).toFormat('LLL dd, yyyy HH:mm'); - const endTime = DateTime.fromMillis(filter.endTimestamp).toFormat('LLL dd, yyyy HH:mm'); - // const [timestamps, setTimestamps] = useState({ - // startTimestamp: 0, - // endTimestamp: 0, - // }); + const startTime = DateTime.fromMillis(filter.startTimestamp).toFormat( + "LLL dd, yyyy HH:mm" + ); + const endTime = DateTime.fromMillis(filter.endTimestamp).toFormat( + "LLL dd, yyyy HH:mm" + ); const [seriesOptions, setSeriesOptions] = useState([ - { label: 'All', value: 'all' }, + { label: "All", value: "all" }, ]); const writeOption = ({ value }: any) => setActiveSeries(value.value); @@ -41,49 +40,68 @@ function WidgetSessions(props: Props) { label: item.seriesName, value: item.seriesId, })); - setSeriesOptions([ - { label: 'All', value: 'all' }, - ...seriesOptions, - ]); + setSeriesOptions([{ label: "All", value: "all" }, ...seriesOptions]); }, [data]); const fetchSessions = (metricId: any, filter: any) => { if (!isMounted()) return; - setLoading(true) - widget.fetchSessions(metricId, filter).then((res: any) => { - setData(res) - }).finally(() => { - setLoading(false) - }); - } - const debounceRequest: any = React.useCallback(debounce(fetchSessions, 1000), []); + setLoading(true); + widget + .fetchSessions(metricId, filter) + .then((res: any) => { + setData(res); + }) + .finally(() => { + setLoading(false); + }); + }; + const debounceRequest: any = React.useCallback( + debounce(fetchSessions, 1000), + [] + ); const depsString = JSON.stringify(widget.series); useEffect(() => { - debounceRequest(widget.metricId, { ...filter, series: widget.toJsonDrilldown(), page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); - }, [filter.startTimestamp, filter.endTimestamp, filter.filters, depsString, metricStore.sessionsPage]); - - // useEffect(() => { - // const timestamps = drillDownPeriod.toTimestamps(); - // // console.log('timestamps', timestamps); - // debounceRequest(widget.metricId, { startTime: timestamps.startTimestamp, endTime: timestamps.endTimestamp, series: widget.toJsonDrilldown(), page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); - // }, [drillDownPeriod]); + debounceRequest(widget.metricId, { + ...filter, + series: widget.toJsonDrilldown(), + page: metricStore.sessionsPage, + limit: metricStore.sessionsPageSize, + }); + }, [ + filter.startTimestamp, + filter.endTimestamp, + filter.filters, + depsString, + metricStore.sessionsPage, + ]); return useObserver(() => (

Sessions

-
between {startTime} and {endTime}
+
+ between{" "} + + {startTime} + {" "} + and{" "} + + {endTime} + {" "} +
- { widget.metricType !== 'table' && ( + {widget.metricType !== "table" && (
- Filter by Series + + Filter by Series +