From e05f14381297face9af24bbe9b912111bf4aa7db Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Fri, 26 Apr 2024 17:37:02 +0200 Subject: [PATCH 01/66] feat ui: dashboards redesign start --- .../DashboardList/DashboardList.tsx | 142 +++++++++++++----- .../DashboardList/DashboardListItem.tsx | 48 ------ .../DashboardList/DashboardSearch.tsx | 21 ++- .../components/DashboardList/Header.tsx | 47 +++--- frontend/app/mstore/types/dashboard.ts | 10 ++ frontend/app/styles/reset.css | 2 +- 6 files changed, 140 insertions(+), 130 deletions(-) delete mode 100644 frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 9651ba90c..e78be299f 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -1,18 +1,75 @@ +import { LockOutlined, TeamOutlined } from '@ant-design/icons'; +import { Switch, Table, TableColumnsType, Tag, Tooltip } from 'antd'; import { observer } from 'mobx-react-lite'; import React from 'react'; -import { NoContent, Pagination } from 'UI'; -import { useStore } from 'App/mstore'; -import { sliceListPerPage } from 'App/utils'; -import DashboardListItem from './DashboardListItem'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; -import { Tooltip } from 'antd'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; -function DashboardList() { +import { checkForRecent } from 'App/date'; +import { useStore } from 'App/mstore'; +import Dashboard from 'App/mstore/types/dashboard'; +import { dashboardSelected, withSiteId } from 'App/routes'; +import { NoContent } from 'UI'; + +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; + +function DashboardList({ history, siteId }: { history: any; siteId: string }) { const { dashboardStore } = useStore(); const list = dashboardStore.filteredList; const dashboardsSearch = dashboardStore.filter.query; const lenth = list.length; + + const tableConfig: TableColumnsType = [ + { + title: 'Title', + dataIndex: 'name', + width: '25%', + render: (t) =>
{t}
, + }, + { + title: 'Description', + ellipsis: { + showTitle: false, + }, + width: '25%', + dataIndex: 'description', + }, + { + title: 'Last Modified', + dataIndex: 'updatedAt', + width: '16.67%', + sorter: (a, b) => a.updatedAt.toMillis() - b.updatedAt.toMillis(), + sortDirections: ['ascend', 'descend'], + render: (date) => checkForRecent(date, 'LLL dd, yyyy, hh:mm a'), + }, + { + title: 'Modified By', + dataIndex: 'updatedBy', + width: '16.67%', + sorter: (a, b) => a.updatedBy.localeCompare(b.updatedBy), + sortDirections: ['ascend', 'descend'], + }, + { + title: ( +
+
Visibility
+ + dashboardStore.updateKey('filter', { + ...dashboardStore.filter, + showMine: !dashboardStore.filter.showMine, + })} checkedChildren={'Public'} unCheckedChildren={'Private'} /> +
+ ), + width: '16.67%', + dataIndex: 'isPublic', + render: (isPublic: boolean) => ( + : }> + {isPublic ? 'Team' : 'Private'} + + ), + }, + ]; return (
- {dashboardsSearch !== '' ? 'No matching results' : "You haven't created any dashboards yet"} + {dashboardsSearch !== '' + ? 'No matching results' + : "You haven't created any dashboards yet"}
} subtext={
- A Dashboard is a collection of Utilize cards to visualize key user interactions or product performance metrics.
} className="text-center">Cards that can be shared across teams. + A Dashboard is a collection of{' '} + + Utilize cards to visualize key user interactions or product + performance metrics. + + } + className="text-center" + > + Cards + {' '} + that can be shared across teams. } > -
-
-
Title
-
Visibility
-
Last Modified
-
- - {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} - /> -
+ + `Showing ${range[0]}-${range[1]} of ${total} items`, + size: 'small', + }} + onRow={(record) => ({ + onClick: () => { + dashboardStore.selectDashboardById(record.dashboardId); + const path = withSiteId( + dashboardSelected(record.dashboardId), + siteId + ); + history.push(path); + }, + })} + /> ); } -export default observer(DashboardList); +export default connect((state: any) => ({ + siteId: state.getIn(['site', 'siteId']), +}))(withRouter(observer(DashboardList))); diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx deleted file mode 100644 index e076dd6d5..000000000 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardListItem.tsx +++ /dev/null @@ -1,48 +0,0 @@ -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 ?
{dashboard.description}
: null} -
- ); -} -// @ts-ignore -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 index d60a6886c..e0ad2048c 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx @@ -1,8 +1,8 @@ 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'; +import { Input } from 'antd'; let debounceUpdate: any = () => {}; @@ -24,16 +24,15 @@ function DashboardSearch() { }; return ( -
- - -
+ dashboardStore.updateKey('filter', { ...dashboardStore.filter, query: value })} + /> ); } diff --git a/frontend/app/components/Dashboard/components/DashboardList/Header.tsx b/frontend/app/components/Dashboard/components/DashboardList/Header.tsx index 9290ff799..ef92298dc 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/Header.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/Header.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import { Button, PageTitle, Toggler, Icon } from 'UI'; -import Select from 'Shared/Select'; +import { PageTitle } from 'UI'; import DashboardSearch from './DashboardSearch'; import { useStore } from 'App/mstore'; import { observer, useObserver } from 'mobx-react-lite'; import { withSiteId } from 'App/routes'; +import { Button } from 'antd' +import { PlusOutlined } from "@ant-design/icons"; function Header({ history, siteId }: { history: any; siteId: string }) { const { dashboardStore } = useStore(); @@ -19,46 +20,32 @@ function Header({ history, siteId }: { history: any; siteId: string }) { }; return ( - <> -
+
-
+ {/* dashboardStore.updateKey('sort', { by: value.value })}*/} + {/*/>*/}
-
- - dashboardStore.updateKey('filter', { - ...dashboardStore.filter, - showMine: !dashboardStore.filter.showMine, - }) - } - /> - setValue(e.target.value)} + className='w-full mb-2' + onKeyDown={(e) => e.key === 'Enter' && onEnter()} + /> +); + +const PredefinedMessage = () => ( +
+ +
Filtering and drill-downs will be supported soon for this card type.
+
+); + +const MetricOptions = ({metric, writeOption}) => { + const isUserPath = metric.metricType === USER_PATH; + + return ( +
+
+ Card showing + + + {isUserPath && ( + <> + + + + )} + {metric.metricOf === FilterKey.ISSUE && metric.metricType === TABLE && ( + <> + issue type + + + )} + {metric.metricType === TABLE && + !(metric.metricOf === FilterKey.ERRORS || metric.metricOf === FilterKey.SESSIONS) && ( + <> + showing + + metricStore.updateKey('filter', {...filter, type: value.value}) + } + plain={true} + isSearchable={true} + /> + + + metricStore.updateKey('filter', {...filter, dashboard: value}) + } + /> +
+ +
+ + + - metricStore.updateKey('filter', { ...filter, type: value.value }) - } - plain={true} - isSearchable={true} - /> - - - metricStore.updateKey('filter', { ...filter, dashboard: value }) - } - /> -
- -
- - - onChange(value)} - isMulti={true} - /> - ); + return ( + (
); -const MetricOptions = ({metric, writeOption}) => { +const MetricTabs = ({metric, writeOption}: any) => { + if (![TABLE].includes(metric.metricType)) return null; + + const onChange = (value: string) => { + console.log('value', value); + writeOption({ + value: { + value + }, name: 'metricOf' + }); + } + + return ( + + ) +} + +const MetricOptions = ({metric, writeOption}: any) => { const isUserPath = metric.metricType === USER_PATH; return ( @@ -198,7 +217,6 @@ interface CardBuilderProps { const CardBuilder = observer((props: CardBuilderProps) => { const history = useHistory(); const {siteId, dashboardId, metricId} = props; - console.log('siteId', siteId); const {metricStore, dashboardStore, aiFiltersStore} = useStore(); const [aiQuery, setAiQuery] = useState(''); const [aiAskChart, setAiAskChart] = useState(''); @@ -209,6 +227,8 @@ const CardBuilder = observer((props: CardBuilderProps) => { const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes(metric.metricType); const testingKey = localStorage.getItem('__mauricio_testing_access') === 'true'; + console.log('metric', metric); + useEffect(() => { if (metric && !initialInstance) setInitialInstance(metric.toJson()); @@ -276,6 +296,8 @@ const CardBuilder = observer((props: CardBuilderProps) => { {/* metric={metric}*/} {/* writeOption={writeOption}*/} {/*/>*/} + {metric.metricType === USER_PATH && } {isPredefined && } {testingKey && ( diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 379ce94cf..691016047 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -359,34 +359,33 @@ export default class DashboardStore { }); } - deleteDashboardWidget(dashboardId: string, widgetId: string) { + async deleteDashboardWidget(dashboardId: string, widgetId: string) { this.isDeleting = true; - return dashboardService - .deleteWidget(dashboardId, widgetId) - .then(() => { - toast.success('Dashboard updated successfully'); - runInAction(() => { - this.selectedDashboard?.removeWidget(widgetId); - }); - }) - .finally(() => { - this.isDeleting = false; + try { + await dashboardService + .deleteWidget(dashboardId, widgetId); + toast.success('Dashboard updated successfully'); + runInAction(() => { + this.selectedDashboard?.removeWidget(widgetId); }); + } finally { + this.isDeleting = false; + } } - addWidgetToDashboard(dashboard: Dashboard, metricIds: any): Promise { + async addWidgetToDashboard(dashboard: Dashboard, metricIds: any): Promise { this.isSaving = true; - return dashboardService - .addWidget(dashboard, metricIds) - .then((response) => { + try { + try { + const response = await dashboardService + .addWidget(dashboard, metricIds); toast.success('Card added to dashboard.'); - }) - .catch(() => { + } catch { toast.error('Card could not be added.'); - }) - .finally(() => { - this.isSaving = false; - }); + } + } finally { + this.isSaving = false; + } } setPeriod(period: any) { From 3bfdc0e5746694a74abd70c1e9b6f556ceb0c2ee Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 25 Jun 2024 16:50:49 +0200 Subject: [PATCH 09/66] change(ui): dashboard redesign --- .../CustomMetricTable/CustomMetricTable.tsx | 78 ++- .../CustomMetricsWidgets/SessionsBy.tsx | 96 +++ .../components/AddCardSelectionModal.tsx | 59 +- .../components/AddToDashboardButton.tsx | 33 + .../Dashboard/components/CreateCardButton.tsx | 31 + .../components/CreateDashboardButton.tsx | 25 + .../DashboardHeader/DashboardHeader.tsx | 28 +- .../DashboardList/DashboardList.tsx | 247 +++---- .../DashboardList/DashboardsView.tsx | 14 +- .../components/DashboardList/Header.tsx | 26 +- .../NewDashModal/CardsLibrary.tsx | 12 +- .../DashboardList/NewDashModal/CreateCard.tsx | 21 +- .../Examples/SessionsBy/Component.tsx | 104 +-- .../NewDashModal/NewDashboardModal.tsx | 2 +- .../DashboardList/NewDashModal/SelectCard.tsx | 16 +- .../DashboardWidgetGrid.tsx | 5 +- .../components/FilterSeries/AddStepButton.tsx | 33 + .../components/FilterSeries/FilterSeries.tsx | 248 ++++--- .../components/WidgetChart/WidgetChart.tsx | 12 +- .../WidgetDateRange/WidgetDateRange.tsx | 25 +- .../components/WidgetForm/WidgetForm.tsx | 661 +++++++++--------- .../components/WidgetForm/WidgetFormNew.tsx | 130 ++++ .../WidgetPreview/WidgetPreview.tsx | 239 +++---- .../components/WidgetView/WidgetView.tsx | 132 ++-- .../WidgetView/WidgetViewHeader.tsx | 46 ++ .../components/WidgetWrapper/AlertButton.tsx | 4 +- .../WidgetWrapper/WidgetWrapperNew.tsx | 181 +++++ .../WidgetWrapper/widgetWrapper.module.css | 3 +- .../components/ui/Icons/color_browser_Tor.tsx | 31 + .../ui/Icons/color_browser_applebot.tsx | 29 + .../color_browser_browser_icons_color_Tor.tsx | 31 + ...r_browser_browser_icons_color_applebot.tsx | 29 + ...lor_browser_browser_icons_color_chrome.tsx | 34 + ...wser_browser_icons_color_chrome_mobile.tsx | 34 + ..._browser_icons_color_chrome_mobile_ios.tsx | 34 + ...owser_browser_icons_color_duck_duck_go.tsx | 59 ++ ..._browser_icons_color_duckduckgo_mobile.tsx | 59 ++ ...color_browser_browser_icons_color_edge.tsx | 47 ++ ...rowser_browser_icons_color_edge_mobile.tsx | 47 ++ ...r_browser_browser_icons_color_facebook.tsx | 28 + ...or_browser_browser_icons_color_firefox.tsx | 124 ++++ ...rowser_browser_icons_color_firefox_ios.tsx | 124 ++++ ...ser_browser_icons_color_firefox_mobile.tsx | 124 ++++ ...lor_browser_browser_icons_color_google.tsx | 24 + ..._browser_browser_icons_color_googlebot.tsx | 24 + ...ser_browser_icons_color_huawei_browser.tsx | 22 + ..._browser_icons_color_internet_explorer.tsx | 21 + ...owser_browser_icons_color_miui_browser.tsx | 28 + ...wser_browser_icons_color_mobile_safari.tsx | 171 +++++ ...r_browser_icons_color_mobile_safari_ui.tsx | 171 +++++ ...olor_browser_browser_icons_color_opera.tsx | 36 + ...lor_browser_browser_icons_color_safari.tsx | 171 +++++ ...r_browser_icons_color_samsung_internet.tsx | 22 + ...browser_browser_icons_color_uc_browser.tsx | 52 ++ ...or_browser_browser_icons_color_unknown.tsx | 23 + ...olor_browser_browser_icons_color_whale.tsx | 43 ++ ...ser_browser_icons_color_yandex_browser.tsx | 22 + .../ui/Icons/color_browser_chrome.tsx | 34 + .../ui/Icons/color_browser_chrome_mobile.tsx | 34 + .../Icons/color_browser_chrome_mobile_ios.tsx | 34 + .../ui/Icons/color_browser_duck_duck_go.tsx | 59 ++ .../Icons/color_browser_duckduckgo_mobile.tsx | 59 ++ .../ui/Icons/color_browser_edge.tsx | 47 ++ .../ui/Icons/color_browser_edge_mobile.tsx | 47 ++ .../ui/Icons/color_browser_facebook.tsx | 28 + .../ui/Icons/color_browser_firefox.tsx | 124 ++++ .../ui/Icons/color_browser_firefox_ios.tsx | 124 ++++ .../ui/Icons/color_browser_firefox_mobile.tsx | 124 ++++ .../ui/Icons/color_browser_google.tsx | 24 + .../ui/Icons/color_browser_googlebot.tsx | 24 + .../ui/Icons/color_browser_huawei_browser.tsx | 22 + .../Icons/color_browser_internet_explorer.tsx | 21 + .../ui/Icons/color_browser_miui_browser.tsx | 28 + .../ui/Icons/color_browser_mobile_safari.tsx | 171 +++++ .../Icons/color_browser_mobile_safari_ui.tsx | 171 +++++ .../ui/Icons/color_browser_opera.tsx | 36 + .../ui/Icons/color_browser_safari.tsx | 171 +++++ .../Icons/color_browser_samsung_internet.tsx | 22 + .../ui/Icons/color_browser_uc_browser.tsx | 52 ++ .../ui/Icons/color_browser_unknown.tsx | 23 + .../ui/Icons/color_browser_whale.tsx | 43 ++ .../ui/Icons/color_browser_yandex_browser.tsx | 22 + .../components/ui/Icons/color_country_de.tsx | 32 + .../components/ui/Icons/color_country_fr.tsx | 32 + .../components/ui/Icons/color_country_gb.tsx | 44 ++ .../components/ui/Icons/color_country_in.tsx | 39 ++ .../components/ui/Icons/color_country_us.tsx | 39 ++ .../ui/Icons/color_device_desktop.tsx | 23 + .../ui/Icons/color_device_mobile.tsx | 35 + .../ui/Icons/color_device_other_phone.tsx | 30 + .../ui/Icons/color_device_tablet.tsx | 23 + .../ui/Icons/color_device_unkown.tsx | 25 + .../components/ui/Icons/color_os_android.tsx | 24 + .../components/ui/Icons/color_os_apple.tsx | 22 + .../ui/Icons/color_os_blackberry.tsx | 28 + .../ui/Icons/color_os_chrome_os.tsx | 34 + .../ui/Icons/color_os_elementary.tsx | 21 + .../components/ui/Icons/color_os_fedora.tsx | 23 + .../components/ui/Icons/color_os_freebsd.tsx | 24 + .../components/ui/Icons/color_os_gnome.tsx | 21 + .../app/components/ui/Icons/color_os_ios.tsx | 24 + .../components/ui/Icons/color_os_linux.tsx | 109 +++ .../ui/Icons/color_os_linux_mint.tsx | 36 + .../components/ui/Icons/color_os_macos.tsx | 30 + .../ui/Icons/color_os_microsoft.tsx | 24 + .../components/ui/Icons/color_os_ubuntu.tsx | 22 + .../components/ui/Icons/color_os_unkown.tsx | 25 + frontend/app/components/ui/Icons/index.ts | 52 ++ frontend/app/components/ui/SVG.tsx | 210 +++++- frontend/app/constants/countries.js | 4 +- frontend/app/mstore/dashboardStore.ts | 19 +- frontend/app/mstore/types/IconProvider.tsx | 115 +++ frontend/app/mstore/types/sessionsCardData.ts | 96 +++ frontend/app/mstore/types/widget.ts | 44 +- frontend/app/svg/ca-no-dashboards.svg | 343 +++++++-- frontend/app/svg/icons/color/browser/Tor.svg | 13 + .../app/svg/icons/color/browser/applebot.svg | 11 + .../app/svg/icons/color/browser/chrome.svg | 16 + .../svg/icons/color/browser/chrome_mobile.svg | 16 + .../icons/color/browser/chrome_mobile_ios.svg | 16 + .../svg/icons/color/browser/duck_duck_go.svg | 41 ++ .../icons/color/browser/duckduckgo_mobile.svg | 41 ++ frontend/app/svg/icons/color/browser/edge.svg | 29 + .../svg/icons/color/browser/edge_mobile.svg | 29 + .../app/svg/icons/color/browser/facebook.svg | 10 + .../app/svg/icons/color/browser/firefox.svg | 106 +++ .../svg/icons/color/browser/firefox_ios.svg | 106 +++ .../icons/color/browser/firefox_mobile.svg | 106 +++ .../app/svg/icons/color/browser/google.svg | 6 + .../app/svg/icons/color/browser/googlebot.svg | 6 + .../icons/color/browser/huawei_browser.svg | 4 + .../icons/color/browser/internet_explorer.svg | 3 + .../svg/icons/color/browser/miui_browser.svg | 10 + .../svg/icons/color/browser/mobile_safari.svg | 153 ++++ .../icons/color/browser/mobile_safari_ui.svg | 153 ++++ .../app/svg/icons/color/browser/opera.svg | 18 + .../app/svg/icons/color/browser/safari.svg | 153 ++++ .../icons/color/browser/samsung_internet.svg | 4 + .../svg/icons/color/browser/uc_browser.svg | 34 + .../app/svg/icons/color/browser/unknown.svg | 5 + .../app/svg/icons/color/browser/whale.svg | 25 + .../icons/color/browser/yandex_browser.svg | 4 + frontend/app/svg/icons/color/country/de.svg | 13 + frontend/app/svg/icons/color/country/fr.svg | 13 + frontend/app/svg/icons/color/country/gb.svg | 25 + frontend/app/svg/icons/color/country/in.svg | 20 + frontend/app/svg/icons/color/country/us.svg | 20 + .../app/svg/icons/color/device/desktop.svg | 5 + .../app/svg/icons/color/device/mobile.svg | 17 + .../svg/icons/color/device/other_phone.svg | 12 + .../app/svg/icons/color/device/tablet.svg | 5 + .../app/svg/icons/color/device/unkown.svg | 7 + frontend/app/svg/icons/color/os/android.svg | 6 + frontend/app/svg/icons/color/os/apple.svg | 4 + .../app/svg/icons/color/os/blackberry.svg | 10 + frontend/app/svg/icons/color/os/chrome_os.svg | 16 + .../app/svg/icons/color/os/elementary.svg | 3 + frontend/app/svg/icons/color/os/fedora.svg | 5 + frontend/app/svg/icons/color/os/freebsd.svg | 6 + frontend/app/svg/icons/color/os/gnome.svg | 3 + frontend/app/svg/icons/color/os/ios.svg | 6 + frontend/app/svg/icons/color/os/linux.svg | 91 +++ .../app/svg/icons/color/os/linux_mint.svg | 18 + frontend/app/svg/icons/color/os/macos.svg | 12 + frontend/app/svg/icons/color/os/microsoft.svg | 6 + frontend/app/svg/icons/color/os/ubuntu.svg | 4 + frontend/app/svg/icons/color/os/unkown.svg | 7 + frontend/app/utils/index.ts | 12 +- frontend/package.json | 6 +- frontend/yarn.lock | 409 +++++++---- 170 files changed, 8082 insertions(+), 1188 deletions(-) create mode 100644 frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx create mode 100644 frontend/app/components/Dashboard/components/AddToDashboardButton.tsx create mode 100644 frontend/app/components/Dashboard/components/CreateCardButton.tsx create mode 100644 frontend/app/components/Dashboard/components/CreateDashboardButton.tsx create mode 100644 frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx create mode 100644 frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx create mode 100644 frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx create mode 100644 frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_Tor.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_applebot.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_Tor.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_applebot.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile_ios.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_duck_duck_go.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_duckduckgo_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_facebook.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_ios.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_google.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_googlebot.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_huawei_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_internet_explorer.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_miui_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari_ui.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_opera.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_safari.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_samsung_internet.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_uc_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_unknown.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_whale.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_browser_icons_color_yandex_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_chrome.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_chrome_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_chrome_mobile_ios.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_duck_duck_go.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_duckduckgo_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_edge.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_edge_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_facebook.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_firefox.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_firefox_ios.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_firefox_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_google.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_googlebot.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_huawei_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_internet_explorer.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_miui_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_mobile_safari.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_mobile_safari_ui.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_opera.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_safari.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_samsung_internet.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_uc_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_unknown.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_whale.tsx create mode 100644 frontend/app/components/ui/Icons/color_browser_yandex_browser.tsx create mode 100644 frontend/app/components/ui/Icons/color_country_de.tsx create mode 100644 frontend/app/components/ui/Icons/color_country_fr.tsx create mode 100644 frontend/app/components/ui/Icons/color_country_gb.tsx create mode 100644 frontend/app/components/ui/Icons/color_country_in.tsx create mode 100644 frontend/app/components/ui/Icons/color_country_us.tsx create mode 100644 frontend/app/components/ui/Icons/color_device_desktop.tsx create mode 100644 frontend/app/components/ui/Icons/color_device_mobile.tsx create mode 100644 frontend/app/components/ui/Icons/color_device_other_phone.tsx create mode 100644 frontend/app/components/ui/Icons/color_device_tablet.tsx create mode 100644 frontend/app/components/ui/Icons/color_device_unkown.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_android.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_apple.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_blackberry.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_chrome_os.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_elementary.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_fedora.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_freebsd.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_gnome.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_ios.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_linux.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_linux_mint.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_macos.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_microsoft.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_ubuntu.tsx create mode 100644 frontend/app/components/ui/Icons/color_os_unkown.tsx create mode 100644 frontend/app/mstore/types/IconProvider.tsx create mode 100644 frontend/app/mstore/types/sessionsCardData.ts create mode 100644 frontend/app/svg/icons/color/browser/Tor.svg create mode 100644 frontend/app/svg/icons/color/browser/applebot.svg create mode 100644 frontend/app/svg/icons/color/browser/chrome.svg create mode 100644 frontend/app/svg/icons/color/browser/chrome_mobile.svg create mode 100644 frontend/app/svg/icons/color/browser/chrome_mobile_ios.svg create mode 100644 frontend/app/svg/icons/color/browser/duck_duck_go.svg create mode 100644 frontend/app/svg/icons/color/browser/duckduckgo_mobile.svg create mode 100644 frontend/app/svg/icons/color/browser/edge.svg create mode 100644 frontend/app/svg/icons/color/browser/edge_mobile.svg create mode 100644 frontend/app/svg/icons/color/browser/facebook.svg create mode 100644 frontend/app/svg/icons/color/browser/firefox.svg create mode 100644 frontend/app/svg/icons/color/browser/firefox_ios.svg create mode 100644 frontend/app/svg/icons/color/browser/firefox_mobile.svg create mode 100644 frontend/app/svg/icons/color/browser/google.svg create mode 100644 frontend/app/svg/icons/color/browser/googlebot.svg create mode 100644 frontend/app/svg/icons/color/browser/huawei_browser.svg create mode 100644 frontend/app/svg/icons/color/browser/internet_explorer.svg create mode 100644 frontend/app/svg/icons/color/browser/miui_browser.svg create mode 100644 frontend/app/svg/icons/color/browser/mobile_safari.svg create mode 100644 frontend/app/svg/icons/color/browser/mobile_safari_ui.svg create mode 100644 frontend/app/svg/icons/color/browser/opera.svg create mode 100644 frontend/app/svg/icons/color/browser/safari.svg create mode 100644 frontend/app/svg/icons/color/browser/samsung_internet.svg create mode 100644 frontend/app/svg/icons/color/browser/uc_browser.svg create mode 100644 frontend/app/svg/icons/color/browser/unknown.svg create mode 100644 frontend/app/svg/icons/color/browser/whale.svg create mode 100644 frontend/app/svg/icons/color/browser/yandex_browser.svg create mode 100644 frontend/app/svg/icons/color/country/de.svg create mode 100644 frontend/app/svg/icons/color/country/fr.svg create mode 100644 frontend/app/svg/icons/color/country/gb.svg create mode 100644 frontend/app/svg/icons/color/country/in.svg create mode 100644 frontend/app/svg/icons/color/country/us.svg create mode 100644 frontend/app/svg/icons/color/device/desktop.svg create mode 100644 frontend/app/svg/icons/color/device/mobile.svg create mode 100644 frontend/app/svg/icons/color/device/other_phone.svg create mode 100644 frontend/app/svg/icons/color/device/tablet.svg create mode 100644 frontend/app/svg/icons/color/device/unkown.svg create mode 100644 frontend/app/svg/icons/color/os/android.svg create mode 100644 frontend/app/svg/icons/color/os/apple.svg create mode 100644 frontend/app/svg/icons/color/os/blackberry.svg create mode 100644 frontend/app/svg/icons/color/os/chrome_os.svg create mode 100644 frontend/app/svg/icons/color/os/elementary.svg create mode 100644 frontend/app/svg/icons/color/os/fedora.svg create mode 100644 frontend/app/svg/icons/color/os/freebsd.svg create mode 100644 frontend/app/svg/icons/color/os/gnome.svg create mode 100644 frontend/app/svg/icons/color/os/ios.svg create mode 100644 frontend/app/svg/icons/color/os/linux.svg create mode 100644 frontend/app/svg/icons/color/os/linux_mint.svg create mode 100644 frontend/app/svg/icons/color/os/macos.svg create mode 100644 frontend/app/svg/icons/color/os/microsoft.svg create mode 100644 frontend/app/svg/icons/color/os/ubuntu.svg create mode 100644 frontend/app/svg/icons/color/os/unkown.svg diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx index 51c5e0ce3..9dea09596 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx @@ -1,24 +1,25 @@ import React from 'react' -import { Table } from '../../common'; -import { List } from 'immutable'; -import { filtersMap } from 'Types/filter/newFilter'; -import { NoContent, Icon } from 'UI'; -import { tableColumnName } from 'App/constants/filterOptions'; -import { numberWithCommas } from 'App/utils'; +import {Table} from '../../common'; +import {List} from 'immutable'; +import {filtersMap} from 'Types/filter/newFilter'; +import {NoContent, Icon} from 'UI'; +import {tableColumnName} from 'App/constants/filterOptions'; +import {numberWithCommas} from 'App/utils'; const getColumns = (metric) => { return [ { - key: 'name', - title: tableColumnName[metric.metricOf], - toText: name => name || 'Unidentified', - width: '70%', + key: 'name', + title: tableColumnName[metric.metricOf], + toText: name => name || 'Unidentified', + width: '70%', + icon: true, }, { - key: 'sessionCount', - title: 'Sessions', - toText: sessions => numberWithCommas(sessions), - width: '30%', + key: 'sessionCount', + title: 'Sessions', + toText: sessions => numberWithCommas(sessions), + width: '30%', }, ] } @@ -29,13 +30,14 @@ interface Props { onClick?: (filters: any) => void; isTemplate?: boolean; } + function CustomMetricTable(props: Props) { - const { metric = {}, data = { values: [] }, onClick = () => null, isTemplate } = props; + const {metric = {}, data = {values: []}, onClick = () => null, isTemplate} = props; const rows = List(data.values); const onClickHandler = (event: any, data: any) => { const filters = Array(); - let filter = { ...filtersMap[metric.metricOf] } + let filter = {...filtersMap[metric.metricOf]} filter.value = [data.name] filter.type = filter.key delete filter.key @@ -49,28 +51,28 @@ function CustomMetricTable(props: Props) { onClick(filters); } return ( -
- - - No data for the selected time period -
- } - > -
- - +
+ + + No data for the selected time period +
+ } + > +
+ + ); } diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx new file mode 100644 index 000000000..10fa154bd --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import {List, Typography} from 'antd'; +import {filtersMap} from 'Types/filter/newFilter'; +import {Icon} from 'UI'; +import {Progress, Empty} from 'antd'; +import cn from "classnames"; + +interface Props { + metric?: any; + data: any; + onClick?: (filters: any) => void; + isTemplate?: boolean; +} + +function SessionsBy(props: Props) { + const {metric = {}, data = {values: []}, onClick = () => null, isTemplate} = props; + const [selected, setSelected] = React.useState(null); + + const onClickHandler = (event: any, data: any) => { + const filters = Array(); + let filter = {...filtersMap[metric.metricOf]}; + filter.value = [data.name]; + filter.type = filter.key; + delete filter.key; + delete filter.operatorOptions; + delete filter.category; + delete filter.icon; + delete filter.label; + delete filter.options; + + setSelected(data.name) + + filters.push(filter); + onClick(filters); + } + + return ( +
+ {data.values && data.values.length === 0 ? ( + + + No data for the selected time period +
+ } + /> + ) : ( + ( + onClickHandler(e, row)} + // actions={[row.sessionCount]} + style={{borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', padding: '6px 0'}} + className={cn('hover:bg-active-blue cursor-pointer', selected === row.name ? 'bg-gray-100' : '')} + > + + {row.name} + {row.sessionCount} + + )} + description={ + + } + /> + {/*
{row.value}
*/} +
+ )} + /> + )} + + ); +} + +export default SessionsBy; diff --git a/frontend/app/components/Dashboard/components/AddCardSelectionModal.tsx b/frontend/app/components/Dashboard/components/AddCardSelectionModal.tsx index e9bb29a64..f427082fa 100644 --- a/frontend/app/components/Dashboard/components/AddCardSelectionModal.tsx +++ b/frontend/app/components/Dashboard/components/AddCardSelectionModal.tsx @@ -14,7 +14,7 @@ function AddCardSelectionModal(props: Props) { const onCloseModal = () => { setOpen(false); - // props.onClose && props.onClose(); + props.onClose && props.onClose(); } const onClick = (isLibrary: boolean) => { @@ -22,34 +22,35 @@ function AddCardSelectionModal(props: Props) { setOpen(true); } return ( - - -
- onClick(true)}> -
- - Add from library -

Select from 12 available

-
-
- - - onClick(false)}> -
- -

Create New Card

-
-
- - - - {open && } - + <> + + + + onClick(true)}> +
+ + Add from library +

Select from 12 available

+
+
+ + + onClick(false)}> +
+ +

Create New Card

+
+
+ + + + + ); } diff --git a/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx b/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx new file mode 100644 index 000000000..84f9f7fa3 --- /dev/null +++ b/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import DashboardSelectionModal from "Components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal"; +import {Grid2x2Check} from "lucide-react" +import {Button} from "antd"; + +interface Props { + metricId: string; +} + +function AddToDashboardButton({metricId}: Props) { + const [show, setShow] = React.useState(false); + return ( + <> + + {show && ( + setShow(false)} + /> + )} + + ); +} + +export default AddToDashboardButton; diff --git a/frontend/app/components/Dashboard/components/CreateCardButton.tsx b/frontend/app/components/Dashboard/components/CreateCardButton.tsx new file mode 100644 index 000000000..665191956 --- /dev/null +++ b/frontend/app/components/Dashboard/components/CreateCardButton.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import {Button, Tooltip} from "UI"; +import AddCardSelectionModal from "Components/Dashboard/components/AddCardSelectionModal"; +import {useStore} from "App/mstore"; + +const MAX_CARDS = 29; + +function CreateCardButton() { + const [open, setOpen] = React.useState(false); + const {dashboardStore} = useStore(); + const dashboard: any = dashboardStore.selectedDashboard; + const canAddMore: boolean = dashboard?.widgets?.length <= MAX_CARDS; + + return <> + + + + setOpen(false)}/> + ; +} + +export default CreateCardButton; diff --git a/frontend/app/components/Dashboard/components/CreateDashboardButton.tsx b/frontend/app/components/Dashboard/components/CreateDashboardButton.tsx new file mode 100644 index 000000000..d5731517d --- /dev/null +++ b/frontend/app/components/Dashboard/components/CreateDashboardButton.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import {PlusOutlined} from "@ant-design/icons"; +import NewDashboardModal from "Components/Dashboard/components/DashboardList/NewDashModal"; +import {Button} from "antd"; + +interface Props { + disabled?: boolean; +} + +function CreateDashboardButton({disabled = false}: Props) { + const [showModal, setShowModal] = React.useState(false); + + return <> + + setShowModal(false)} open={showModal}/> + ; +} + +export default CreateDashboardButton; diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 29950a0cd..174a97fba 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -10,8 +10,9 @@ import DashboardOptions from '../DashboardOptions'; import withModal from 'App/components/Modal/withModal'; import {observer} from 'mobx-react-lite'; import DashboardEditModal from '../DashboardEditModal'; -import AddCardModal from '../AddCardModal'; -import AddCardSelectionModal from "Components/Dashboard/components/AddCardSelectionModal"; +import CreateDashboardButton from "Components/Dashboard/components/CreateDashboardButton"; +import CreateCard from "Components/Dashboard/components/DashboardList/NewDashModal/CreateCard"; +import CreateCardButton from "Components/Dashboard/components/CreateCardButton"; interface IProps { dashboardId: string; @@ -22,27 +23,6 @@ interface IProps { type Props = IProps & RouteComponentProps; const MAX_CARDS = 29; -function AddCard(props: { disabled: boolean }) { - const [open, setOpen] = React.useState(false); - - // showModal(, {right: true}) - return <> - - - - setOpen(false)}/> - ; -} - function DashboardHeader(props: Props) { const {siteId, dashboardId} = props; const {dashboardStore} = useStore(); @@ -103,7 +83,7 @@ function DashboardHeader(props: Props) { />
- +
= [ - { - title: 'Title', - dataIndex: 'name', - width: '25%', - render: (t) =>
{t}
, - }, - { - title: 'Description', - ellipsis: { - showTitle: false, - }, - width: '25%', - dataIndex: 'description', - }, - { - title: 'Last Modified', - dataIndex: 'updatedAt', - width: '16.67%', - sorter: (a, b) => a.updatedAt.toMillis() - b.updatedAt.toMillis(), - sortDirections: ['ascend', 'descend'], - render: (date) => checkForRecent(date, 'LLL dd, yyyy, hh:mm a'), - }, - { - title: 'Modified By', - dataIndex: 'updatedBy', - width: '16.67%', - sorter: (a, b) => a.updatedBy.localeCompare(b.updatedBy), - sortDirections: ['ascend', 'descend'], - }, - { - title: ( -
-
Visibility
- - dashboardStore.updateKey('filter', { - ...dashboardStore.filter, - showMine: !dashboardStore.filter.showMine, - })} checkedChildren={'Public'} unCheckedChildren={'Private'} /> -
- ), - width: '16.67%', - dataIndex: 'isPublic', - render: (isPublic: boolean) => ( - : }> - {isPublic ? 'Team' : 'Private'} - - ), - }, - ]; - return ( - - -
- {dashboardsSearch !== '' - ? 'No matching results' - : "You haven't created any dashboards yet"} -
-
- } - subtext={ -
- A Dashboard is a collection of{' '} - - Utilize cards to visualize key user interactions or product - performance metrics. -
- } - className="text-center" - > - Cards - {' '} - that can be shared across teams. -
- } - > -
- `Showing ${range[0]}-${range[1]} of ${total} items`, - size: 'small', - }} - onRow={(record) => ({ - onClick: () => { - dashboardStore.selectDashboardById(record.dashboardId); - const path = withSiteId( - dashboardSelected(record.dashboardId), - siteId - ); - history.push(path); - }, - })} - /> - - ); + const tableConfig: TableColumnsType = [ + { + title: 'Title', + dataIndex: 'name', + width: '25%', + render: (t) =>
{t}
, + }, + { + title: 'Description', + ellipsis: { + showTitle: false, + }, + width: '25%', + dataIndex: 'description', + }, + { + title: 'Last Modified', + dataIndex: 'updatedAt', + width: '16.67%', + sorter: (a, b) => a.updatedAt.toMillis() - b.updatedAt.toMillis(), + sortDirections: ['ascend', 'descend'], + render: (date) => checkForRecent(date, 'LLL dd, yyyy, hh:mm a'), + }, + { + title: 'Modified By', + dataIndex: 'updatedBy', + width: '16.67%', + sorter: (a, b) => a.updatedBy.localeCompare(b.updatedBy), + sortDirections: ['ascend', 'descend'], + }, + { + title: ( +
+
Visibility
+ + dashboardStore.updateKey('filter', { + ...dashboardStore.filter, + showMine: !dashboardStore.filter.showMine, + })} checkedChildren={'Public'} unCheckedChildren={'Private'}/> +
+ ), + width: '16.67%', + dataIndex: 'isPublic', + render: (isPublic: boolean) => ( + : }> + {isPublic ? 'Team' : 'Private'} + + ), + }, + ]; + return ( + list.length === 0 && !dashboardStore.filter.showMine ? ( + } + imageStyle={{height: 300}} + description={( +
+ {dashboardsSearch !== '' + ? + No matching results + + : ( +
+ + You haven't created any dashboards yet + +
+ A Dashboard is a collection of{' '} + + Utilize cards to visualize key user interactions or product + performance metrics. +
+ } + className="text-center" + > + Cards + {' '} + that can be shared across teams. +
+ +
+ +
+
+ )} + + )} + /> + ) : ( +
+ `Showing ${range[0]}-${range[1]} of ${total} items`, + size: 'small', + }} + onRow={(record) => ({ + onClick: () => { + dashboardStore.selectDashboardById(record.dashboardId); + const path = withSiteId( + dashboardSelected(record.dashboardId), + siteId + ); + history.push(path); + }, + })} + />) + ); } export default connect((state: any) => ({ - siteId: state.getIn(['site', 'siteId']), -}))(withRouter(observer(DashboardList))); + siteId: state.getIn(['site', 'siteId']), +}))(observer(DashboardList)); diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx index 1c5f1ae46..bb3a152b9 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -3,13 +3,13 @@ import withPageTitle from 'HOCs/withPageTitle'; import DashboardList from './DashboardList'; import Header from './Header'; -function DashboardsView({ history, siteId }: { history: any; siteId: string }) { - return ( -
-
- -
- ); +function DashboardsView({history, siteId}: { history: any; siteId: string }) { + return ( +
+
+ +
+ ); } export default withPageTitle('Dashboards - OpenReplay')(DashboardsView); diff --git a/frontend/app/components/Dashboard/components/DashboardList/Header.tsx b/frontend/app/components/Dashboard/components/DashboardList/Header.tsx index 5b0062ea4..8eb74ae6d 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/Header.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/Header.tsx @@ -1,24 +1,11 @@ -import {PlusOutlined} from '@ant-design/icons'; -import {Button} from 'antd'; -import {observer} from 'mobx-react-lite'; import React from 'react'; import {PageTitle} from 'UI'; import DashboardSearch from './DashboardSearch'; -import NewDashboardModal from './NewDashModal'; +import CreateDashboardButton from "Components/Dashboard/components/CreateDashboardButton"; function Header() { - const [showModal, setShowModal] = React.useState(true); - - const onAddDashboardClick = () => { - setShowModal(true); - }; - - const onClose = () => { - setShowModal(false); - }; - return ( <>
@@ -26,22 +13,15 @@ function Header() {
- +
- ); } -export default observer(Header); +export default Header; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx index 3465b71e6..9d2fc28e3 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx @@ -23,11 +23,11 @@ function CardsLibrary(props: Props) { const {selectedList} = props; const {metricStore, dashboardStore} = useStore(); - const cards = useMemo(() => { - return metricStore.filteredCards.filter((card: any) => { - return CARD_TYPES_MAP[props.category || 'default'].includes(card.metricType); - }); - }, [metricStore.filteredCards, props.category]); + // const cards = useMemo(() => { + // return metricStore.filteredCards.filter((card: any) => { + // return CARD_TYPES_MAP[props.category || 'default'].includes(card.metricType); + // }); + // }, [metricStore.filteredCards, props.category]); useEffect(() => { metricStore.fetchList(); @@ -40,7 +40,7 @@ function CardsLibrary(props: Props) { return (
- {cards.map((metric: any) => ( + {metricStore.filteredCards.map((metric: any) => (
onItemClick(metric.metricId)}> diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx index 7ca9a826f..df4d8a3fb 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx @@ -7,7 +7,6 @@ import {useStore} from "App/mstore"; import {CLICKMAP} from "App/constants/card"; import {renderClickmapThumbnail} from "Components/Dashboard/components/WidgetForm/renderMap"; import WidgetPreview from "Components/Dashboard/components/WidgetPreview/WidgetPreview"; -import {number} from "Player/player/localStorage"; const getTitleByType = (type: string) => { switch (type) { @@ -28,7 +27,8 @@ function CreateCard(props: Props) { const {metricStore, dashboardStore, aiFiltersStore} = useStore(); const metric = metricStore.instance; const siteId: string = history.location.pathname.split('/')[1]; - const dashboardId: string = history.location.pathname.split('/')[4]; + const dashboardId: string = history.location.pathname.split('/')[3]; + const isItDashboard = history.location.pathname.includes('dashboard') // const title = getTitleByType(metric.metricType) const createNewDashboard = async () => { @@ -48,8 +48,8 @@ function CreateCard(props: Props) { } const createCard = async () => { - const isClickmap = metric.metricType === CLICKMAP; - if (isClickmap) { + const isClickMap = metric.metricType === CLICKMAP; + if (isClickMap) { try { metric.thumbnail = await renderClickmapThumbnail(); } catch (e) { @@ -62,11 +62,18 @@ function CreateCard(props: Props) { } const createDashboardAndAddCard = async () => { - const dashboardId = await createNewDashboard(); const cardId = await createCard(); - await addCardToDashboard(dashboardId, cardId); - history.replace(`${history.location.pathname}/${dashboardId}`); + if (dashboardId) { + await addCardToDashboard(dashboardId, cardId); + dashboardStore.fetch(dashboardId); + } else if (isItDashboard) { + const dashboardId = await createNewDashboard(); + await addCardToDashboard(dashboardId, cardId); + history.replace(`${history.location.pathname}/${dashboardId}`); + } else { + history.replace(`${history.location.pathname}/${cardId}`); + } } return ( diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx index 45783145d..eda89c46f 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx @@ -1,59 +1,59 @@ import ExCard from '../ExCard' import React from 'react' -function ByComponent({ title, rows, lineWidth, onCard, type }: { - title: string - rows: { - label: string - progress: number - value: string - icon: React.ReactNode - }[] - onCard: (card: string) => void - type: string - lineWidth: number +function ByComponent({title, rows, lineWidth, onCard, type}: { + title: string + rows: { + label: string + progress: number + value: string + icon: React.ReactNode + }[] + onCard: (card: string) => void + type: string + lineWidth: number }) { - return ( - -
- {rows.map((r) => ( -
-
{r.icon}
-
{r.label}
-
-
-
+ return ( + +
+ {rows.map((r) => ( +
+
{r.icon}
+
{r.label}
+
+
+
+
+
{r.value}
+
+ ))}
-
{r.value}
-
- ))} -
-
- ) + + ) } -export default ByComponent \ No newline at end of file +export default ByComponent diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx index 9c0eaad8f..bf9830f52 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx @@ -34,7 +34,7 @@ const NewDashboardModal: React.FC = ({
{step === 0 && } - {step === 1 && setStep(0)}/>} + {step === 1 && setStep(0)} />}
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx index 9c21a58ed..f558a8bb8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx @@ -6,16 +6,17 @@ import Option from './Option'; import CardsLibrary from "Components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary"; interface SelectCardProps { - onClose: () => void; + onClose: (refresh?: boolean) => void; onCard: () => void; isLibrary?: boolean; } -const SelectCard: React.FC = ({onCard, isLibrary = false}) => { +const SelectCard: React.FC = (props: SelectCardProps) => { + const {onCard, isLibrary = false} = props; const [selected, setSelected] = React.useState('product-analytics'); const [selectedCards, setSelectedCards] = React.useState([]); const {metricStore, dashboardStore} = useStore(); - const dashboardId = window.location.pathname.split('/')[4]; + const dashboardId = window.location.pathname.split('/')[3]; const handleCardSelection = (card: string) => { @@ -45,14 +46,17 @@ const SelectCard: React.FC = ({onCard, isLibrary = false}) => { } const onAddSelected = () => { - console.log(selectedCards); - dashboardStore.addWidgetToDashboard(dashboardId, selectedCards); + const dashboard = dashboardStore.getDashboard(dashboardId); + dashboardStore.addWidgetToDashboard(dashboard!, selectedCards).finally(() => { + dashboardStore.fetch(dashboardId); + props.onClose(true); + }); } return ( <>
- + {!isLibrary && } {isLibrary ? : } diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index f8a3bdd32..4f26f2d32 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -5,6 +5,7 @@ import { NoContent, Loader, Icon } from 'UI'; import { useObserver } from 'mobx-react-lite'; import Widget from 'App/mstore/types/widget'; import MetricTypeList from '../MetricTypeList'; +import WidgetWrapperNew from "Components/Dashboard/components/WidgetWrapper/WidgetWrapperNew"; interface Props { siteId: string; @@ -63,7 +64,7 @@ function DashboardWidgetGrid(props: Props) { {smallWidgets && smallWidgets.map((item: any, index: any) => ( - @@ -90,7 +91,7 @@ function DashboardWidgetGrid(props: Props) { {regularWidgets && regularWidgets.map((item: any, index: any) => ( - diff --git a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx new file mode 100644 index 000000000..7879ff095 --- /dev/null +++ b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import FilterSelection from "Shared/Filters/FilterSelection/FilterSelection"; +import {PlusIcon} from "lucide-react"; +import {Button} from "antd"; +import {useStore} from "App/mstore"; + +interface Props { + series: any; + excludeFilterKeys: Array; +} + +function AddStepButton({series, excludeFilterKeys}: Props) { + const {metricStore} = useStore(); + const metric: any = metricStore.instance; + + const onAddFilter = (filter: any) => { + series.filter.addFilter(filter); + metric.updateKey('hasChanged', true) + } + return ( + + + + ); +} + +export default AddStepButton; diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 14af62f56..7861fa2ad 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -1,119 +1,155 @@ -import React, { useState } from 'react'; +import React, {useState} from 'react'; import FilterList from 'Shared/Filters/FilterList'; -import { Button, Icon } from 'UI'; -import FilterSelection from 'Shared/Filters/FilterSelection'; +import {Icon} from 'UI'; import SeriesName from './SeriesName'; import cn from 'classnames'; -import { observer } from 'mobx-react-lite'; +import {observer} from 'mobx-react-lite'; import ExcludeFilters from './ExcludeFilters'; +import AddStepButton from "Components/Dashboard/components/FilterSeries/AddStepButton"; +import {Button, Space} from "antd"; +import {ChevronDown, ChevronUp, Trash} from "lucide-react"; interface Props { - seriesIndex: number; - series: any; - onRemoveSeries: (seriesIndex: any) => void; - canDelete?: boolean; - supportsEmpty?: boolean; - hideHeader?: boolean; - emptyMessage?: any; - observeChanges?: () => void; - excludeFilterKeys?: Array; - canExclude?: boolean; + seriesIndex: number; + series: any; + onRemoveSeries: (seriesIndex: any) => void; + canDelete?: boolean; + supportsEmpty?: boolean; + hideHeader?: boolean; + emptyMessage?: any; + observeChanges?: () => void; + excludeFilterKeys?: Array; + canExclude?: boolean; } -function FilterSeries(props: Props) { - const { - observeChanges = () => {}, - canDelete, - hideHeader = false, - emptyMessage = 'Add user event or filter to define the series by clicking Add Step.', - supportsEmpty = true, - excludeFilterKeys = [], - canExclude = false, - } = props; - const [expanded, setExpanded] = useState(true); - const { series, seriesIndex } = props; +const FilterSeriesHeader = observer((props: { + expanded: boolean, + hidden: boolean, + seriesIndex: number, + series: any, + onRemove: (seriesIndex: any) => void, + canDelete: boolean | undefined, + toggleExpand: () => void +}) => { + const events = props.series.filter.filters.filter((i: any) => i && i.isEvent).length; + const filters = props.series.filter.filters.filter((i: any) => i && !i.isEvent).length; + const onUpdate = (name: any) => { + props.series.update('name', name) + } + return
+ + + {!props.expanded && ( + + {events > 0 && ( + + )} - const onAddFilter = (filter: any) => { - series.filter.addFilter(filter); - observeChanges(); - }; - - const onUpdateFilter = (filterIndex: any, filter: any) => { - series.filter.updateFilter(filterIndex, filter); - observeChanges(); - }; - - const onFilterMove = (newFilters: any) => { - series.filter.replaceFilters(newFilters.toArray()) - observeChanges(); - } - - const onChangeEventsOrder = (_: any, { name, value }: any) => { - series.filter.updateKey(name, value); - observeChanges(); - }; - - const onRemoveFilter = (filterIndex: any) => { - series.filter.removeFilter(filterIndex); - observeChanges(); - }; - - return ( -
- {canExclude && } -
-
- series.update('name', name)} - /> -
- -
-
- -
- -
setExpanded(!expanded)} className="ml-3"> - -
-
-
- {expanded && ( - <> -
- {series.filter.filters.length > 0 ? ( - - ) : ( -
{emptyMessage}
+ {filters > 0 && ( + + )} + )} -
-
-
- - - -
-
- - )} -
- ); + + {/*{events === 0 && filters === 0 && !props.expanded && (*/} + {/* */} + {/*)}*/} +
+ + +
; +}) + +function FilterSeries(props: Props) { + const { + observeChanges = () => { + }, + canDelete, + hideHeader = false, + emptyMessage = 'Add user event or filter to define the series by clicking Add Step.', + supportsEmpty = true, + excludeFilterKeys = [], + canExclude = false, + } = props; + const [expanded, setExpanded] = useState(true); + const {series, seriesIndex} = props; + + const onUpdateFilter = (filterIndex: any, filter: any) => { + series.filter.updateFilter(filterIndex, filter); + observeChanges(); + }; + + const onFilterMove = (newFilters: any) => { + series.filter.replaceFilters(newFilters.toArray()) + observeChanges(); + } + + const onChangeEventsOrder = (_: any, {name, value}: any) => { + series.filter.updateKey(name, value); + observeChanges(); + }; + + const onRemoveFilter = (filterIndex: any) => { + series.filter.removeFilter(filterIndex); + observeChanges(); + }; + + return ( +
+ {canExclude && } + + {!hideHeader && ( +
+ ); } export default observer(FilterSeries); diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 2416152dc..15376eb1c 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -33,6 +33,7 @@ import ClickMapCard from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/ import InsightsCard from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/InsightsCard'; import SankeyChart from 'Shared/Insights/SankeyChart'; import CohortCard from '../../Widgets/CustomMetricsWidgets/CohortCard'; +import SessionsBy from "Components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy"; interface Props { metric: any; @@ -96,6 +97,7 @@ function WidgetChart(props: Props) { if (!isMounted()) return; setLoading(true); dashboardStore.fetchMetricChartData(metric, payload, isWidget, period).then((res: any) => { + console.log('res', res) if (isMounted()) setData(res); }).finally(() => { setLoading(false); @@ -181,11 +183,17 @@ function WidgetChart(props: Props) { } if (viewType === TABLE) { return ( - + // ); } else if (viewType === 'pieChart') { return ( diff --git a/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx b/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx index 3034aecba..2527b1f34 100644 --- a/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx +++ b/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx @@ -1,13 +1,13 @@ import React from 'react'; import SelectDateRange from 'Shared/SelectDateRange'; -import { useStore } from 'App/mstore'; -import { useObserver } from 'mobx-react-lite'; +import {useStore} from 'App/mstore'; +import {useObserver} from 'mobx-react-lite'; +import {Space} from "antd"; -interface Props { - -} -function WidgetDateRange(props: Props) { - const { dashboardStore } = useStore(); +function WidgetDateRange({ + label = 'Time Range', + }: any) { + const {dashboardStore} = useStore(); const period = useObserver(() => dashboardStore.drillDownPeriod); const drillDownFilter = useObserver(() => dashboardStore.drillDownFilter); @@ -21,16 +21,15 @@ function WidgetDateRange(props: Props) { } return ( - <> - Time Range + + {label && {label}} metric.setPeriod(period)} onChange={onChangePeriod} right={true} - /> - + /> + ); } -export default WidgetDateRange; \ No newline at end of file +export default WidgetDateRange; diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx index b4aed6460..f85f0cce1 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx @@ -1,362 +1,367 @@ -import React, { useEffect, useState } from 'react'; -import { metricOf, issueOptions, issueCategories } from 'App/constants/filterOptions'; -import { FilterKey } from 'Types/filter/filterType'; -import { useStore } from 'App/mstore'; -import { observer } from 'mobx-react-lite'; -import { Button, Icon, confirm, Tooltip } from 'UI'; +import React, {useEffect, useState} from 'react'; +import {metricOf, issueOptions, issueCategories} from 'App/constants/filterOptions'; +import {FilterKey} from 'Types/filter/filterType'; +import {useStore} from 'App/mstore'; +import {observer} from 'mobx-react-lite'; +import {Button, Icon, confirm, Tooltip} from 'UI'; import FilterSeries from '../FilterSeries'; import Select from 'Shared/Select'; -import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes'; +import {withSiteId, dashboardMetricDetails, metricDetails} from 'App/routes'; import MetricTypeDropdown from './components/MetricTypeDropdown'; import MetricSubtypeDropdown from './components/MetricSubtypeDropdown'; import { - TIMESERIES, - TABLE, - CLICKMAP, - FUNNEL, - ERRORS, - RESOURCE_MONITORING, - PERFORMANCE, - WEB_VITALS, - INSIGHTS, - USER_PATH, - RETENTION + TIMESERIES, + TABLE, + CLICKMAP, + FUNNEL, + ERRORS, + RESOURCE_MONITORING, + PERFORMANCE, + WEB_VITALS, + INSIGHTS, + USER_PATH, + RETENTION } from 'App/constants/card'; -import { eventKeys } from 'App/types/filter/newFilter'; -import { renderClickmapThumbnail } from './renderMap'; +import {eventKeys} from 'App/types/filter/newFilter'; +import {renderClickmapThumbnail} from './renderMap'; import Widget from 'App/mstore/types/widget'; import FilterItem from 'Shared/Filters/FilterItem'; -import { Input } from 'antd' +import {Input} from 'antd' interface Props { - history: any; - match: any; - onDelete: () => void; + history: any; + match: any; + onDelete: () => void; + expanded?: boolean; } function WidgetForm(props: Props) { - const { - history, - match: { - params: { siteId, dashboardId } - } - } = props; - const [aiQuery, setAiQuery] = useState('') - const [aiAskChart, setAiAskChart] = useState('') - const { metricStore, dashboardStore, aiFiltersStore } = useStore(); - const isSaving = metricStore.isSaving; - const metric: any = metricStore.instance; - const [initialInstance, setInitialInstance] = useState(); + const { + history, + match: { + params: {siteId, dashboardId} + } + } = props; + const [aiQuery, setAiQuery] = useState('') + const [aiAskChart, setAiAskChart] = useState('') + const {metricStore, dashboardStore, aiFiltersStore} = useStore(); + const isSaving = metricStore.isSaving; + const metric: any = metricStore.instance; + const [initialInstance, setInitialInstance] = useState(); - const timeseriesOptions = metricOf.filter((i) => i.type === 'timeseries'); - const tableOptions = metricOf.filter((i) => i.type === 'table'); - const isTable = metric.metricType === TABLE; - const isClickmap = metric.metricType === CLICKMAP; - const isFunnel = metric.metricType === FUNNEL; - const isInsights = metric.metricType === INSIGHTS; - const isPathAnalysis = metric.metricType === USER_PATH; - const isRetention = metric.metricType === RETENTION; - const canAddSeries = metric.series.length < 3; - const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; - const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1); + const timeseriesOptions = metricOf.filter((i) => i.type === 'timeseries'); + const tableOptions = metricOf.filter((i) => i.type === 'table'); + const isTable = metric.metricType === TABLE; + const isClickmap = metric.metricType === CLICKMAP; + const isFunnel = metric.metricType === FUNNEL; + const isInsights = metric.metricType === INSIGHTS; + const isPathAnalysis = metric.metricType === USER_PATH; + const isRetention = metric.metricType === RETENTION; + const canAddSeries = metric.series.length < 3; + const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; + const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1); - const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes( - metric.metricType - ); + const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes( + metric.metricType + ); - const excludeFilterKeys = isClickmap || isPathAnalysis ? eventKeys : []; + const excludeFilterKeys = isClickmap || isPathAnalysis ? eventKeys : []; - useEffect(() => { - if (!!metric && !initialInstance) { - setInitialInstance(metric.toJson()); - } - }, [metric]); + useEffect(() => { + if (!!metric && !initialInstance) { + setInitialInstance(metric.toJson()); + } + }, [metric]); - const writeOption = ({ value, name }: { value: any; name: any }) => { - value = Array.isArray(value) ? value : value.value; - const obj: any = { [name]: value }; + const writeOption = ({value, name}: { value: any; name: any }) => { + value = Array.isArray(value) ? value : value.value; + const obj: any = {[name]: value}; - if (name === 'metricType') { - switch (value) { - case TIMESERIES: - obj.metricOf = timeseriesOptions[0].value; - break; - case TABLE: - obj.metricOf = tableOptions[0].value; - break; - } + if (name === 'metricType') { + switch (value) { + case TIMESERIES: + obj.metricOf = timeseriesOptions[0].value; + break; + case TABLE: + obj.metricOf = tableOptions[0].value; + break; + } + } + + metricStore.merge(obj); + }; + + const onSave = async () => { + const wasCreating = !metric.exists(); + if (isClickmap) { + try { + metric.thumbnail = await renderClickmapThumbnail(); + } catch (e) { + console.error(e); + } + } + const savedMetric = await metricStore.save(metric); + setInitialInstance(metric.toJson()); + if (wasCreating) { + if (parseInt(dashboardId, 10) > 0) { + history.replace( + withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId) + ); + void dashboardStore.addWidgetToDashboard( + dashboardStore.getDashboard(parseInt(dashboardId, 10))!, + [savedMetric.metricId] + ); + } else { + history.replace(withSiteId(metricDetails(savedMetric.metricId), siteId)); + } + } + }; + + const onDelete = async () => { + if ( + await confirm({ + header: 'Confirm', + confirmButton: 'Yes, delete', + confirmation: `Are you sure you want to permanently delete this card?` + }) + ) { + metricStore.delete(metric).then(props.onDelete); + } + }; + + const undoChanges = () => { + const w = new Widget(); + metricStore.merge(w.fromJson(initialInstance), false); + }; + + const fetchResults = () => { + aiFiltersStore.getCardFilters(aiQuery, metric.metricType) + .then((f) => { + metric.createSeries(f.filters); + }) + }; + + const fetchChartData = () => { + void aiFiltersStore.getCardData(aiAskChart, metric.toJson()) } - metricStore.merge(obj); - }; + const handleKeyDown = (event: any) => { + if (event.key === 'Enter') { + fetchResults(); + } + }; + const handleChartKeyDown = (event: any) => { + if (event.key === 'Enter') { + fetchChartData(); + } + }; - const onSave = async () => { - const wasCreating = !metric.exists(); - if (isClickmap) { - try { - metric.thumbnail = await renderClickmapThumbnail(); - } catch (e) { - console.error(e); - } - } - const savedMetric = await metricStore.save(metric); - setInitialInstance(metric.toJson()); - if (wasCreating) { - if (parseInt(dashboardId, 10) > 0) { - history.replace( - withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId) - ); - void dashboardStore.addWidgetToDashboard( - dashboardStore.getDashboard(parseInt(dashboardId, 10))!, - [savedMetric.metricId] - ); - } else { - history.replace(withSiteId(metricDetails(savedMetric.metricId), siteId)); - } - } - }; + const testingKey = localStorage.getItem('__mauricio_testing_access') === 'true'; + return ( +
+ {/* +
+
+ Card showing + + - const onDelete = async () => { - if ( - await confirm({ - header: 'Confirm', - confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this card?` - }) - ) { - metricStore.delete(metric).then(props.onDelete); - } - }; + {isPathAnalysis && ( + <> + + + + )} - const fetchResults = () => { - aiFiltersStore.getCardFilters(aiQuery, metric.metricType) - .then((f) => { - metric.createSeries(f.filters); - }) - }; + {metric.metricOf === FilterKey.ISSUE && metric.metricType === TABLE && ( + <> + issue type + + + )} - const handleKeyDown = (event: any) => { - if (event.key === 'Enter') { - fetchResults(); - } - }; - const handleChartKeyDown = (event: any) => { - if (event.key === 'Enter') { - fetchChartData(); - } - }; - - const testingKey = localStorage.getItem('__mauricio_testing_access') === 'true'; - return ( -
-
-
- Card showing - - - - {isPathAnalysis && ( - <> - - - - )} - - {metric.metricOf === FilterKey.ISSUE && metric.metricType === TABLE && ( - <> - issue type - - - )} - - {metric.metricType === 'table' && - !(metric.metricOf === FilterKey.ERRORS || metric.metricOf === FilterKey.SESSIONS) && ( - <> - showing - setAiQuery(e.target.value)} - className="w-full mb-2" - onKeyDown={handleKeyDown} - /> : null} - {testingKey ? setAiAskChart(e.target.value)} - className="w-full mb-2" - onKeyDown={handleChartKeyDown} - /> : null} - {aiFiltersStore.isLoading ? ( -
-
- Loading -
-
- ) : null} - {!isPredefined && ( -
-
- {`${isTable || isFunnel || isClickmap || isInsights || isPathAnalysis || isRetention ? 'Filter by' : 'Chart Series'}`} - {!isTable && !isFunnel && !isClickmap && !isInsights && !isPathAnalysis && !isRetention && ( - - )} -
- - {metric.series.length > 0 && - metric.series - .slice(0, isTable || isFunnel || isClickmap || isInsights || isRetention ? 1 : metric.series.length) - .map((series: any, index: number) => ( -
- metric.updateKey('hasChanged', true)} - hideHeader={isTable || isClickmap || isInsights || isPathAnalysis || isFunnel} - seriesIndex={index} - series={series} - onRemoveSeries={() => metric.removeSeries(index)} - canDelete={metric.series.length > 1} - emptyMessage={ - isTable - ? 'Filter data using any event or attribute. Use Add Step button below to do so.' - : 'Add user event or filter to define the series by clicking Add Step.' - } - /> + {metric.metricType === 'table' && + !(metric.metricOf === FilterKey.ERRORS || metric.metricOf === FilterKey.SESSIONS) && ( + <> + showing + setAiQuery(e.target.value)} + className="w-full mb-2" + onKeyDown={handleKeyDown} + /> : null} + {testingKey ? setAiAskChart(e.target.value)} + className="w-full mb-2" + onKeyDown={handleChartKeyDown} + /> : null} + {aiFiltersStore.isLoading ? ( +
+
+ Loading +
+
+ ) : null} + {!isPredefined && ( +
+
+ {`${isTable || isFunnel || isClickmap || isInsights || isPathAnalysis || isRetention ? 'Filter by' : 'Chart Series'}`} + {!isTable && !isFunnel && !isClickmap && !isInsights && !isPathAnalysis && !isRetention && ( + + )} +
+ + {metric.series.length > 0 && + metric.series + .slice(0, isTable || isFunnel || isClickmap || isInsights || isRetention ? 1 : metric.series.length) + .map((series: any, index: number) => ( +
+ metric.updateKey('hasChanged', true)} + hideHeader={isTable || isClickmap || isInsights || isPathAnalysis || isFunnel} + seriesIndex={index} + series={series} + onRemoveSeries={() => metric.removeSeries(index)} + canDelete={metric.series.length > 1} + emptyMessage={ + isTable + ? 'Filter data using any event or attribute. Use Add Step button below to do so.' + : 'Add user event or filter to define the series by clicking Add Step.' + } + /> +
+ ))} +
+ )} + +
+ +
+ + {metric.exists() && metric.hasChanged && ( + + )} +
+
+
+ {metric.exists() && ( + + )} +
+
-
-
- ); + ); } export default observer(WidgetForm); diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx new file mode 100644 index 000000000..70af4ad6b --- /dev/null +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import {Card, Space, Typography, Button} from "antd"; +import {useStore} from "App/mstore"; +import FilterSelection from "Shared/Filters/FilterSelection/FilterSelection"; +import {eventKeys} from "Types/filter/newFilter"; +import {CLICKMAP, FUNNEL, INSIGHTS, RETENTION, TABLE, USER_PATH} from "App/constants/card"; +import FilterSeries from "Components/Dashboard/components/FilterSeries/FilterSeries"; +import {metricOf} from "App/constants/filterOptions"; +import {AudioWaveform, PlusIcon} from "lucide-react"; +import {observer} from "mobx-react-lite"; +import AddStepButton from "Components/Dashboard/components/FilterSeries/AddStepButton"; + + +interface Props { +} + +function WidgetFormNew(props: Props) { + const [expanded, setExpanded] = React.useState(true); + const {metricStore, dashboardStore, aiFiltersStore} = useStore(); + const metric: any = metricStore.instance; + + const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; + const filtersLength = metric.series[0].filter.filters.filter((i: any) => i && !i.isEvent).length; + const isClickmap = metric.metricType === CLICKMAP; + const isPathAnalysis = metric.metricType === USER_PATH; + const excludeFilterKeys = isClickmap || isPathAnalysis ? eventKeys : []; + const hasFilters = filtersLength > 0 || eventsLength > 0; + + return ( + <> + + {!hasFilters && ( + + )} + + + {/*{eventsLength > 0 && !expanded && (*/} + + {/*)}*/} + + {hasFilters && expanded && ( + + )} + + ); +} + +export default observer(WidgetFormNew); + + +function DefineSteps({metric, excludeFilterKeys}: any) { + return ( + + Define Steps + + + ); +} + + +const FilterSection = observer(({metric, excludeFilterKeys}: any) => { + // const timeseriesOptions = metricOf.filter((i) => i.type === 'timeseries'); + // const tableOptions = metricOf.filter((i) => i.type === 'table'); + const isTable = metric.metricType === TABLE; + const isClickMap = metric.metricType === CLICKMAP; + const isFunnel = metric.metricType === FUNNEL; + const isInsights = metric.metricType === INSIGHTS; + const isPathAnalysis = metric.metricType === USER_PATH; + const isRetention = metric.metricType === RETENTION; + const canAddSeries = metric.series.length < 3; + const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; + // const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1); + + const isSingleSeries = isTable || isFunnel || isClickMap || isInsights || isRetention + + // const onAddFilter = (filter: any) => { + // metric.series[0].filter.addFilter(filter); + // metric.updateKey('hasChanged', true) + // } + + return ( + <> + { + metric.series.length > 0 && metric.series + .slice(0, isSingleSeries ? 1 : metric.series.length) + .map((series: any, index: number) => ( +
+ metric.updateKey('hasChanged', true)} + hideHeader={isTable || isClickMap || isInsights || isPathAnalysis || isFunnel} + seriesIndex={index} + series={series} + onRemoveSeries={() => metric.removeSeries(index)} + canDelete={metric.series.length > 1} + emptyMessage={ + isTable + ? 'Filter data using any event or attribute. Use Add Step button below to do so.' + : 'Add user event or filter to define the series by clicking Add Step.' + } + /> +
+ )) + } + + {!isSingleSeries && canAddSeries && ( + + + + )} + + ); +}) diff --git a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx index 0a2727132..683a090f9 100644 --- a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx @@ -1,148 +1,135 @@ import React from 'react'; import cn from 'classnames'; import WidgetWrapper from '../WidgetWrapper'; -import { useStore } from 'App/mstore'; -import { SegmentSelection, Button, Icon } from 'UI'; -import { observer } from 'mobx-react-lite'; -import { FilterKey } from 'Types/filter/filterType'; -import WidgetDateRange from '../WidgetDateRange/WidgetDateRange'; +import {useStore} from 'App/mstore'; +// import {SegmentSelection, Button, Icon} from 'UI'; +import {observer} from 'mobx-react-lite'; +// import {FilterKey} from 'Types/filter/filterType'; +// import WidgetDateRange from '../WidgetDateRange/WidgetDateRange'; import ClickMapRagePicker from "Components/Dashboard/components/ClickMapRagePicker"; -import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelectionModal'; -import { CLICKMAP, TABLE, TIMESERIES, RETENTION, USER_PATH } from 'App/constants/card'; -import { Space, Switch } from 'antd'; +// import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelectionModal'; +import {CLICKMAP, TABLE, TIMESERIES, RETENTION, USER_PATH} from 'App/constants/card'; +import {Space, Switch} from 'antd'; +// import AddToDashboardButton from "Components/Dashboard/components/AddToDashboardButton"; interface Props { className?: string; name: string; isEditing?: boolean; } + function WidgetPreview(props: Props) { - const [showDashboardSelectionModal, setShowDashboardSelectionModal] = React.useState(false); - const { className = '' } = props; - const { metricStore, dashboardStore } = useStore(); - const dashboards = dashboardStore.dashboards; + const {className = ''} = props; + const {metricStore, dashboardStore} = useStore(); + // const dashboards = dashboardStore.dashboards; const metric: any = metricStore.instance; - const isTimeSeries = metric.metricType === TIMESERIES; - const isTable = metric.metricType === TABLE; - const isRetention = metric.metricType === RETENTION; - const disableVisualization = metric.metricOf === FilterKey.SESSIONS || metric.metricOf === FilterKey.ERRORS; - - const changeViewType = (_, { name, value }: any) => { - metric.update({ [ name ]: value }); - } - - const canAddToDashboard = metric.exists() && dashboards.length > 0; + // const isTimeSeries = metric.metricType === TIMESERIES; + // const isTable = metric.metricType === TABLE; + // const isRetention = metric.metricType === RETENTION; + // const disableVisualization = metric.metricOf === FilterKey.SESSIONS || metric.metricOf === FilterKey.ERRORS; + // + // const changeViewType = (_, {name, value}: any) => { + // metric.update({[name]: value}); + // } return ( <> -
-
-

- {props.name} -

-
- {metric.metricType === USER_PATH && ( - { - e.preventDefault(); - metric.update({ hideExcess: !metric.hideExcess }); - }} - > - - - Hide Minor Paths - - - )} - {isTimeSeries && ( - <> - Visualization - - - )} +
+
+

+ {props.name} +

+
+ {metric.metricType === USER_PATH && ( + { + e.preventDefault(); + metric.update({hideExcess: !metric.hideExcess}); + }} + > + + + Hide Minor Paths + + + )} - {!disableVisualization && isTable && ( - <> - Visualization - - - )} + {/*{isTimeSeries && (*/} + {/* <>*/} + {/* Visualization*/} + {/* */} + {/* */} + {/*)}*/} - {isRetention && ( - <> - Visualization - - - )} -
- {metric.metricType === CLICKMAP ? ( - - ) : null} - - {/* add to dashboard */} - {metric.exists() && ( - - )} + {/*{!disableVisualization && isTable && (*/} + {/* <>*/} + {/* Visualization*/} + {/* */} + {/* */} + {/*)}*/} + + {/*{isRetention && (*/} + {/* <>*/} + {/* Visualization*/} + {/* */} + {/**/} + {/*)}*/} + +
+ {metric.metricType === CLICKMAP ? ( + + ) : null} + + + {/* add to dashboard */} + {/*{metric.exists() && (*/} + {/* */} + {/*)}*/} +
+
+
+
-
- -
-
- { canAddToDashboard && ( - setShowDashboardSelectionModal(false)} - /> - )} ); } diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index be46a16d3..b1f00c057 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -1,18 +1,15 @@ -import React, { useState } from 'react'; -import { useStore } from 'App/mstore'; -import cn from 'classnames'; -import { Icon, Loader, NoContent } from 'UI'; -import WidgetForm from '../WidgetForm'; +import React, {useState} from 'react'; +import {useStore} from 'App/mstore'; +import {Icon, Loader, NoContent} from 'UI'; import WidgetPreview from '../WidgetPreview'; import WidgetSessions from '../WidgetSessions'; -import { useObserver } from 'mobx-react-lite'; -import WidgetName from '../WidgetName'; -import { withSiteId } from 'App/routes'; +import {useObserver} from 'mobx-react-lite'; +import {dashboardMetricDetails, metricDetails, withSiteId} from 'App/routes'; import FunnelIssues from '../Funnels/FunnelIssues/FunnelIssues'; import Breadcrumb from 'Shared/Breadcrumb'; -import { FilterKey } from 'Types/filter/filterType'; -import { Prompt } from 'react-router'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; +import {FilterKey} from 'Types/filter/filterType'; +import {Prompt, useHistory} from 'react-router'; +import AnimatedSVG, {ICONS} from 'Shared/AnimatedSVG/AnimatedSVG'; import { TIMESERIES, TABLE, @@ -21,31 +18,41 @@ import { INSIGHTS, USER_PATH, RETENTION, - } from 'App/constants/card'; +} from 'App/constants/card'; import CardIssues from '../CardIssues'; import CardUserList from '../CardUserList/CardUserList'; +import WidgetViewHeader from "Components/Dashboard/components/WidgetView/WidgetViewHeader"; +import WidgetFormNew from "Components/Dashboard/components/WidgetForm/WidgetFormNew"; +import {Space} from "antd"; +import {renderClickmapThumbnail} from "Components/Dashboard/components/WidgetForm/renderMap"; +import Widget from "App/mstore/types/widget"; interface Props { history: any; match: any; siteId: any; } + function WidgetView(props: Props) { const { match: { - params: { siteId, dashboardId, metricId }, + params: {siteId, dashboardId, metricId}, }, } = props; - const { metricStore, dashboardStore } = useStore(); + // const siteId = location.pathname.split('/')[1]; + // const dashboardId = location.pathname.split('/')[3]; + const {metricStore, dashboardStore} = useStore(); const widget = useObserver(() => metricStore.instance); const loading = useObserver(() => metricStore.isLoading); const [expanded, setExpanded] = useState(!metricId || metricId === 'create'); const hasChanged = useObserver(() => widget.hasChanged); - const dashboards = useObserver(() => dashboardStore.dashboards); const dashboard = useObserver(() => dashboards.find((d: any) => d.dashboardId == dashboardId)); const dashboardName = dashboard ? dashboard.name : null; const [metricNotFound, setMetricNotFound] = useState(false); + const history = useHistory(); + const [initialInstance, setInitialInstance] = useState(); + const isClickMap = widget.metricType === CLICKMAP; React.useEffect(() => { if (metricId && metricId !== 'create') { @@ -59,13 +66,44 @@ function WidgetView(props: Props) { } }, []); - const onBackHandler = () => { - props.history.goBack(); + // const onBackHandler = () => { + // props.history.goBack(); + // }; + // + // const openEdit = () => { + // if (expanded) return; + // setExpanded(true); + // }; + + const undoChanges = () => { + const w = new Widget(); + metricStore.merge(w.fromJson(initialInstance), false); }; - const openEdit = () => { - if (expanded) return; - setExpanded(true); + const onSave = async () => { + const wasCreating = !widget.exists(); + if (isClickMap) { + try { + widget.thumbnail = await renderClickmapThumbnail(); + } catch (e) { + console.error(e); + } + } + const savedMetric = await metricStore.save(widget); + setInitialInstance(widget.toJson()); + if (wasCreating) { + if (parseInt(dashboardId, 10) > 0) { + history.replace( + withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId) + ); + void dashboardStore.addWidgetToDashboard( + dashboardStore.getDashboard(parseInt(dashboardId, 10))!, + [savedMetric.metricId] + ); + } else { + history.replace(withSiteId(metricDetails(savedMetric.metricId), siteId)); + } + } }; return useObserver(() => ( @@ -80,57 +118,47 @@ function WidgetView(props: Props) { }} /> -
+
- +
Metric not found!
} > -
-
-

- metricStore.merge({ name })} canEdit={expanded} /> -

-
setExpanded(!expanded)}> -
- {expanded ? 'Collapse' : 'Edit'} - -
-
-
+ + - {expanded && } -
+ - - - {widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ( - <> - {(widget.metricType === TABLE || widget.metricType === TIMESERIES || widget.metricType === CLICKMAP || widget.metricType === INSIGHTS) && } - {widget.metricType === FUNNEL && } - - )} + {/*
*/} + {/* */} + {/*
*/} - {widget.metricType === USER_PATH && } - {widget.metricType === RETENTION && } + + + {widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ( + <> + {(widget.metricType === TABLE || widget.metricType === TIMESERIES || widget.metricType === CLICKMAP || widget.metricType === INSIGHTS) && + } + {widget.metricType === FUNNEL && } + + )} + + {widget.metricType === USER_PATH && } + {widget.metricType === RETENTION && } +
diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx new file mode 100644 index 000000000..d54528e9b --- /dev/null +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import cn from "classnames"; +import WidgetName from "Components/Dashboard/components/WidgetName"; +import {useStore} from "App/mstore"; +import {useObserver} from "mobx-react-lite"; +import AddToDashboardButton from "Components/Dashboard/components/AddToDashboardButton"; +import WidgetDateRange from "Components/Dashboard/components/WidgetDateRange/WidgetDateRange"; +import {Button, Space} from "antd"; + +interface Props { + onClick?: () => void; + onSave: () => void; + undoChanges?: () => void; +} + +function WidgetViewHeader({onClick, onSave, undoChanges}: Props) { + const {metricStore, dashboardStore} = useStore(); + const widget = useObserver(() => metricStore.instance); + + return ( +
+

+ metricStore.merge({name})} + canEdit={true}/> +

+ + + + + +
+ ); +} + +export default WidgetViewHeader; diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx index 548bc9570..0b50abdd4 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx @@ -4,7 +4,7 @@ import { useStore } from 'App/mstore'; interface Props { seriesId: string; - initAlert: Function; + initAlert?: Function; } function AlertButton(props: Props) { const { seriesId } = props; @@ -24,4 +24,4 @@ function AlertButton(props: Props) { ); } -export default AlertButton; \ No newline at end of file +export default AlertButton; diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx new file mode 100644 index 000000000..b1fd54cd4 --- /dev/null +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx @@ -0,0 +1,181 @@ +import React, {useRef} from 'react'; +import cn from 'classnames'; +import {Card, Tooltip, Button} from 'antd'; +import {ItemMenu, TextEllipsis} from 'UI'; +import {useDrag, useDrop} from 'react-dnd'; +import WidgetChart from '../WidgetChart'; +import {observer} from 'mobx-react-lite'; +import {useStore} from 'App/mstore'; +import {withRouter, RouteComponentProps} from 'react-router-dom'; +import {withSiteId, dashboardMetricDetails} from 'App/routes'; +import TemplateOverlay from './TemplateOverlay'; +import AlertButton from './AlertButton'; +import stl from './widgetWrapper.module.css'; +import {FilterKey} from 'App/types/filter/filterType'; +import LazyLoad from 'react-lazyload'; +import {TIMESERIES} from "App/constants/card"; + +interface Props { + className?: string; + widget?: any; + index?: number; + moveListItem?: any; + isPreview?: boolean; + isTemplate?: boolean; + dashboardId?: string; + siteId?: string; + active?: boolean; + history?: any; + onClick?: () => void; + isWidget?: boolean; + hideName?: boolean; + grid?: string; + isGridView?: boolean; +} + +function WidgetWrapperNew(props: Props & RouteComponentProps) { + const {dashboardStore} = useStore(); + const { + isWidget = false, + active = false, + index = 0, + moveListItem = null, + isPreview = false, + isTemplate = false, + siteId, + grid = '', + isGridView = false, + } = props; + const widget: any = props.widget; + const isTimeSeries = widget.metricType === TIMESERIES; + const isPredefined = widget.metricType === 'predefined'; + const dashboard = dashboardStore.selectedDashboard; + + const [{isDragging}, dragRef] = useDrag({ + type: 'item', + item: {index, grid}, + collect: (monitor) => ({ + isDragging: monitor.isDragging(), + }), + }); + + const [{isOver, canDrop}, dropRef] = useDrop({ + accept: 'item', + drop: (item: any) => { + if (item.index === index || item.grid !== grid) return; + moveListItem(item.index, index); + }, + canDrop(item) { + return item.grid === grid; + }, + collect: (monitor: any) => ({ + isOver: monitor.isOver(), + canDrop: monitor.canDrop(), + }), + }); + + const onDelete = async () => { + dashboardStore.deleteDashboardWidget(dashboard?.dashboardId!, widget.widgetId); + }; + + const onChartClick = () => { + if (!isWidget || isPredefined) return; + props.history.push( + withSiteId(dashboardMetricDetails(dashboard?.dashboardId, widget.metricId), siteId) + ); + }; + + const ref: any = useRef(null); + const dragDropRef: any = dragRef(dropRef(ref)); + const addOverlay = + isTemplate || + (!isPredefined && + isWidget && + widget.metricOf !== FilterKey.ERRORS && + widget.metricOf !== FilterKey.SESSIONS); + + return ( + null} + id={`widget-${widget.widgetId}`} + title={!props.hideName ? widget.name : null} + extra={isWidget ? [ +
+ {!isPredefined && isTimeSeries && !isGridView && ( + <> + +
+ + )} + + {!isTemplate && !isGridView && ( + + )} +
+ ] : []} + styles={{ + header: { + padding: '0 14px', + borderBottom: 'none', + minHeight: 44, + fontWeight: 500, + fontSize: 14, + }, + body: { + padding: 0, + }, + }} + > + {!isTemplate && isWidget && isPredefined && ( + +
+ {'Cannot drill down system provided metrics'} +
+
+ )} + + {addOverlay && } + + +
+ +
+
+ + ); +} + +export default withRouter(observer(WidgetWrapperNew)); diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/widgetWrapper.module.css b/frontend/app/components/Dashboard/components/WidgetWrapper/widgetWrapper.module.css index c9d6530ec..899e4007e 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/widgetWrapper.module.css +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/widgetWrapper.module.css @@ -13,6 +13,7 @@ left: 0; right: 0; } + .overlayDashboard { - top: 20%!important; + top: 40px !important; } diff --git a/frontend/app/components/ui/Icons/color_browser_Tor.tsx b/frontend/app/components/ui/Icons/color_browser_Tor.tsx new file mode 100644 index 000000000..f058a16f2 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_Tor.tsx @@ -0,0 +1,31 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_tor(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + ); +} + +export default Color_browser_tor; diff --git a/frontend/app/components/ui/Icons/color_browser_applebot.tsx b/frontend/app/components/ui/Icons/color_browser_applebot.tsx new file mode 100644 index 000000000..df6d17c49 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_applebot.tsx @@ -0,0 +1,29 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_applebot(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + ); +} + +export default Color_browser_applebot; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_Tor.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_Tor.tsx new file mode 100644 index 000000000..97790107e --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_Tor.tsx @@ -0,0 +1,31 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_tor(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_tor; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_applebot.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_applebot.tsx new file mode 100644 index 000000000..4a89a1c58 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_applebot.tsx @@ -0,0 +1,29 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_applebot(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_applebot; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome.tsx new file mode 100644 index 000000000..03d2bc838 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_chrome(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_chrome; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile.tsx new file mode 100644 index 000000000..3334a23bf --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_chrome_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_chrome_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile_ios.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile_ios.tsx new file mode 100644 index 000000000..9fcfe34ce --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_chrome_mobile_ios.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_chrome_mobile_ios(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_chrome_mobile_ios; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_duck_duck_go.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_duck_duck_go.tsx new file mode 100644 index 000000000..882d028f1 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_duck_duck_go.tsx @@ -0,0 +1,59 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_duck_duck_go(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_duck_duck_go; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_duckduckgo_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_duckduckgo_mobile.tsx new file mode 100644 index 000000000..ba29a7048 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_duckduckgo_mobile.tsx @@ -0,0 +1,59 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_duckduckgo_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_duckduckgo_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge.tsx new file mode 100644 index 000000000..3c5137612 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge.tsx @@ -0,0 +1,47 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_edge(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_edge; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge_mobile.tsx new file mode 100644 index 000000000..d1de8b61d --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_edge_mobile.tsx @@ -0,0 +1,47 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_edge_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_edge_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_facebook.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_facebook.tsx new file mode 100644 index 000000000..7840dc2db --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_facebook.tsx @@ -0,0 +1,28 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_facebook(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_facebook; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox.tsx new file mode 100644 index 000000000..530510311 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox.tsx @@ -0,0 +1,124 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_firefox(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_firefox; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_ios.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_ios.tsx new file mode 100644 index 000000000..194fd7d17 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_ios.tsx @@ -0,0 +1,124 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_firefox_ios(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_firefox_ios; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_mobile.tsx new file mode 100644 index 000000000..e8ef605f8 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_firefox_mobile.tsx @@ -0,0 +1,124 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_firefox_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_firefox_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_google.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_google.tsx new file mode 100644 index 000000000..cf501b842 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_google.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_google(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_browser_browser_icons_color_google; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_googlebot.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_googlebot.tsx new file mode 100644 index 000000000..e718ad635 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_googlebot.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_googlebot(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_browser_browser_icons_color_googlebot; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_huawei_browser.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_huawei_browser.tsx new file mode 100644 index 000000000..4441c68dd --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_huawei_browser.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_huawei_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_browser_browser_icons_color_huawei_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_internet_explorer.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_internet_explorer.tsx new file mode 100644 index 000000000..f35efa231 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_internet_explorer.tsx @@ -0,0 +1,21 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_internet_explorer(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + ); +} + +export default Color_browser_browser_icons_color_internet_explorer; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_miui_browser.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_miui_browser.tsx new file mode 100644 index 000000000..8f5a7b9d3 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_miui_browser.tsx @@ -0,0 +1,28 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_miui_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_miui_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari.tsx new file mode 100644 index 000000000..0b859eb31 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari.tsx @@ -0,0 +1,171 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_mobile_safari(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_mobile_safari; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari_ui.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari_ui.tsx new file mode 100644 index 000000000..5dd4759fa --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_mobile_safari_ui.tsx @@ -0,0 +1,171 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_mobile_safari_ui(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_mobile_safari_ui; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_opera.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_opera.tsx new file mode 100644 index 000000000..014c116a3 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_opera.tsx @@ -0,0 +1,36 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_opera(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_opera; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_safari.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_safari.tsx new file mode 100644 index 000000000..82d1dc987 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_safari.tsx @@ -0,0 +1,171 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_safari(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_safari; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_samsung_internet.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_samsung_internet.tsx new file mode 100644 index 000000000..9d522aceb --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_samsung_internet.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_samsung_internet(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_browser_browser_icons_color_samsung_internet; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_uc_browser.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_uc_browser.tsx new file mode 100644 index 000000000..c617b1a71 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_uc_browser.tsx @@ -0,0 +1,52 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_uc_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_uc_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_unknown.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_unknown.tsx new file mode 100644 index 000000000..9dd310dcc --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_unknown.tsx @@ -0,0 +1,23 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_unknown(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + ); +} + +export default Color_browser_browser_icons_color_unknown; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_whale.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_whale.tsx new file mode 100644 index 000000000..1bbabf2b6 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_whale.tsx @@ -0,0 +1,43 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_whale(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_browser_icons_color_whale; diff --git a/frontend/app/components/ui/Icons/color_browser_browser_icons_color_yandex_browser.tsx b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_yandex_browser.tsx new file mode 100644 index 000000000..3d4982f69 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_browser_icons_color_yandex_browser.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_browser_icons_color_yandex_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_browser_browser_icons_color_yandex_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_chrome.tsx b/frontend/app/components/ui/Icons/color_browser_chrome.tsx new file mode 100644 index 000000000..17a41d20d --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_chrome.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_chrome(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_chrome; diff --git a/frontend/app/components/ui/Icons/color_browser_chrome_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_chrome_mobile.tsx new file mode 100644 index 000000000..ea003623f --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_chrome_mobile.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_chrome_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_chrome_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_chrome_mobile_ios.tsx b/frontend/app/components/ui/Icons/color_browser_chrome_mobile_ios.tsx new file mode 100644 index 000000000..dc26328cb --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_chrome_mobile_ios.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_chrome_mobile_ios(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_chrome_mobile_ios; diff --git a/frontend/app/components/ui/Icons/color_browser_duck_duck_go.tsx b/frontend/app/components/ui/Icons/color_browser_duck_duck_go.tsx new file mode 100644 index 000000000..65194f9b1 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_duck_duck_go.tsx @@ -0,0 +1,59 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_duck_duck_go(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_duck_duck_go; diff --git a/frontend/app/components/ui/Icons/color_browser_duckduckgo_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_duckduckgo_mobile.tsx new file mode 100644 index 000000000..c4f77cb33 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_duckduckgo_mobile.tsx @@ -0,0 +1,59 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_duckduckgo_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_duckduckgo_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_edge.tsx b/frontend/app/components/ui/Icons/color_browser_edge.tsx new file mode 100644 index 000000000..350919ecc --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_edge.tsx @@ -0,0 +1,47 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_edge(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_edge; diff --git a/frontend/app/components/ui/Icons/color_browser_edge_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_edge_mobile.tsx new file mode 100644 index 000000000..6d4126152 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_edge_mobile.tsx @@ -0,0 +1,47 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_edge_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_edge_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_facebook.tsx b/frontend/app/components/ui/Icons/color_browser_facebook.tsx new file mode 100644 index 000000000..504a748cc --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_facebook.tsx @@ -0,0 +1,28 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_facebook(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + ); +} + +export default Color_browser_facebook; diff --git a/frontend/app/components/ui/Icons/color_browser_firefox.tsx b/frontend/app/components/ui/Icons/color_browser_firefox.tsx new file mode 100644 index 000000000..41b53363c --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_firefox.tsx @@ -0,0 +1,124 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_firefox(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_firefox; diff --git a/frontend/app/components/ui/Icons/color_browser_firefox_ios.tsx b/frontend/app/components/ui/Icons/color_browser_firefox_ios.tsx new file mode 100644 index 000000000..a041bd941 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_firefox_ios.tsx @@ -0,0 +1,124 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_firefox_ios(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_firefox_ios; diff --git a/frontend/app/components/ui/Icons/color_browser_firefox_mobile.tsx b/frontend/app/components/ui/Icons/color_browser_firefox_mobile.tsx new file mode 100644 index 000000000..169e9733d --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_firefox_mobile.tsx @@ -0,0 +1,124 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_firefox_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_firefox_mobile; diff --git a/frontend/app/components/ui/Icons/color_browser_google.tsx b/frontend/app/components/ui/Icons/color_browser_google.tsx new file mode 100644 index 000000000..e49dafeb4 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_google.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_google(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_browser_google; diff --git a/frontend/app/components/ui/Icons/color_browser_googlebot.tsx b/frontend/app/components/ui/Icons/color_browser_googlebot.tsx new file mode 100644 index 000000000..9ff0d24f8 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_googlebot.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_googlebot(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_browser_googlebot; diff --git a/frontend/app/components/ui/Icons/color_browser_huawei_browser.tsx b/frontend/app/components/ui/Icons/color_browser_huawei_browser.tsx new file mode 100644 index 000000000..c5779f10f --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_huawei_browser.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_huawei_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_browser_huawei_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_internet_explorer.tsx b/frontend/app/components/ui/Icons/color_browser_internet_explorer.tsx new file mode 100644 index 000000000..13f6deca4 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_internet_explorer.tsx @@ -0,0 +1,21 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_internet_explorer(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + ); +} + +export default Color_browser_internet_explorer; diff --git a/frontend/app/components/ui/Icons/color_browser_miui_browser.tsx b/frontend/app/components/ui/Icons/color_browser_miui_browser.tsx new file mode 100644 index 000000000..36f97bf3f --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_miui_browser.tsx @@ -0,0 +1,28 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_miui_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + ); +} + +export default Color_browser_miui_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_mobile_safari.tsx b/frontend/app/components/ui/Icons/color_browser_mobile_safari.tsx new file mode 100644 index 000000000..2c1dd03c8 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_mobile_safari.tsx @@ -0,0 +1,171 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_mobile_safari(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_mobile_safari; diff --git a/frontend/app/components/ui/Icons/color_browser_mobile_safari_ui.tsx b/frontend/app/components/ui/Icons/color_browser_mobile_safari_ui.tsx new file mode 100644 index 000000000..c29c4c146 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_mobile_safari_ui.tsx @@ -0,0 +1,171 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_mobile_safari_ui(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_mobile_safari_ui; diff --git a/frontend/app/components/ui/Icons/color_browser_opera.tsx b/frontend/app/components/ui/Icons/color_browser_opera.tsx new file mode 100644 index 000000000..655f404df --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_opera.tsx @@ -0,0 +1,36 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_opera(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_opera; diff --git a/frontend/app/components/ui/Icons/color_browser_safari.tsx b/frontend/app/components/ui/Icons/color_browser_safari.tsx new file mode 100644 index 000000000..6134ccd85 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_safari.tsx @@ -0,0 +1,171 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_safari(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_safari; diff --git a/frontend/app/components/ui/Icons/color_browser_samsung_internet.tsx b/frontend/app/components/ui/Icons/color_browser_samsung_internet.tsx new file mode 100644 index 000000000..83950918f --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_samsung_internet.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_samsung_internet(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_browser_samsung_internet; diff --git a/frontend/app/components/ui/Icons/color_browser_uc_browser.tsx b/frontend/app/components/ui/Icons/color_browser_uc_browser.tsx new file mode 100644 index 000000000..8437e9c4c --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_uc_browser.tsx @@ -0,0 +1,52 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_uc_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_uc_browser; diff --git a/frontend/app/components/ui/Icons/color_browser_unknown.tsx b/frontend/app/components/ui/Icons/color_browser_unknown.tsx new file mode 100644 index 000000000..2e54d1e8e --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_unknown.tsx @@ -0,0 +1,23 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_unknown(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + ); +} + +export default Color_browser_unknown; diff --git a/frontend/app/components/ui/Icons/color_browser_whale.tsx b/frontend/app/components/ui/Icons/color_browser_whale.tsx new file mode 100644 index 000000000..255a41aa0 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_whale.tsx @@ -0,0 +1,43 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_whale(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_browser_whale; diff --git a/frontend/app/components/ui/Icons/color_browser_yandex_browser.tsx b/frontend/app/components/ui/Icons/color_browser_yandex_browser.tsx new file mode 100644 index 000000000..165012319 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_browser_yandex_browser.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_browser_yandex_browser(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_browser_yandex_browser; diff --git a/frontend/app/components/ui/Icons/color_country_de.tsx b/frontend/app/components/ui/Icons/color_country_de.tsx new file mode 100644 index 000000000..9ab278f0a --- /dev/null +++ b/frontend/app/components/ui/Icons/color_country_de.tsx @@ -0,0 +1,32 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_country_de(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + ); +} + +export default Color_country_de; diff --git a/frontend/app/components/ui/Icons/color_country_fr.tsx b/frontend/app/components/ui/Icons/color_country_fr.tsx new file mode 100644 index 000000000..dc49d0a8a --- /dev/null +++ b/frontend/app/components/ui/Icons/color_country_fr.tsx @@ -0,0 +1,32 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_country_fr(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + ); +} + +export default Color_country_fr; diff --git a/frontend/app/components/ui/Icons/color_country_gb.tsx b/frontend/app/components/ui/Icons/color_country_gb.tsx new file mode 100644 index 000000000..2cae970c1 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_country_gb.tsx @@ -0,0 +1,44 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_country_gb(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_country_gb; diff --git a/frontend/app/components/ui/Icons/color_country_in.tsx b/frontend/app/components/ui/Icons/color_country_in.tsx new file mode 100644 index 000000000..5b653d55c --- /dev/null +++ b/frontend/app/components/ui/Icons/color_country_in.tsx @@ -0,0 +1,39 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_country_in(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_country_in; diff --git a/frontend/app/components/ui/Icons/color_country_us.tsx b/frontend/app/components/ui/Icons/color_country_us.tsx new file mode 100644 index 000000000..99c5da188 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_country_us.tsx @@ -0,0 +1,39 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_country_us(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_country_us; diff --git a/frontend/app/components/ui/Icons/color_device_desktop.tsx b/frontend/app/components/ui/Icons/color_device_desktop.tsx new file mode 100644 index 000000000..912b9f809 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_device_desktop.tsx @@ -0,0 +1,23 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_device_desktop(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + ); +} + +export default Color_device_desktop; diff --git a/frontend/app/components/ui/Icons/color_device_mobile.tsx b/frontend/app/components/ui/Icons/color_device_mobile.tsx new file mode 100644 index 000000000..689568920 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_device_mobile.tsx @@ -0,0 +1,35 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_device_mobile(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + ); +} + +export default Color_device_mobile; diff --git a/frontend/app/components/ui/Icons/color_device_other_phone.tsx b/frontend/app/components/ui/Icons/color_device_other_phone.tsx new file mode 100644 index 000000000..27c6e96b6 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_device_other_phone.tsx @@ -0,0 +1,30 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_device_other_phone(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + ); +} + +export default Color_device_other_phone; diff --git a/frontend/app/components/ui/Icons/color_device_tablet.tsx b/frontend/app/components/ui/Icons/color_device_tablet.tsx new file mode 100644 index 000000000..9ddadca3f --- /dev/null +++ b/frontend/app/components/ui/Icons/color_device_tablet.tsx @@ -0,0 +1,23 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_device_tablet(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + ); +} + +export default Color_device_tablet; diff --git a/frontend/app/components/ui/Icons/color_device_unkown.tsx b/frontend/app/components/ui/Icons/color_device_unkown.tsx new file mode 100644 index 000000000..e70102fc1 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_device_unkown.tsx @@ -0,0 +1,25 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_device_unkown(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + ); +} + +export default Color_device_unkown; diff --git a/frontend/app/components/ui/Icons/color_os_android.tsx b/frontend/app/components/ui/Icons/color_os_android.tsx new file mode 100644 index 000000000..3c92aa44c --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_android.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_android(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_os_android; diff --git a/frontend/app/components/ui/Icons/color_os_apple.tsx b/frontend/app/components/ui/Icons/color_os_apple.tsx new file mode 100644 index 000000000..00251c99a --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_apple.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_apple(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_os_apple; diff --git a/frontend/app/components/ui/Icons/color_os_blackberry.tsx b/frontend/app/components/ui/Icons/color_os_blackberry.tsx new file mode 100644 index 000000000..b8c4c7040 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_blackberry.tsx @@ -0,0 +1,28 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_blackberry(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + ); +} + +export default Color_os_blackberry; diff --git a/frontend/app/components/ui/Icons/color_os_chrome_os.tsx b/frontend/app/components/ui/Icons/color_os_chrome_os.tsx new file mode 100644 index 000000000..91dcf6d18 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_chrome_os.tsx @@ -0,0 +1,34 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_chrome_os(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + ); +} + +export default Color_os_chrome_os; diff --git a/frontend/app/components/ui/Icons/color_os_elementary.tsx b/frontend/app/components/ui/Icons/color_os_elementary.tsx new file mode 100644 index 000000000..8ed7b6a61 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_elementary.tsx @@ -0,0 +1,21 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_elementary(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + ); +} + +export default Color_os_elementary; diff --git a/frontend/app/components/ui/Icons/color_os_fedora.tsx b/frontend/app/components/ui/Icons/color_os_fedora.tsx new file mode 100644 index 000000000..e9126d10a --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_fedora.tsx @@ -0,0 +1,23 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_fedora(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + ); +} + +export default Color_os_fedora; diff --git a/frontend/app/components/ui/Icons/color_os_freebsd.tsx b/frontend/app/components/ui/Icons/color_os_freebsd.tsx new file mode 100644 index 000000000..6038fa31c --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_freebsd.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_freebsd(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_os_freebsd; diff --git a/frontend/app/components/ui/Icons/color_os_gnome.tsx b/frontend/app/components/ui/Icons/color_os_gnome.tsx new file mode 100644 index 000000000..856c593e6 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_gnome.tsx @@ -0,0 +1,21 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_gnome(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + ); +} + +export default Color_os_gnome; diff --git a/frontend/app/components/ui/Icons/color_os_ios.tsx b/frontend/app/components/ui/Icons/color_os_ios.tsx new file mode 100644 index 000000000..f5f267c24 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_ios.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_ios(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_os_ios; diff --git a/frontend/app/components/ui/Icons/color_os_linux.tsx b/frontend/app/components/ui/Icons/color_os_linux.tsx new file mode 100644 index 000000000..f49bbe0c9 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_linux.tsx @@ -0,0 +1,109 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_linux(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_os_linux; diff --git a/frontend/app/components/ui/Icons/color_os_linux_mint.tsx b/frontend/app/components/ui/Icons/color_os_linux_mint.tsx new file mode 100644 index 000000000..62d1de60e --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_linux_mint.tsx @@ -0,0 +1,36 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_linux_mint(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + + + + + + + ); +} + +export default Color_os_linux_mint; diff --git a/frontend/app/components/ui/Icons/color_os_macos.tsx b/frontend/app/components/ui/Icons/color_os_macos.tsx new file mode 100644 index 000000000..385e42140 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_macos.tsx @@ -0,0 +1,30 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_macos(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + + + + + + ); +} + +export default Color_os_macos; diff --git a/frontend/app/components/ui/Icons/color_os_microsoft.tsx b/frontend/app/components/ui/Icons/color_os_microsoft.tsx new file mode 100644 index 000000000..473f2c462 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_microsoft.tsx @@ -0,0 +1,24 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_microsoft(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + ); +} + +export default Color_os_microsoft; diff --git a/frontend/app/components/ui/Icons/color_os_ubuntu.tsx b/frontend/app/components/ui/Icons/color_os_ubuntu.tsx new file mode 100644 index 000000000..c43c8f2c7 --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_ubuntu.tsx @@ -0,0 +1,22 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_ubuntu(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + ); +} + +export default Color_os_ubuntu; diff --git a/frontend/app/components/ui/Icons/color_os_unkown.tsx b/frontend/app/components/ui/Icons/color_os_unkown.tsx new file mode 100644 index 000000000..ba81af46d --- /dev/null +++ b/frontend/app/components/ui/Icons/color_os_unkown.tsx @@ -0,0 +1,25 @@ + +/* Auto-generated, do not edit */ +import React from 'react'; + +interface Props { + size?: number | string; + width?: number | string; + height?: number | string; + fill?: string; +} + +function Color_os_unkown(props: Props) { + const { size = 14, width = size, height = size, fill = '' } = props; + return ( + + + + + + + + ); +} + +export default Color_os_unkown; diff --git a/frontend/app/components/ui/Icons/index.ts b/frontend/app/components/ui/Icons/index.ts index 736064750..6fc2a46b3 100644 --- a/frontend/app/components/ui/Icons/index.ts +++ b/frontend/app/components/ui/Icons/index.ts @@ -114,8 +114,45 @@ export { default as Cogs } from './cogs'; export { default as Collection_play } from './collection_play'; export { default as Collection } from './collection'; export { default as Color_apple } from './color_apple'; +export { default as Color_browser_tor } from './color_browser_Tor'; +export { default as Color_browser_applebot } from './color_browser_applebot'; +export { default as Color_browser_chrome } from './color_browser_chrome'; +export { default as Color_browser_chrome_mobile } from './color_browser_chrome_mobile'; +export { default as Color_browser_chrome_mobile_ios } from './color_browser_chrome_mobile_ios'; +export { default as Color_browser_duck_duck_go } from './color_browser_duck_duck_go'; +export { default as Color_browser_duckduckgo_mobile } from './color_browser_duckduckgo_mobile'; +export { default as Color_browser_edge } from './color_browser_edge'; +export { default as Color_browser_edge_mobile } from './color_browser_edge_mobile'; +export { default as Color_browser_facebook } from './color_browser_facebook'; +export { default as Color_browser_firefox } from './color_browser_firefox'; +export { default as Color_browser_firefox_ios } from './color_browser_firefox_ios'; +export { default as Color_browser_firefox_mobile } from './color_browser_firefox_mobile'; +export { default as Color_browser_google } from './color_browser_google'; +export { default as Color_browser_googlebot } from './color_browser_googlebot'; +export { default as Color_browser_huawei_browser } from './color_browser_huawei_browser'; +export { default as Color_browser_internet_explorer } from './color_browser_internet_explorer'; +export { default as Color_browser_miui_browser } from './color_browser_miui_browser'; +export { default as Color_browser_mobile_safari } from './color_browser_mobile_safari'; +export { default as Color_browser_mobile_safari_ui } from './color_browser_mobile_safari_ui'; +export { default as Color_browser_opera } from './color_browser_opera'; +export { default as Color_browser_safari } from './color_browser_safari'; +export { default as Color_browser_samsung_internet } from './color_browser_samsung_internet'; +export { default as Color_browser_uc_browser } from './color_browser_uc_browser'; +export { default as Color_browser_unknown } from './color_browser_unknown'; +export { default as Color_browser_whale } from './color_browser_whale'; +export { default as Color_browser_yandex_browser } from './color_browser_yandex_browser'; export { default as Color_chrome } from './color_chrome'; +export { default as Color_country_de } from './color_country_de'; +export { default as Color_country_fr } from './color_country_fr'; +export { default as Color_country_gb } from './color_country_gb'; +export { default as Color_country_in } from './color_country_in'; +export { default as Color_country_us } from './color_country_us'; export { default as Color_de } from './color_de'; +export { default as Color_device_desktop } from './color_device_desktop'; +export { default as Color_device_mobile } from './color_device_mobile'; +export { default as Color_device_other_phone } from './color_device_other_phone'; +export { default as Color_device_tablet } from './color_device_tablet'; +export { default as Color_device_unkown } from './color_device_unkown'; export { default as Color_edge } from './color_edge'; export { default as Color_fedora } from './color_fedora'; export { default as Color_firefox } from './color_firefox'; @@ -124,6 +161,21 @@ export { default as Color_gb } from './color_gb'; export { default as Color_in } from './color_in'; export { default as Color_microsoft } from './color_microsoft'; export { default as Color_opera } from './color_opera'; +export { default as Color_os_android } from './color_os_android'; +export { default as Color_os_apple } from './color_os_apple'; +export { default as Color_os_blackberry } from './color_os_blackberry'; +export { default as Color_os_chrome_os } from './color_os_chrome_os'; +export { default as Color_os_elementary } from './color_os_elementary'; +export { default as Color_os_fedora } from './color_os_fedora'; +export { default as Color_os_freebsd } from './color_os_freebsd'; +export { default as Color_os_gnome } from './color_os_gnome'; +export { default as Color_os_ios } from './color_os_ios'; +export { default as Color_os_linux } from './color_os_linux'; +export { default as Color_os_linux_mint } from './color_os_linux_mint'; +export { default as Color_os_macos } from './color_os_macos'; +export { default as Color_os_microsoft } from './color_os_microsoft'; +export { default as Color_os_ubuntu } from './color_os_ubuntu'; +export { default as Color_os_unkown } from './color_os_unkown'; export { default as Color_safari } from './color_safari'; export { default as Color_ubuntu } from './color_ubuntu'; export { default as Color_us } from './color_us'; diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index 0543bd6de..4fdadcbe1 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -116,8 +116,45 @@ import { Collection_play, Collection, Color_apple, + Color_browser_tor, + Color_browser_applebot, + Color_browser_chrome, + Color_browser_chrome_mobile, + Color_browser_chrome_mobile_ios, + Color_browser_duck_duck_go, + Color_browser_duckduckgo_mobile, + Color_browser_edge, + Color_browser_edge_mobile, + Color_browser_facebook, + Color_browser_firefox, + Color_browser_firefox_ios, + Color_browser_firefox_mobile, + Color_browser_google, + Color_browser_googlebot, + Color_browser_huawei_browser, + Color_browser_internet_explorer, + Color_browser_miui_browser, + Color_browser_mobile_safari, + Color_browser_mobile_safari_ui, + Color_browser_opera, + Color_browser_safari, + Color_browser_samsung_internet, + Color_browser_uc_browser, + Color_browser_unknown, + Color_browser_whale, + Color_browser_yandex_browser, Color_chrome, + Color_country_de, + Color_country_fr, + Color_country_gb, + Color_country_in, + Color_country_us, Color_de, + Color_device_desktop, + Color_device_mobile, + Color_device_other_phone, + Color_device_tablet, + Color_device_unkown, Color_edge, Color_fedora, Color_firefox, @@ -126,6 +163,21 @@ import { Color_in, Color_microsoft, Color_opera, + Color_os_android, + Color_os_apple, + Color_os_blackberry, + Color_os_chrome_os, + Color_os_elementary, + Color_os_fedora, + Color_os_freebsd, + Color_os_gnome, + Color_os_ios, + Color_os_linux, + Color_os_linux_mint, + Color_os_macos, + Color_os_microsoft, + Color_os_ubuntu, + Color_os_unkown, Color_safari, Color_ubuntu, Color_us, @@ -490,7 +542,7 @@ import { Zoom_in } from './Icons' -export type IconNames = 'activity' | 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-bar-left' | 'arrow-clockwise' | 'arrow-counterclockwise' | 'arrow-down-short' | 'arrow-down-up' | 'arrow-down' | 'arrow-repeat' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up-short' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_avatar1' | 'avatar/icn_avatar10' | 'avatar/icn_avatar11' | 'avatar/icn_avatar12' | 'avatar/icn_avatar13' | 'avatar/icn_avatar14' | 'avatar/icn_avatar15' | 'avatar/icn_avatar16' | 'avatar/icn_avatar17' | 'avatar/icn_avatar18' | 'avatar/icn_avatar19' | 'avatar/icn_avatar2' | 'avatar/icn_avatar20' | 'avatar/icn_avatar21' | 'avatar/icn_avatar22' | 'avatar/icn_avatar23' | 'avatar/icn_avatar3' | 'avatar/icn_avatar4' | 'avatar/icn_avatar5' | 'avatar/icn_avatar6' | 'avatar/icn_avatar7' | 'avatar/icn_avatar8' | 'avatar/icn_avatar9' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'battery-charging' | 'battery' | 'bell-fill' | 'bell-plus' | 'bell-slash' | 'bell' | 'binoculars' | 'book-doc' | 'book' | 'bookmark' | 'broadcast' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'buildings' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'call' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'card-checklist' | 'card-list' | 'card-text' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-left-text' | 'chat-right-text' | 'chat-square-quote' | 'check-circle-fill' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'click-hesitation' | 'click-rage' | 'clipboard-check' | 'clipboard-list-check' | 'clock-history' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection-play' | 'collection' | 'color/apple' | 'color/chrome' | 'color/de' | 'color/edge' | 'color/fedora' | 'color/firefox' | 'color/fr' | 'color/gb' | 'color/in' | 'color/microsoft' | 'color/opera' | 'color/safari' | 'color/ubuntu' | 'color/us' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-2-back' | 'credit-card-front' | 'cross' | 'cubes' | 'cursor-trash' | 'dash' | 'dashboard-icn' | 'db-icons/icn-card-clickMap' | 'db-icons/icn-card-errors' | 'db-icons/icn-card-funnel' | 'db-icons/icn-card-funnels' | 'db-icons/icn-card-insights' | 'db-icons/icn-card-library' | 'db-icons/icn-card-mapchart' | 'db-icons/icn-card-pathAnalysis' | 'db-icons/icn-card-performance' | 'db-icons/icn-card-resources' | 'db-icons/icn-card-table' | 'db-icons/icn-card-timeseries' | 'db-icons/icn-card-webVitals' | 'desktop' | 'device' | 'diagram-3' | 'dice-3' | 'dizzy' | 'door-closed' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'emoji-dizzy' | 'enter' | 'envelope-check' | 'envelope-paper' | 'envelope-x' | 'envelope' | 'errors-icon' | 'event/click' | 'event/click_hesitation' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/input_hesitation' | 'event/link' | 'event/location' | 'event/mouse_thrashing' | 'event/resize' | 'event/view' | 'exclamation-circle-fill' | 'exclamation-circle' | 'exclamation-triangle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'fflag-multi' | 'fflag-single' | 'file-bar-graph' | 'file-code' | 'file-medical-alt' | 'file-pdf' | 'file' | 'files' | 'filetype-js' | 'filetype-pdf' | '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/tag-element' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'folder-plus' | 'folder2' | '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' | 'gear-fill' | 'gear' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-1x2' | 'grid-3x3' | 'grid-check' | 'grid-horizontal' | 'grid' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'ic-errors' | 'ic-network' | 'ic-rage' | 'ic-resources' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'input-hesitation' | '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/teams-white' | 'integrations/teams' | 'integrations/vuejs' | 'integrations/zustand' | 'journal-code' | 'key' | 'keyboard' | 'layer-group' | 'layers-half' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-arrow' | 'list-ul' | 'list' | 'lock-alt' | 'low-disc-space' | 'magic' | 'map-marker-alt' | 'memory-ios' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'mouse-pointer-click' | 'network' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'no-recordings' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-circle-fill' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'people' | 'percent' | 'performance-icon' | 'person-border' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-bold' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plug' | 'plus-circle' | 'plus-lg' | 'plus' | 'pointer-sessions-search' | 'prev1' | 'pulse' | 'puzzle-piece' | 'puzzle' | 'question-circle' | 'question-lg' | 'quote-left' | 'quote-right' | 'quotes' | 'record-btn' | 'record-circle-fill' | 'record-circle' | 'record2' | 'redo-back' | 'redo' | 'redux' | 'remote-control' | 'replay-10' | 'resources-icon' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'side_menu_closed' | 'side_menu_open' | 'signpost-split' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slack' | 'slash-circle' | 'sleep' | 'sliders' | 'social/slack' | 'social/trello' | 'sparkles' | 'speedometer2' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stickies' | 'stop-record-circle' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'terminal' | 'text-paragraph' | 'thermometer-sun' | 'toggles' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'user-switch' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'web-vitals' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; +export type IconNames = 'activity' | 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-bar-left' | 'arrow-clockwise' | 'arrow-counterclockwise' | 'arrow-down-short' | 'arrow-down-up' | 'arrow-down' | 'arrow-repeat' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up-short' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_avatar1' | 'avatar/icn_avatar10' | 'avatar/icn_avatar11' | 'avatar/icn_avatar12' | 'avatar/icn_avatar13' | 'avatar/icn_avatar14' | 'avatar/icn_avatar15' | 'avatar/icn_avatar16' | 'avatar/icn_avatar17' | 'avatar/icn_avatar18' | 'avatar/icn_avatar19' | 'avatar/icn_avatar2' | 'avatar/icn_avatar20' | 'avatar/icn_avatar21' | 'avatar/icn_avatar22' | 'avatar/icn_avatar23' | 'avatar/icn_avatar3' | 'avatar/icn_avatar4' | 'avatar/icn_avatar5' | 'avatar/icn_avatar6' | 'avatar/icn_avatar7' | 'avatar/icn_avatar8' | 'avatar/icn_avatar9' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'battery-charging' | 'battery' | 'bell-fill' | 'bell-plus' | 'bell-slash' | 'bell' | 'binoculars' | 'book-doc' | 'book' | 'bookmark' | 'broadcast' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'buildings' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'call' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'card-checklist' | 'card-list' | 'card-text' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-left-text' | 'chat-right-text' | 'chat-square-quote' | 'check-circle-fill' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'click-hesitation' | 'click-rage' | 'clipboard-check' | 'clipboard-list-check' | 'clock-history' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection-play' | 'collection' | 'color/apple' | 'color/browser/Tor' | 'color/browser/applebot' | 'color/browser/chrome' | 'color/browser/chrome_mobile' | 'color/browser/chrome_mobile_ios' | 'color/browser/duck_duck_go' | 'color/browser/duckduckgo_mobile' | 'color/browser/edge' | 'color/browser/edge_mobile' | 'color/browser/facebook' | 'color/browser/firefox' | 'color/browser/firefox_ios' | 'color/browser/firefox_mobile' | 'color/browser/google' | 'color/browser/googlebot' | 'color/browser/huawei_browser' | 'color/browser/internet_explorer' | 'color/browser/miui_browser' | 'color/browser/mobile_safari' | 'color/browser/mobile_safari_ui' | 'color/browser/opera' | 'color/browser/safari' | 'color/browser/samsung_internet' | 'color/browser/uc_browser' | 'color/browser/unknown' | 'color/browser/whale' | 'color/browser/yandex_browser' | 'color/chrome' | 'color/country/de' | 'color/country/fr' | 'color/country/gb' | 'color/country/in' | 'color/country/us' | 'color/de' | 'color/device/desktop' | 'color/device/mobile' | 'color/device/other_phone' | 'color/device/tablet' | 'color/device/unkown' | 'color/edge' | 'color/fedora' | 'color/firefox' | 'color/fr' | 'color/gb' | 'color/in' | 'color/microsoft' | 'color/opera' | 'color/os/android' | 'color/os/apple' | 'color/os/blackberry' | 'color/os/chrome_os' | 'color/os/elementary' | 'color/os/fedora' | 'color/os/freebsd' | 'color/os/gnome' | 'color/os/ios' | 'color/os/linux' | 'color/os/linux_mint' | 'color/os/macos' | 'color/os/microsoft' | 'color/os/ubuntu' | 'color/os/unkown' | 'color/safari' | 'color/ubuntu' | 'color/us' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-2-back' | 'credit-card-front' | 'cross' | 'cubes' | 'cursor-trash' | 'dash' | 'dashboard-icn' | 'db-icons/icn-card-clickMap' | 'db-icons/icn-card-errors' | 'db-icons/icn-card-funnel' | 'db-icons/icn-card-funnels' | 'db-icons/icn-card-insights' | 'db-icons/icn-card-library' | 'db-icons/icn-card-mapchart' | 'db-icons/icn-card-pathAnalysis' | 'db-icons/icn-card-performance' | 'db-icons/icn-card-resources' | 'db-icons/icn-card-table' | 'db-icons/icn-card-timeseries' | 'db-icons/icn-card-webVitals' | 'desktop' | 'device' | 'diagram-3' | 'dice-3' | 'dizzy' | 'door-closed' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'emoji-dizzy' | 'enter' | 'envelope-check' | 'envelope-paper' | 'envelope-x' | 'envelope' | 'errors-icon' | 'event/click' | 'event/click_hesitation' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/input_hesitation' | 'event/link' | 'event/location' | 'event/mouse_thrashing' | 'event/resize' | 'event/view' | 'exclamation-circle-fill' | 'exclamation-circle' | 'exclamation-triangle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'fflag-multi' | 'fflag-single' | 'file-bar-graph' | 'file-code' | 'file-medical-alt' | 'file-pdf' | 'file' | 'files' | 'filetype-js' | 'filetype-pdf' | '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/tag-element' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'folder-plus' | 'folder2' | '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' | 'gear-fill' | 'gear' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-1x2' | 'grid-3x3' | 'grid-check' | 'grid-horizontal' | 'grid' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'ic-errors' | 'ic-network' | 'ic-rage' | 'ic-resources' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'input-hesitation' | '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/teams-white' | 'integrations/teams' | 'integrations/vuejs' | 'integrations/zustand' | 'journal-code' | 'key' | 'keyboard' | 'layer-group' | 'layers-half' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-arrow' | 'list-ul' | 'list' | 'lock-alt' | 'low-disc-space' | 'magic' | 'map-marker-alt' | 'memory-ios' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'mouse-pointer-click' | 'network' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'no-recordings' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-circle-fill' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'people' | 'percent' | 'performance-icon' | 'person-border' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-bold' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plug' | 'plus-circle' | 'plus-lg' | 'plus' | 'pointer-sessions-search' | 'prev1' | 'pulse' | 'puzzle-piece' | 'puzzle' | 'question-circle' | 'question-lg' | 'quote-left' | 'quote-right' | 'quotes' | 'record-btn' | 'record-circle-fill' | 'record-circle' | 'record2' | 'redo-back' | 'redo' | 'redux' | 'remote-control' | 'replay-10' | 'resources-icon' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'side_menu_closed' | 'side_menu_open' | 'signpost-split' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slack' | 'slash-circle' | 'sleep' | 'sliders' | 'social/slack' | 'social/trello' | 'sparkles' | 'speedometer2' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stickies' | 'stop-record-circle' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'terminal' | 'text-paragraph' | 'thermometer-sun' | 'toggles' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'user-switch' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'web-vitals' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; interface Props { name: IconNames; @@ -847,12 +899,123 @@ const SVG = (props: Props) => { // case 'color/apple': case 'color/apple': return ; + // case 'color/browser/Tor': + case 'color/browser/Tor': return ; + + // case 'color/browser/applebot': + case 'color/browser/applebot': return ; + + // case 'color/browser/chrome': + case 'color/browser/chrome': return ; + + // case 'color/browser/chrome_mobile': + case 'color/browser/chrome_mobile': return ; + + // case 'color/browser/chrome_mobile_ios': + case 'color/browser/chrome_mobile_ios': return ; + + // case 'color/browser/duck_duck_go': + case 'color/browser/duck_duck_go': return ; + + // case 'color/browser/duckduckgo_mobile': + case 'color/browser/duckduckgo_mobile': return ; + + // case 'color/browser/edge': + case 'color/browser/edge': return ; + + // case 'color/browser/edge_mobile': + case 'color/browser/edge_mobile': return ; + + // case 'color/browser/facebook': + case 'color/browser/facebook': return ; + + // case 'color/browser/firefox': + case 'color/browser/firefox': return ; + + // case 'color/browser/firefox_ios': + case 'color/browser/firefox_ios': return ; + + // case 'color/browser/firefox_mobile': + case 'color/browser/firefox_mobile': return ; + + // case 'color/browser/google': + case 'color/browser/google': return ; + + // case 'color/browser/googlebot': + case 'color/browser/googlebot': return ; + + // case 'color/browser/huawei_browser': + case 'color/browser/huawei_browser': return ; + + // case 'color/browser/internet_explorer': + case 'color/browser/internet_explorer': return ; + + // case 'color/browser/miui_browser': + case 'color/browser/miui_browser': return ; + + // case 'color/browser/mobile_safari': + case 'color/browser/mobile_safari': return ; + + // case 'color/browser/mobile_safari_ui': + case 'color/browser/mobile_safari_ui': return ; + + // case 'color/browser/opera': + case 'color/browser/opera': return ; + + // case 'color/browser/safari': + case 'color/browser/safari': return ; + + // case 'color/browser/samsung_internet': + case 'color/browser/samsung_internet': return ; + + // case 'color/browser/uc_browser': + case 'color/browser/uc_browser': return ; + + // case 'color/browser/unknown': + case 'color/browser/unknown': return ; + + // case 'color/browser/whale': + case 'color/browser/whale': return ; + + // case 'color/browser/yandex_browser': + case 'color/browser/yandex_browser': return ; + // case 'color/chrome': case 'color/chrome': return ; + // case 'color/country/de': + case 'color/country/de': return ; + + // case 'color/country/fr': + case 'color/country/fr': return ; + + // case 'color/country/gb': + case 'color/country/gb': return ; + + // case 'color/country/in': + case 'color/country/in': return ; + + // case 'color/country/us': + case 'color/country/us': return ; + // case 'color/de': case 'color/de': return ; + // case 'color/device/desktop': + case 'color/device/desktop': return ; + + // case 'color/device/mobile': + case 'color/device/mobile': return ; + + // case 'color/device/other_phone': + case 'color/device/other_phone': return ; + + // case 'color/device/tablet': + case 'color/device/tablet': return ; + + // case 'color/device/unkown': + case 'color/device/unkown': return ; + // case 'color/edge': case 'color/edge': return ; @@ -877,6 +1040,51 @@ const SVG = (props: Props) => { // case 'color/opera': case 'color/opera': return ; + // case 'color/os/android': + case 'color/os/android': return ; + + // case 'color/os/apple': + case 'color/os/apple': return ; + + // case 'color/os/blackberry': + case 'color/os/blackberry': return ; + + // case 'color/os/chrome_os': + case 'color/os/chrome_os': return ; + + // case 'color/os/elementary': + case 'color/os/elementary': return ; + + // case 'color/os/fedora': + case 'color/os/fedora': return ; + + // case 'color/os/freebsd': + case 'color/os/freebsd': return ; + + // case 'color/os/gnome': + case 'color/os/gnome': return ; + + // case 'color/os/ios': + case 'color/os/ios': return ; + + // case 'color/os/linux': + case 'color/os/linux': return ; + + // case 'color/os/linux_mint': + case 'color/os/linux_mint': return ; + + // case 'color/os/macos': + case 'color/os/macos': return ; + + // case 'color/os/microsoft': + case 'color/os/microsoft': return ; + + // case 'color/os/ubuntu': + case 'color/os/ubuntu': return ; + + // case 'color/os/unkown': + case 'color/os/unkown': return ; + // case 'color/safari': case 'color/safari': return ; diff --git a/frontend/app/constants/countries.js b/frontend/app/constants/countries.js index e7a9024c2..0aadfbd8b 100644 --- a/frontend/app/constants/countries.js +++ b/frontend/app/constants/countries.js @@ -12,7 +12,7 @@ function sortObjectValuesAlphabetically(obj) { return sortedObj; } -const countries = { +export const countries = { AC: 'Ascension Island', AD: 'Andorra', AE: 'United Arab Emirates', @@ -295,4 +295,4 @@ const countries = { ZW: 'Zimbabwe', }; -export default sortObjectValuesAlphabetically(countries) \ No newline at end of file +export default sortObjectValuesAlphabetically(countries) diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 691016047..1a0456d55 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -162,18 +162,17 @@ export default class DashboardStore { }); } - fetch(dashboardId: string): Promise { + async fetch(dashboardId: string): Promise { this.setFetchingDashboard(true); - return dashboardService - .getDashboard(dashboardId) - .then((response) => { - this.selectedDashboard?.update({ - widgets: new Dashboard().fromJson(response).widgets, - }); - }) - .finally(() => { - this.setFetchingDashboard(false); + try { + const response = await dashboardService + .getDashboard(dashboardId); + this.selectedDashboard?.update({ + widgets: new Dashboard().fromJson(response).widgets, }); + } finally { + this.setFetchingDashboard(false); + } } setFetchingDashboard(value: boolean) { diff --git a/frontend/app/mstore/types/IconProvider.tsx b/frontend/app/mstore/types/IconProvider.tsx new file mode 100644 index 000000000..a4654633d --- /dev/null +++ b/frontend/app/mstore/types/IconProvider.tsx @@ -0,0 +1,115 @@ +import {Icon} from "UI"; +import React from "react"; +import * as Flags from "country-flag-icons/react/3x2"; + +interface IconProvider { + getIcon(name: string): React.ReactNode; +} + +class BrowserIconProvider implements IconProvider { + getIcon(name: string): React.ReactNode { + const s = name.toLowerCase(); + let icon = 'color/browser/unknown' + if (s.includes('chrome')) { + icon = 'color/browser/chrome'; + } else if (s.includes('firefox')) { + icon = 'color/browser/firefox'; + } else if (s.includes('safari')) { + icon = 'color/browser/safari'; + } else if (s.includes('edge')) { + icon = 'color/browser/edge'; + } else if (s.includes('opera')) { + icon = 'color/browser/opera'; + } else if (s.includes('ie')) { + icon = 'color/browser/ie'; + } + + return + } +} + +class CountryIconProvider implements IconProvider { + getIcon(name: string): React.ReactNode { + const s = name.toUpperCase(); + if (Flags[s as keyof typeof Flags]) { + const FlagComponent = Flags[s as keyof typeof Flags]; + return + } + + return + } +} + +class IssueIconProvider implements IconProvider { + getIcon(name: string): React.ReactNode { + const s = name.toLowerCase(); + // let icon = 'event/' + s; // TODO use this line + let icon = 'event/clickrage'; + + + if (s.includes('dead_click')) { + icon = 'event/clickrage'; + } else if (s.includes('click_rage')) { + icon = 'event/clickrage'; + } else if (s.includes('mouse_thrashing')) { + icon = 'event/clickrage'; + } + return + } +} + +class UrlIconProvider implements IconProvider { + getIcon(name: string): React.ReactNode { + return + } +} + +class DeviceIconProvider implements IconProvider { + getIcon(name: string): React.ReactNode { + const s = name.toLowerCase(); + let icon = 'color/device/desktop' + if (s.includes('desktop')) { + icon = 'color/device/desktop'; + } else if ( + s.includes('mobile') || s.includes('iphone') || s === 'k' || s.includes('android') || + s.includes('smartphone') || s.includes('phone') || s.includes('moto') + ) { + icon = 'color/device/mobile'; + } else if (s.includes('tablet')) { + icon = 'color/device/tablet'; + } else { + icon = 'color/device/desktop'; + } + + return + } +} + +class OsIconProvider implements IconProvider { + getIcon(name: string): React.ReactNode { + const s = name.toLowerCase(); + if (s.includes('windows')) { + return 'os/windows'; + } else if (s.includes('mac')) { + return 'os/mac'; + } else if (s.includes('linux')) { + return 'os/linux'; + } else { + return 'os/unknown'; + } + } +} + +export { + BrowserIconProvider, + CountryIconProvider, + IssueIconProvider, + UrlIconProvider, + DeviceIconProvider, + OsIconProvider +}; +export type {IconProvider}; + diff --git a/frontend/app/mstore/types/sessionsCardData.ts b/frontend/app/mstore/types/sessionsCardData.ts new file mode 100644 index 000000000..23c8b2306 --- /dev/null +++ b/frontend/app/mstore/types/sessionsCardData.ts @@ -0,0 +1,96 @@ +import {numberWithCommas} from "App/utils"; +import {countries} from "App/constants"; +import { + BrowserIconProvider, + CountryIconProvider, DeviceIconProvider, + IconProvider, + IssueIconProvider, OsIconProvider, + UrlIconProvider +} from "./IconProvider"; + +interface NameFormatter { + format(name: string): string; +} + +class BaseFormatter implements NameFormatter { + format(name: string): string { + return name.replace(/_/g, ' ').replace(/\w\S*/g, (w) => (w.replace(/^\w/, (c) => c.toUpperCase()))).trim(); + } +} + +class BrowserFormatter extends BaseFormatter { + format(name: string): string { + return super.format(name); + } +} + +class CountryFormatter extends BaseFormatter { + format(name: string): string { + if (name === 'UN') { + return 'Unknown Country'; + } + return countries[name.toUpperCase()] || name; + } +} + +class IssueFormatter extends BaseFormatter { + format(name: string): string { + return super.format(name); + } +} + +export class SessionsByRow { + name: string; + sessionCount: number; + progress: number; + icon: React.ReactNode; + + fromJson(json: any, totalSessions: number, metricType: string) { + const {nameFormatter, iconProvider} = this.getFormatters(metricType); + this.name = nameFormatter.format(json.name) || 'Unidentified'; + this.sessionCount = numberWithCommas(json.sessionCount); + this.progress = Math.round((json.sessionCount / totalSessions) * 100); + this.icon = iconProvider.getIcon(json.name); + return this; + } + + private getFormatters(metricType: string): { nameFormatter: NameFormatter; iconProvider: IconProvider } { + switch (metricType) { + case 'userBrowser': + return {nameFormatter: new BrowserFormatter(), iconProvider: new BrowserIconProvider()}; + case 'userCountry': + return {nameFormatter: new CountryFormatter(), iconProvider: new CountryIconProvider()}; + case 'issue': + return {nameFormatter: new IssueFormatter(), iconProvider: new IssueIconProvider()}; + case 'location': + return {nameFormatter: new BaseFormatter(), iconProvider: new UrlIconProvider()}; + case 'userDevice': + return {nameFormatter: new BaseFormatter(), iconProvider: new DeviceIconProvider()}; + case 'platform': + return {nameFormatter: new BaseFormatter(), iconProvider: new OsIconProvider()}; + default: + return {nameFormatter: new BaseFormatter(), iconProvider: new DefaultIconProvider()}; + } + } +} + +class DefaultIconProvider implements IconProvider { + getIcon(name: string): string { + return 'ic-user-path'; + } +} + +// Usage example +// const data = [ +// { +// values: [ +// {name: 'chrome', sessionCount: 120}, +// {name: 'firefox', sessionCount: 80}, +// {name: 'safari', sessionCount: 50}, +// ] +// } +// ]; +// const totalSessions = 1000; +// const metricOf = 'browser'; +// +// data[0]['values'] = data[0]['values'].map((s: any) => new SessionsByRow().fromJson(s, totalSessions, metricOf)); diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 3ec76a5d6..283b895d6 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -15,6 +15,9 @@ import FilterItem from './filterItem'; import {filtersMap} from 'Types/filter/newFilter'; import Issue from '../types/issue'; import {durationFormatted} from 'App/date'; +import React from "react"; +import {countries} from "App/constants/countries"; +import {SessionsByRow} from "./sessionsCardData"; export class InsightIssue { icon: string; @@ -273,38 +276,11 @@ export default class Widget { const _data: any = {...data}; if (this.metricType === USER_PATH) { - // Ensure nodes have unique IDs const _data = processData(data); - - // const nodes = data.nodes.map(node => ({ - // ...node, - // avgTimeFromPrevious: node.avgTimeFromPrevious ? durationFormatted(node.avgTimeFromPrevious) : null, - // idd: node.idd || Math.random().toString(36).substring(7), - // })); - // - // // Ensure links have unique IDs and use node IDs - // const links = data.links.map(link => ({ - // ...link, - // value: Math.round(link.value), - // id: link.id || Math.random().toString(36).substring(7), - // })); - // - // const _data = { nodes, links }; - - // _data['nodes'] = data.nodes.map((s: any) => ({ - // ...s, - // avgTimeFromPrevious: s.avgTimeFromPrevious ? durationFormatted(s.avgTimeFromPrevious) : null, - // idd: Math.random().toString(36).substring(7), - // })); - // _data['links'] = data.links.map((s: any) => ({ - // ...s, - // value: Math.round(s.value), - // id: Math.random().toString(36).substring(7), - // })); - Object.assign(this.data, _data); return _data; } + if (this.metricOf === FilterKey.ERRORS) { _data['errors'] = data.errors.map((s: any) => new Error().fromJSON(s)); } else if (this.metricType === INSIGHTS) { @@ -316,6 +292,11 @@ export default class Widget { ); } else if (this.metricType === FUNNEL) { _data.funnel = new Funnel().fromJSON(_data); + } else if (this.metricType === TABLE) { + const totalSessions = data[0]['totalSessions']; + _data[0]['values'] = data[0]['values'].map((s: any) => new SessionsByRow().fromJson(s, totalSessions, this.metricOf)); + + console.log('_data[\'values\']', _data['values']) } else { if (data.hasOwnProperty('chart')) { _data['value'] = data.value; @@ -450,7 +431,10 @@ interface Data { const generateUniqueId = (): string => Math.random().toString(36).substring(2, 15); -const processData = (data: Data): { nodes: Node[], links: { source: number, target: number, value: number, id: string }[] } => { +const processData = (data: Data): { + nodes: Node[], + links: { source: number, target: number, value: number, id: string }[] +} => { // Ensure nodes have unique IDs const nodes = data.nodes.map(node => ({ ...node, @@ -479,5 +463,5 @@ const processData = (data: Data): { nodes: Node[], links: { source: number, targ return aIndex - bIndex; }); - return { nodes: sortedNodes, links }; + return {nodes: sortedNodes, links}; }; diff --git a/frontend/app/svg/ca-no-dashboards.svg b/frontend/app/svg/ca-no-dashboards.svg index 7eedeff65..4370b3f8e 100644 --- a/frontend/app/svg/ca-no-dashboards.svg +++ b/frontend/app/svg/ca-no-dashboards.svg @@ -1,52 +1,301 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/color/browser/Tor.svg b/frontend/app/svg/icons/color/browser/Tor.svg new file mode 100644 index 000000000..f475a8f59 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/Tor.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/applebot.svg b/frontend/app/svg/icons/color/browser/applebot.svg new file mode 100644 index 000000000..2da2dcdcc --- /dev/null +++ b/frontend/app/svg/icons/color/browser/applebot.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/chrome.svg b/frontend/app/svg/icons/color/browser/chrome.svg new file mode 100644 index 000000000..76fcb91f4 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/chrome.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/chrome_mobile.svg b/frontend/app/svg/icons/color/browser/chrome_mobile.svg new file mode 100644 index 000000000..9434a8ac6 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/chrome_mobile.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/chrome_mobile_ios.svg b/frontend/app/svg/icons/color/browser/chrome_mobile_ios.svg new file mode 100644 index 000000000..1f7ccfcec --- /dev/null +++ b/frontend/app/svg/icons/color/browser/chrome_mobile_ios.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/duck_duck_go.svg b/frontend/app/svg/icons/color/browser/duck_duck_go.svg new file mode 100644 index 000000000..dac9a189c --- /dev/null +++ b/frontend/app/svg/icons/color/browser/duck_duck_go.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/duckduckgo_mobile.svg b/frontend/app/svg/icons/color/browser/duckduckgo_mobile.svg new file mode 100644 index 000000000..901934503 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/duckduckgo_mobile.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/edge.svg b/frontend/app/svg/icons/color/browser/edge.svg new file mode 100644 index 000000000..2eeed3b9f --- /dev/null +++ b/frontend/app/svg/icons/color/browser/edge.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/edge_mobile.svg b/frontend/app/svg/icons/color/browser/edge_mobile.svg new file mode 100644 index 000000000..32a745aa3 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/edge_mobile.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/facebook.svg b/frontend/app/svg/icons/color/browser/facebook.svg new file mode 100644 index 000000000..adc02877c --- /dev/null +++ b/frontend/app/svg/icons/color/browser/facebook.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/firefox.svg b/frontend/app/svg/icons/color/browser/firefox.svg new file mode 100644 index 000000000..798e52d15 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/firefox.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/firefox_ios.svg b/frontend/app/svg/icons/color/browser/firefox_ios.svg new file mode 100644 index 000000000..e07aa7054 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/firefox_ios.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/firefox_mobile.svg b/frontend/app/svg/icons/color/browser/firefox_mobile.svg new file mode 100644 index 000000000..58eac0539 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/firefox_mobile.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/google.svg b/frontend/app/svg/icons/color/browser/google.svg new file mode 100644 index 000000000..e22a64477 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/google.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/googlebot.svg b/frontend/app/svg/icons/color/browser/googlebot.svg new file mode 100644 index 000000000..01f272bd6 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/googlebot.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/huawei_browser.svg b/frontend/app/svg/icons/color/browser/huawei_browser.svg new file mode 100644 index 000000000..4c05b3373 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/huawei_browser.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/internet_explorer.svg b/frontend/app/svg/icons/color/browser/internet_explorer.svg new file mode 100644 index 000000000..4db5365de --- /dev/null +++ b/frontend/app/svg/icons/color/browser/internet_explorer.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/miui_browser.svg b/frontend/app/svg/icons/color/browser/miui_browser.svg new file mode 100644 index 000000000..e151f2afe --- /dev/null +++ b/frontend/app/svg/icons/color/browser/miui_browser.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/mobile_safari.svg b/frontend/app/svg/icons/color/browser/mobile_safari.svg new file mode 100644 index 000000000..3821ec96b --- /dev/null +++ b/frontend/app/svg/icons/color/browser/mobile_safari.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/mobile_safari_ui.svg b/frontend/app/svg/icons/color/browser/mobile_safari_ui.svg new file mode 100644 index 000000000..33f36c5e7 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/mobile_safari_ui.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/opera.svg b/frontend/app/svg/icons/color/browser/opera.svg new file mode 100644 index 000000000..406c9595c --- /dev/null +++ b/frontend/app/svg/icons/color/browser/opera.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/safari.svg b/frontend/app/svg/icons/color/browser/safari.svg new file mode 100644 index 000000000..84d75b8e8 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/safari.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/samsung_internet.svg b/frontend/app/svg/icons/color/browser/samsung_internet.svg new file mode 100644 index 000000000..014fd6617 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/samsung_internet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/uc_browser.svg b/frontend/app/svg/icons/color/browser/uc_browser.svg new file mode 100644 index 000000000..89e46e607 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/uc_browser.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/unknown.svg b/frontend/app/svg/icons/color/browser/unknown.svg new file mode 100644 index 000000000..e10752b03 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/unknown.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/whale.svg b/frontend/app/svg/icons/color/browser/whale.svg new file mode 100644 index 000000000..895a997ef --- /dev/null +++ b/frontend/app/svg/icons/color/browser/whale.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/browser/yandex_browser.svg b/frontend/app/svg/icons/color/browser/yandex_browser.svg new file mode 100644 index 000000000..b3eda7aa8 --- /dev/null +++ b/frontend/app/svg/icons/color/browser/yandex_browser.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/country/de.svg b/frontend/app/svg/icons/color/country/de.svg new file mode 100644 index 000000000..c22cf3eca --- /dev/null +++ b/frontend/app/svg/icons/color/country/de.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/color/country/fr.svg b/frontend/app/svg/icons/color/country/fr.svg new file mode 100644 index 000000000..af130683d --- /dev/null +++ b/frontend/app/svg/icons/color/country/fr.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/color/country/gb.svg b/frontend/app/svg/icons/color/country/gb.svg new file mode 100644 index 000000000..5fe9fa63e --- /dev/null +++ b/frontend/app/svg/icons/color/country/gb.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/color/country/in.svg b/frontend/app/svg/icons/color/country/in.svg new file mode 100644 index 000000000..1a17c7e3d --- /dev/null +++ b/frontend/app/svg/icons/color/country/in.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/color/country/us.svg b/frontend/app/svg/icons/color/country/us.svg new file mode 100644 index 000000000..1e6ffa7d8 --- /dev/null +++ b/frontend/app/svg/icons/color/country/us.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/app/svg/icons/color/device/desktop.svg b/frontend/app/svg/icons/color/device/desktop.svg new file mode 100644 index 000000000..30cf2f25c --- /dev/null +++ b/frontend/app/svg/icons/color/device/desktop.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/device/mobile.svg b/frontend/app/svg/icons/color/device/mobile.svg new file mode 100644 index 000000000..9a95c74cc --- /dev/null +++ b/frontend/app/svg/icons/color/device/mobile.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/device/other_phone.svg b/frontend/app/svg/icons/color/device/other_phone.svg new file mode 100644 index 000000000..dbcd205ba --- /dev/null +++ b/frontend/app/svg/icons/color/device/other_phone.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/device/tablet.svg b/frontend/app/svg/icons/color/device/tablet.svg new file mode 100644 index 000000000..ba84f3267 --- /dev/null +++ b/frontend/app/svg/icons/color/device/tablet.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/device/unkown.svg b/frontend/app/svg/icons/color/device/unkown.svg new file mode 100644 index 000000000..dc3acfbe8 --- /dev/null +++ b/frontend/app/svg/icons/color/device/unkown.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/android.svg b/frontend/app/svg/icons/color/os/android.svg new file mode 100644 index 000000000..05ca9f292 --- /dev/null +++ b/frontend/app/svg/icons/color/os/android.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/apple.svg b/frontend/app/svg/icons/color/os/apple.svg new file mode 100644 index 000000000..950248697 --- /dev/null +++ b/frontend/app/svg/icons/color/os/apple.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/blackberry.svg b/frontend/app/svg/icons/color/os/blackberry.svg new file mode 100644 index 000000000..7cf0cf145 --- /dev/null +++ b/frontend/app/svg/icons/color/os/blackberry.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/chrome_os.svg b/frontend/app/svg/icons/color/os/chrome_os.svg new file mode 100644 index 000000000..30a38bcbb --- /dev/null +++ b/frontend/app/svg/icons/color/os/chrome_os.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/elementary.svg b/frontend/app/svg/icons/color/os/elementary.svg new file mode 100644 index 000000000..1a7c3cd4f --- /dev/null +++ b/frontend/app/svg/icons/color/os/elementary.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/fedora.svg b/frontend/app/svg/icons/color/os/fedora.svg new file mode 100644 index 000000000..843063a38 --- /dev/null +++ b/frontend/app/svg/icons/color/os/fedora.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/freebsd.svg b/frontend/app/svg/icons/color/os/freebsd.svg new file mode 100644 index 000000000..7703e7423 --- /dev/null +++ b/frontend/app/svg/icons/color/os/freebsd.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/gnome.svg b/frontend/app/svg/icons/color/os/gnome.svg new file mode 100644 index 000000000..aff8a3850 --- /dev/null +++ b/frontend/app/svg/icons/color/os/gnome.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/ios.svg b/frontend/app/svg/icons/color/os/ios.svg new file mode 100644 index 000000000..e2e472497 --- /dev/null +++ b/frontend/app/svg/icons/color/os/ios.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/linux.svg b/frontend/app/svg/icons/color/os/linux.svg new file mode 100644 index 000000000..67d8c2680 --- /dev/null +++ b/frontend/app/svg/icons/color/os/linux.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/linux_mint.svg b/frontend/app/svg/icons/color/os/linux_mint.svg new file mode 100644 index 000000000..c2d15f346 --- /dev/null +++ b/frontend/app/svg/icons/color/os/linux_mint.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/macos.svg b/frontend/app/svg/icons/color/os/macos.svg new file mode 100644 index 000000000..32eac2230 --- /dev/null +++ b/frontend/app/svg/icons/color/os/macos.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/microsoft.svg b/frontend/app/svg/icons/color/os/microsoft.svg new file mode 100644 index 000000000..419ccfa0f --- /dev/null +++ b/frontend/app/svg/icons/color/os/microsoft.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/ubuntu.svg b/frontend/app/svg/icons/color/os/ubuntu.svg new file mode 100644 index 000000000..a9043bca0 --- /dev/null +++ b/frontend/app/svg/icons/color/os/ubuntu.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/color/os/unkown.svg b/frontend/app/svg/icons/color/os/unkown.svg new file mode 100644 index 000000000..dc3acfbe8 --- /dev/null +++ b/frontend/app/svg/icons/color/os/unkown.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/frontend/app/utils/index.ts b/frontend/app/utils/index.ts index 89e4a49f6..f3e76e5af 100644 --- a/frontend/app/utils/index.ts +++ b/frontend/app/utils/index.ts @@ -43,7 +43,15 @@ export const getUniqueFilter = (keys) => (item, i, list) => export const numberWithCommas = (x) => (x ? x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : 0); -export const numberCompact = (x) => (x >= 1000 ? x / 1000 + 'k' : x); +export const numberCompact = (x) => { + if (x < 1000) { + return x; + } + if (x < 1000000) { + return `${Math.floor(x / 1000)}K`; + } + return `${Math.floor(x / 1000000)}M`; +} export const cutURL = (url, prefix = '.../') => `${prefix + url.split('/').slice(3).join('/')}`; @@ -479,4 +487,4 @@ export const checkParam = (paramName: string, storageKey?: string, search?: stri return existsAndTrue; }; -export const isValidUrl = (url) => /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/.test(url); \ No newline at end of file +export const isValidUrl = (url) => /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/.test(url); diff --git a/frontend/package.json b/frontend/package.json index d147175b1..5fb124a8a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -32,7 +32,7 @@ "@sentry/browser": "^5.21.1", "@svg-maps/world": "^1.0.1", "@svgr/webpack": "^6.2.1", - "antd": "^5.9.4", + "antd": "^5.18.3", "chroma-js": "^2.4.2", "classnames": "^2.3.1", "copy-to-clipboard": "^3.3.1", @@ -48,7 +48,7 @@ "jshint": "^2.11.1", "jspdf": "^2.5.1", "jsx-runtime": "^1.2.0", - "lucide-react": "^0.363.0", + "lucide-react": "^0.396.0", "luxon": "^1.24.1", "microdiff": "^1.4.0", "mobx": "^6.3.8", @@ -78,7 +78,7 @@ "react-toastify": "^9.1.1", "react-virtualized": "^9.22.3", "react18-json-view": "^0.2.8", - "recharts": "^2.12.6", + "recharts": "^2.12.7", "redux": "^4.0.5", "redux-immutable": "^4.0.0", "redux-thunk": "^2.3.0", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 7eaa2109f..692a0b265 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -38,9 +38,9 @@ __metadata: languageName: node linkType: hard -"@ant-design/cssinjs@npm:^1.18.5": - version: 1.19.1 - resolution: "@ant-design/cssinjs@npm:1.19.1" +"@ant-design/cssinjs@npm:^1.21.0": + version: 1.21.0 + resolution: "@ant-design/cssinjs@npm:1.21.0" dependencies: "@babel/runtime": ^7.11.1 "@emotion/hash": ^0.8.0 @@ -52,7 +52,7 @@ __metadata: peerDependencies: react: ">=16.0.0" react-dom: ">=16.0.0" - checksum: dab835d7295c180b3329e725081a955cc210f67546c0da4697223ea4e715299e4a39577085a324e669cc201523cc89d24e707a50428f48bc842917065f06cf17 + checksum: ffc384e369e2d0610ef322adcf3eba9fe785c4cc065b2bffbf6973abebf72f15ea194d7ffbb94440f363ee7c105388c6ca6b98aff3979f31ee7a49bd2600e986 languageName: node linkType: hard @@ -63,7 +63,7 @@ __metadata: languageName: node linkType: hard -"@ant-design/icons@npm:^5.2.5, @ant-design/icons@npm:^5.3.6": +"@ant-design/icons@npm:^5.2.5": version: 5.3.6 resolution: "@ant-design/icons@npm:5.3.6" dependencies: @@ -79,6 +79,22 @@ __metadata: languageName: node linkType: hard +"@ant-design/icons@npm:^5.3.7": + version: 5.3.7 + resolution: "@ant-design/icons@npm:5.3.7" + dependencies: + "@ant-design/colors": ^7.0.0 + "@ant-design/icons-svg": ^4.4.0 + "@babel/runtime": ^7.11.2 + classnames: ^2.2.6 + rc-util: ^5.31.1 + peerDependencies: + react: ">=16.0.0" + react-dom: ">=16.0.0" + checksum: 1db109da6893938c431381ad25b4709cbc9c928b9c50b7e1e53a3f49c4faac91e5ec70f1b7df3bf714197841810d858be09c1b61e6cc407cd093b3ab65451daa + languageName: node + linkType: hard + "@ant-design/react-slick@npm:~1.1.2": version: 1.1.2 resolution: "@ant-design/react-slick@npm:1.1.2" @@ -1852,6 +1868,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/runtime@npm:7.24.7" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: b6fa3ec61a53402f3c1d75f4d808f48b35e0dfae0ec8e2bb5c6fc79fb95935da75766e0ca534d0f1c84871f6ae0d2ebdd950727cfadb745a2cdbef13faef5513 + languageName: node + linkType: hard + "@babel/runtime@npm:~7.5.4": version: 7.5.5 resolution: "@babel/runtime@npm:7.5.5" @@ -3004,6 +3029,15 @@ __metadata: languageName: node linkType: hard +"@rc-component/async-validator@npm:^5.0.3": + version: 5.0.4 + resolution: "@rc-component/async-validator@npm:5.0.4" + dependencies: + "@babel/runtime": ^7.24.4 + checksum: e874f87e67228d897801360ef1dbd9f3677e10c57c4b4c708c67f9929f44d8c36ca70ff3967e3fc6ef20b87982c966b27695df44899ca50588240e07130fe2ba + languageName: node + linkType: hard + "@rc-component/color-picker@npm:~1.5.3": version: 1.5.3 resolution: "@rc-component/color-picker@npm:1.5.3" @@ -3069,9 +3103,9 @@ __metadata: languageName: node linkType: hard -"@rc-component/tour@npm:~1.14.2": - version: 1.14.2 - resolution: "@rc-component/tour@npm:1.14.2" +"@rc-component/tour@npm:~1.15.0": + version: 1.15.0 + resolution: "@rc-component/tour@npm:1.15.0" dependencies: "@babel/runtime": ^7.18.0 "@rc-component/portal": ^1.0.0-9 @@ -3081,7 +3115,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: ed2f3f8d14ff7f6666bd3952de47e6db7c70f3a2656300ed1a1bf9e218ef431bb081c73a44dd09a0e419428a354f199b5dd5c5b0ccef191f6f61b34cfb8b6fbe + checksum: c3bdc3331869c7691197b0d4d40a6e307d7a2379fee8fadeb4718c45e6ccfe31bffc1d018b0a5bc246247bbc80069ff09a6b8bf92089f0a8c271946da1c40236 languageName: node linkType: hard @@ -3102,6 +3136,23 @@ __metadata: languageName: node linkType: hard +"@rc-component/trigger@npm:^2.1.1, @rc-component/trigger@npm:^2.2.0": + version: 2.2.0 + resolution: "@rc-component/trigger@npm:2.2.0" + dependencies: + "@babel/runtime": ^7.23.2 + "@rc-component/portal": ^1.1.0 + classnames: ^2.3.2 + rc-motion: ^2.0.0 + rc-resize-observer: ^1.3.1 + rc-util: ^5.38.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 71881fceaa645ae906d765901c23b7c80d96bc6305e943ddc18f2226eb5524d3b61b7d46eae3ab9c6a0519376b7ee5c312df82eb1143942941ba2a56a675ccf6 + languageName: node + linkType: hard + "@react-dnd/asap@npm:4.0.1": version: 4.0.1 resolution: "@react-dnd/asap@npm:4.0.1" @@ -6611,62 +6662,62 @@ __metadata: languageName: node linkType: hard -"antd@npm:^5.9.4": - version: 5.16.1 - resolution: "antd@npm:5.16.1" +"antd@npm:^5.18.3": + version: 5.18.3 + resolution: "antd@npm:5.18.3" dependencies: "@ant-design/colors": ^7.0.2 - "@ant-design/cssinjs": ^1.18.5 - "@ant-design/icons": ^5.3.6 + "@ant-design/cssinjs": ^1.21.0 + "@ant-design/icons": ^5.3.7 "@ant-design/react-slick": ~1.1.2 - "@babel/runtime": ^7.24.4 + "@babel/runtime": ^7.24.7 "@ctrl/tinycolor": ^3.6.1 "@rc-component/color-picker": ~1.5.3 "@rc-component/mutate-observer": ^1.1.0 - "@rc-component/tour": ~1.14.2 - "@rc-component/trigger": ^2.0.0 + "@rc-component/tour": ~1.15.0 + "@rc-component/trigger": ^2.2.0 classnames: ^2.5.1 copy-to-clipboard: ^3.3.3 - dayjs: ^1.11.10 + dayjs: ^1.11.11 qrcode.react: ^3.1.0 - rc-cascader: ~3.24.0 - rc-checkbox: ~3.2.0 + rc-cascader: ~3.26.0 + rc-checkbox: ~3.3.0 rc-collapse: ~3.7.3 - rc-dialog: ~9.4.0 - rc-drawer: ~7.1.0 + rc-dialog: ~9.5.2 + rc-drawer: ~7.2.0 rc-dropdown: ~4.2.0 - rc-field-form: ~1.44.0 - rc-image: ~7.6.0 - rc-input: ~1.4.5 - rc-input-number: ~9.0.0 - rc-mentions: ~2.11.1 - rc-menu: ~9.13.0 - rc-motion: ^2.9.0 - rc-notification: ~5.4.0 + rc-field-form: ~2.2.1 + rc-image: ~7.9.0 + rc-input: ~1.5.1 + rc-input-number: ~9.1.0 + rc-mentions: ~2.14.0 + rc-menu: ~9.14.0 + rc-motion: ^2.9.2 + rc-notification: ~5.6.0 rc-pagination: ~4.0.4 - rc-picker: ~4.3.0 + rc-picker: ~4.5.0 rc-progress: ~4.0.0 - rc-rate: ~2.12.0 + rc-rate: ~2.13.0 rc-resize-observer: ^1.4.0 rc-segmented: ~2.3.0 - rc-select: ~14.13.0 - rc-slider: ~10.5.0 + rc-select: ~14.14.0 + rc-slider: ~10.6.2 rc-steps: ~6.0.1 rc-switch: ~4.1.0 - rc-table: ~7.45.4 - rc-tabs: ~14.1.1 - rc-textarea: ~1.6.3 + rc-table: ~7.45.7 + rc-tabs: ~15.1.1 + rc-textarea: ~1.7.0 rc-tooltip: ~6.2.0 - rc-tree: ~5.8.5 - rc-tree-select: ~5.19.0 + rc-tree: ~5.8.8 + rc-tree-select: ~5.21.0 rc-upload: ~4.5.2 - rc-util: ^5.39.1 + rc-util: ^5.43.0 scroll-into-view-if-needed: ^3.1.0 throttle-debounce: ^5.0.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: e2678fb2bf7f22a7350785825370a91a367b767f8aeff3642dbc54eae1d51dfbe3ed89956fb60a1819a6ad01c067b76024063992b0708f25439cece9c0042c28 + checksum: da0420ef3c22ad205e5198d83da0e3df672ee3e7a9e64ec60e77c51537d6c2e955f223c48d3d8479b4617a8470db2f2de4ecf9611dddf475da47b5959bd78aa1 languageName: node linkType: hard @@ -7104,13 +7155,6 @@ __metadata: languageName: node linkType: hard -"async-validator@npm:^4.1.0": - version: 4.2.5 - resolution: "async-validator@npm:4.2.5" - checksum: 0ec09ee388aae5f6b037a320049a369b681ca9b341b28e2693e50e89b5c4c64c057a2c57f9fc1c18dd020823809d8af4b72b278e0a7a872c9e3accd5c4c3ce3a - languageName: node - linkType: hard - "async@npm:^3.2.0, async@npm:^3.2.3, async@npm:^3.2.4": version: 3.2.5 resolution: "async@npm:3.2.5" @@ -9926,13 +9970,20 @@ __metadata: languageName: node linkType: hard -"dayjs@npm:^1.10.4, dayjs@npm:^1.11.10": +"dayjs@npm:^1.10.4": version: 1.11.10 resolution: "dayjs@npm:1.11.10" checksum: 4de9af50639d47df87f2e15fa36bb07e0f9ed1e9c52c6caa1482788ee9a384d668f1dbd00c54f82aaab163db07d61d2899384b8254da3a9184fc6deca080e2fe languageName: node linkType: hard +"dayjs@npm:^1.11.11": + version: 1.11.11 + resolution: "dayjs@npm:1.11.11" + checksum: 0131d10516b9945f05a57e13f4af49a6814de5573a494824e103131a3bbe4cc470b1aefe8e17e51f9a478a22cd116084be1ee5725cedb66ec4c3f9091202dc4b + languageName: node + linkType: hard + "debounce@npm:^1.2.1": version: 1.2.1 resolution: "debounce@npm:1.2.1" @@ -16401,12 +16452,12 @@ __metadata: languageName: node linkType: hard -"lucide-react@npm:^0.363.0": - version: 0.363.0 - resolution: "lucide-react@npm:0.363.0" +"lucide-react@npm:^0.396.0": + version: 0.396.0 + resolution: "lucide-react@npm:0.396.0" peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 - checksum: e18d3710e619f86d9f6686aa6975bba8a20a48c70ef2da231b61b29fe56eff85df463d38d6885345597a0942c940971cd4e81e8e777583c7db2fd8d62160bf20 + checksum: 3c48ed3d12016e670781698af7a08067ea49b5132d6bef2b6e6e794d76f93de46d6f308af50263a8ae0c2e23bf21b0b33b97aded9aed5a68c6b81e6117cf4828 languageName: node linkType: hard @@ -18275,7 +18326,7 @@ __metadata: "@types/react-virtualized": ^9.21.21 "@typescript-eslint/eslint-plugin": ^5.24.0 "@typescript-eslint/parser": ^5.24.0 - antd: ^5.9.4 + antd: ^5.18.3 autoprefixer: ^10.4.7 babel-loader: ^9.1.3 babel-plugin-react-require: ^4.0.2 @@ -18311,7 +18362,7 @@ __metadata: jshint: ^2.11.1 jspdf: ^2.5.1 jsx-runtime: ^1.2.0 - lucide-react: ^0.363.0 + lucide-react: ^0.396.0 luxon: ^1.24.1 microdiff: ^1.4.0 mini-css-extract-plugin: ^2.6.0 @@ -18352,7 +18403,7 @@ __metadata: react-toastify: ^9.1.1 react-virtualized: ^9.22.3 react18-json-view: ^0.2.8 - recharts: ^2.12.6 + recharts: ^2.12.7 redux: ^4.0.5 redux-immutable: ^4.0.0 redux-thunk: ^2.3.0 @@ -20225,26 +20276,26 @@ __metadata: languageName: node linkType: hard -"rc-cascader@npm:~3.24.0": - version: 3.24.0 - resolution: "rc-cascader@npm:3.24.0" +"rc-cascader@npm:~3.26.0": + version: 3.26.0 + resolution: "rc-cascader@npm:3.26.0" dependencies: "@babel/runtime": ^7.12.5 array-tree-filter: ^2.1.0 classnames: ^2.3.1 - rc-select: ~14.13.0 + rc-select: ~14.14.0 rc-tree: ~5.8.1 rc-util: ^5.37.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 6d9a7a53bc79a06c8d8b2f813ad36b927c7985c18cbccbc851f9ee270ca2327db6bbd0fa6dc12d22777a58ffd14cce27b1d4beb5cd57048dd9b8d155d7f891c5 + checksum: aa28be36e7ffdf8988f898130bf957e252b6eb68e15b3bfc8723f61ea6b7f81da18a3f64fa366e7437a68b0b986afae093d9ce1b4bba868d03ece65987155a64 languageName: node linkType: hard -"rc-checkbox@npm:~3.2.0": - version: 3.2.0 - resolution: "rc-checkbox@npm:3.2.0" +"rc-checkbox@npm:~3.3.0": + version: 3.3.0 + resolution: "rc-checkbox@npm:3.3.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.3.2 @@ -20252,7 +20303,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 1eb4e6bf98936b54a281781d922ec07a05c27b9a754fe1d89c25cdaf83c40f0ac3c56f47e33a401f2a95ca19b703b14a3524e21a6fc6afebf753057bcb7ce90a + checksum: 90dc42115370f6578a798558e30b6248e73d52022dc685b17893f8de1b3dc0b88886258447270c555b7d963621f36b25dadbde9938ba3ea49ec01b24fb2a3555 languageName: node linkType: hard @@ -20271,9 +20322,9 @@ __metadata: languageName: node linkType: hard -"rc-dialog@npm:~9.4.0": - version: 9.4.0 - resolution: "rc-dialog@npm:9.4.0" +"rc-dialog@npm:~9.5.2": + version: 9.5.2 + resolution: "rc-dialog@npm:9.5.2" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/portal": ^1.0.0-8 @@ -20283,13 +20334,13 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 22804e44d7cf5952cce29d92bd180f86bffc9c182165144911e40f209169850aece8ec76a532867ad14272fe5e1ca1b59313af0f62bd7d0f3e37fe2695757677 + checksum: e5854b2b99d4336f8c1125f63bb66da6b25959502866fb74c32cede5cad4ee6aa62dba6de79a16082812605193d83d99409f6372b161c2b906e68b9645d7031e languageName: node linkType: hard -"rc-drawer@npm:~7.1.0": - version: 7.1.0 - resolution: "rc-drawer@npm:7.1.0" +"rc-drawer@npm:~7.2.0": + version: 7.2.0 + resolution: "rc-drawer@npm:7.2.0" dependencies: "@babel/runtime": ^7.23.9 "@rc-component/portal": ^1.1.1 @@ -20299,7 +20350,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 7a27192518f853e1d410391a687c2aae7a8760dbdd9bd0a9d864b83aac9b1253517517f89acd389c11bd7d682f557f6515c5405317e5c2010763f4e0de7dbfc6 + checksum: d6814998983100193d6a521745324a94fa8d65cbb979b2764d1d48a78d6b6e22f9d078ebb68545b68a0cc38f062298d11ed3635e93d004a60415d384330a8573 languageName: node linkType: hard @@ -20318,56 +20369,56 @@ __metadata: languageName: node linkType: hard -"rc-field-form@npm:~1.44.0": - version: 1.44.0 - resolution: "rc-field-form@npm:1.44.0" +"rc-field-form@npm:~2.2.1": + version: 2.2.1 + resolution: "rc-field-form@npm:2.2.1" dependencies: "@babel/runtime": ^7.18.0 - async-validator: ^4.1.0 + "@rc-component/async-validator": ^5.0.3 rc-util: ^5.32.2 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 27ce3c68d412613431b9a601aa93e8663e3afaa690fbb674feab09af495fe3c136b5da207bb4df76f4944065e72bd3f5519f5874b234956bbedd7779e5d53cb5 + checksum: 59911ef8222b08df561ea32bf0cc8d0731c796a06de95be9faacd8399be24e9c82343ceb52201df13c061bf75713b43e8d3963de33c41be35b735991c8f0f500 languageName: node linkType: hard -"rc-image@npm:~7.6.0": - version: 7.6.0 - resolution: "rc-image@npm:7.6.0" +"rc-image@npm:~7.9.0": + version: 7.9.0 + resolution: "rc-image@npm:7.9.0" dependencies: "@babel/runtime": ^7.11.2 "@rc-component/portal": ^1.0.2 classnames: ^2.2.6 - rc-dialog: ~9.4.0 + rc-dialog: ~9.5.2 rc-motion: ^2.6.2 rc-util: ^5.34.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: ed9b0a8815de05ee582f89d062a4116cc85a1b920b125e9fc305d4f6f25da615338b47ebcca04f98fbe546c9822557c986cc30c9456057cd2e48f02673cd57a1 + checksum: fd04b8b66447d6c55f6fb298723582b80e51ddf364d7ae9560431f3f6a11622b97f1870755014d22994fadfbaaa21dda80444eee717409300853c1f65764d5b1 languageName: node linkType: hard -"rc-input-number@npm:~9.0.0": - version: 9.0.0 - resolution: "rc-input-number@npm:9.0.0" +"rc-input-number@npm:~9.1.0": + version: 9.1.0 + resolution: "rc-input-number@npm:9.1.0" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/mini-decimal": ^1.0.1 classnames: ^2.2.5 - rc-input: ~1.4.0 - rc-util: ^5.28.0 + rc-input: ~1.5.0 + rc-util: ^5.40.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 7a8567716c1f566224d4ccd64dbe477bddf803c42f95cb0378f2ce31f6b0a18f52961a3e7437405f8335f6e585ce496f9df5b3e8d3ab1c2b671edefc40b9b90a + checksum: 360a3e215ed8b3f1bdc3605eae139059db59dcfb962e321260e16f1d34bc19d99323b8c7c5ba58a8feeb42a017293ad6b74c30f81f92a618c89625f5f8330219 languageName: node linkType: hard -"rc-input@npm:~1.4.0, rc-input@npm:~1.4.5": - version: 1.4.5 - resolution: "rc-input@npm:1.4.5" +"rc-input@npm:~1.5.0, rc-input@npm:~1.5.1": + version: 1.5.1 + resolution: "rc-input@npm:1.5.1" dependencies: "@babel/runtime": ^7.11.1 classnames: ^2.2.1 @@ -20375,31 +20426,31 @@ __metadata: peerDependencies: react: ">=16.0.0" react-dom: ">=16.0.0" - checksum: 9546c18ab3fd90429c746638e008579933a5aba0b738c6bb33b34fdb963d23edce1d6a34b1f658ac60122208caa5fcf4f9e45dbb82e7d1457003c4a6e0e34fbc + checksum: b6c0199f48a810fbc1ed0bbf0b64c80f2d8b2efb10632cfabe473ea7b79630553ac0f351774d3d0659c2580319e5f98e7e7630efb857f6f26cc49754334536f3 languageName: node linkType: hard -"rc-mentions@npm:~2.11.1": - version: 2.11.1 - resolution: "rc-mentions@npm:2.11.1" +"rc-mentions@npm:~2.14.0": + version: 2.14.0 + resolution: "rc-mentions@npm:2.14.0" dependencies: "@babel/runtime": ^7.22.5 "@rc-component/trigger": ^2.0.0 classnames: ^2.2.6 - rc-input: ~1.4.0 - rc-menu: ~9.13.0 - rc-textarea: ~1.6.1 + rc-input: ~1.5.0 + rc-menu: ~9.14.0 + rc-textarea: ~1.7.0 rc-util: ^5.34.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 117374675b4c691c82872b5531fc91079af38d4c0c3e155065a2567072591c6d3634fef91745a896a67d8bb4a617e8e328c9cc3dec1e59ae901e0ab5796caf01 + checksum: 43e3da8d736b5656fd2bb1073f81be5b494178123a1ca7834168e596cc2156827bee1d63a780c4338bd71a43368ae4fa445e8174b2ba1f3b29cb5ce70ad1adb4 languageName: node linkType: hard -"rc-menu@npm:~9.13.0": - version: 9.13.0 - resolution: "rc-menu@npm:9.13.0" +"rc-menu@npm:~9.14.0": + version: 9.14.1 + resolution: "rc-menu@npm:9.14.1" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/trigger": ^2.0.0 @@ -20410,7 +20461,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 7b488367c43e2a13391cf6b9debae58d7fa8fd663d596ded8763431158ed9e6d8d0fef37d05424791b86081e86130ab3214a40813b2ce30046fc881d54ebf279 + checksum: 821c4016d64b83fb3035c0abfe83c6203f6ae885e9fbb7d4f78e7db5ae390cb67398bac7fd667ff738c4dccb447d9a35ac0bdf0f2bc4816def2b33cdb8a16861 languageName: node linkType: hard @@ -20428,9 +20479,23 @@ __metadata: languageName: node linkType: hard -"rc-notification@npm:~5.4.0": - version: 5.4.0 - resolution: "rc-notification@npm:5.4.0" +"rc-motion@npm:^2.9.2": + version: 2.9.2 + resolution: "rc-motion@npm:2.9.2" + dependencies: + "@babel/runtime": ^7.11.1 + classnames: ^2.2.1 + rc-util: ^5.43.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: e5e4f8fe83238c414fb0fc738b4d71faef0c951b5858bfd90bb3f3ff1dde1577262c258fcdae4e5a53a78f5056e2868ff85335ded92758cc886e610308709d8d + languageName: node + linkType: hard + +"rc-notification@npm:~5.6.0": + version: 5.6.0 + resolution: "rc-notification@npm:5.6.0" dependencies: "@babel/runtime": ^7.10.1 classnames: 2.x @@ -20439,7 +20504,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: f8709d9dfc357a8f12a6f40ad1a5f7c40e06ee3d8936e0f4e68cd7f03f91efb9c3bb69ee992070103f91c9acb241fb70a3fc01b72a4a1359fa110d5dfb5a926a + checksum: 754b158716564a90a96480646fd95ce02b54b25dc88a6b7fd7d4cbfd53f6fcd95aa97fe9267356f66a678ec38c8a04282217c5b909904949b4bdd3a7fd1b7480 languageName: node linkType: hard @@ -20472,9 +20537,9 @@ __metadata: languageName: node linkType: hard -"rc-picker@npm:~4.3.0": - version: 4.3.0 - resolution: "rc-picker@npm:4.3.0" +"rc-picker@npm:~4.5.0": + version: 4.5.0 + resolution: "rc-picker@npm:4.5.0" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/trigger": ^2.0.0 @@ -20498,7 +20563,7 @@ __metadata: optional: true moment: optional: true - checksum: 9b758f1de19ee54f0e84681313e421c104ff697c0c28796b3173c586cb4912147cd17d2c4566be31a4ebda79944c6d497fbf4f2e7a87d00f4ace340c13dc7df4 + checksum: 4302ae7e2f152dd505c1f2dc5e19eaa4019ac57432e4d26b3be961af6c6fc4297abe0a680f644295621330ef5121faab7416d6b29987c1326fcefb6e654b5215 languageName: node linkType: hard @@ -20516,9 +20581,9 @@ __metadata: languageName: node linkType: hard -"rc-rate@npm:~2.12.0": - version: 2.12.0 - resolution: "rc-rate@npm:2.12.0" +"rc-rate@npm:~2.13.0": + version: 2.13.0 + resolution: "rc-rate@npm:2.13.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.5 @@ -20526,7 +20591,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 871bb040ec1de727c9b83e0d5db68877c22ef7494f82ce6dedbe655fc7894d7db63e99bed96584eed122e8845270df0b08e2a97a4cc5600e652ce229d561ace5 + checksum: 3e2c15ee41d20837e820b6a1b83bf83e74ecb36c1da05c9e32c22d864586e7a826c961ba8159468ac9c9ac2fcb03b91a812070a5eb8119e77c2248ef95d6febd languageName: node linkType: hard @@ -20560,12 +20625,12 @@ __metadata: languageName: node linkType: hard -"rc-select@npm:~14.13.0": - version: 14.13.0 - resolution: "rc-select@npm:14.13.0" +"rc-select@npm:~14.14.0": + version: 14.14.0 + resolution: "rc-select@npm:14.14.0" dependencies: "@babel/runtime": ^7.10.1 - "@rc-component/trigger": ^2.0.0 + "@rc-component/trigger": ^2.1.1 classnames: 2.x rc-motion: ^2.0.1 rc-overflow: ^1.3.1 @@ -20574,21 +20639,21 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: aac6741204ceddbed2ca52b966c6b120d0c4b4dfcf81ff2d985dc3b24a81d998303e6816cd64046e38a5e953b4388eac18cece5b0371a339513dfd6db0cf2956 + checksum: beedaf68d84ab21ca00b759f36bc15649fb20a636e39baa1ef489181f038674f8950881c5c3100dc8bc0b9a6bc3f0f0db1c01244180386c5e82c63b8ecdf8aa1 languageName: node linkType: hard -"rc-slider@npm:~10.5.0": - version: 10.5.0 - resolution: "rc-slider@npm:10.5.0" +"rc-slider@npm:~10.6.2": + version: 10.6.2 + resolution: "rc-slider@npm:10.6.2" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.5 - rc-util: ^5.27.0 + rc-util: ^5.36.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: f9d6d4afc7cc62e81fe4dc4de465195c30af123e8e7fb695ded09ecdb6bffdbf696e5764d3c4faa8a7ee3fd43cf80897f83de04e23e2aaad0b97ce4a0bf34696 + checksum: f2d156ffa88596419957f3955a2be86a98705140546f24e53180a17baa20f948187db55529759451adcfbcc52dc67c72bd26b4d3afd54529be8f092e81fa8f65 languageName: node linkType: hard @@ -20620,54 +20685,54 @@ __metadata: languageName: node linkType: hard -"rc-table@npm:~7.45.4": - version: 7.45.4 - resolution: "rc-table@npm:7.45.4" +"rc-table@npm:~7.45.7": + version: 7.45.7 + resolution: "rc-table@npm:7.45.7" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/context": ^1.4.0 classnames: ^2.2.5 rc-resize-observer: ^1.1.0 rc-util: ^5.37.0 - rc-virtual-list: ^3.11.1 + rc-virtual-list: ^3.14.2 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 1b9d22fb8c521ca691b9ac1fd2cde90c2e37f056ec75838f260f50f616b009bef8016ab0c921da892d960ae5b10fa5bd0e211bc5f471aeb6affafce4e3c7d5e4 + checksum: 18803454e2d4f2dcbbc8d6c5cf8b0445c35f586106d389db503601f4b17e941765c1fda53555a2120af4b122b9a88ccde30c28bb4d6a2fd96f9daa5438ff16a5 languageName: node linkType: hard -"rc-tabs@npm:~14.1.1": - version: 14.1.1 - resolution: "rc-tabs@npm:14.1.1" +"rc-tabs@npm:~15.1.1": + version: 15.1.1 + resolution: "rc-tabs@npm:15.1.1" dependencies: "@babel/runtime": ^7.11.2 classnames: 2.x rc-dropdown: ~4.2.0 - rc-menu: ~9.13.0 + rc-menu: ~9.14.0 rc-motion: ^2.6.2 rc-resize-observer: ^1.0.0 rc-util: ^5.34.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 9ba0f295de28b682d8306deabdd7aba226cb636adfc45fd34b5ea987403ff808a7bfaebc4e744d520ec630287b6008e5d46967bd103a2e0de2c4a969d411750c + checksum: b6115747f23f94d31fa6b2de381e6e7db38f18a121cdf15ffaec8008faa9da6c7e8d6253c998f817b6e453532ca6e3577b0b7ab9bf4ec3de541eaad32fac50f7 languageName: node linkType: hard -"rc-textarea@npm:~1.6.1, rc-textarea@npm:~1.6.3": - version: 1.6.3 - resolution: "rc-textarea@npm:1.6.3" +"rc-textarea@npm:~1.7.0": + version: 1.7.0 + resolution: "rc-textarea@npm:1.7.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.1 - rc-input: ~1.4.0 + rc-input: ~1.5.0 rc-resize-observer: ^1.0.0 rc-util: ^5.27.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: fe88d9009511e07e260b4492bf009d51992177683db58ad4c52a3d6f4759415efcf39411e492202ca7a2de8f301cefda375278b7a51a33a9d25a0a805f1c762c + checksum: 7a72c67e8bb947a188b824a9081bdceb0fd150d4b783ec6b6195bd74eb31434308b9862ddad3ddb9c450637578d6825a7a8fd4116b23bff1a649a72c646985f8 languageName: node linkType: hard @@ -20699,23 +20764,23 @@ __metadata: languageName: node linkType: hard -"rc-tree-select@npm:~5.19.0": - version: 5.19.0 - resolution: "rc-tree-select@npm:5.19.0" +"rc-tree-select@npm:~5.21.0": + version: 5.21.0 + resolution: "rc-tree-select@npm:5.21.0" dependencies: "@babel/runtime": ^7.10.1 classnames: 2.x - rc-select: ~14.13.0 + rc-select: ~14.14.0 rc-tree: ~5.8.1 rc-util: ^5.16.1 peerDependencies: react: "*" react-dom: "*" - checksum: 268305427670d367ee8b0db5797dfd0f32ff3a147cc3104d512414c72b7b214841b2b02bd86b81ef45f0256030b63b4b6dc65b89a6b5e4105697bd2e684c93f6 + checksum: c73c81f248e6be638dfca58c31303e5a173643accfbc79da4bc630b59cc381a9f6d6c4bbef551afe007edba0825496f8dc84800d2b9440d495833a4ceabea296 languageName: node linkType: hard -"rc-tree@npm:~5.8.1, rc-tree@npm:~5.8.5": +"rc-tree@npm:~5.8.1": version: 5.8.5 resolution: "rc-tree@npm:5.8.5" dependencies: @@ -20731,6 +20796,22 @@ __metadata: languageName: node linkType: hard +"rc-tree@npm:~5.8.8": + version: 5.8.8 + resolution: "rc-tree@npm:5.8.8" + dependencies: + "@babel/runtime": ^7.10.1 + classnames: 2.x + rc-motion: ^2.0.1 + rc-util: ^5.16.1 + rc-virtual-list: ^3.5.1 + peerDependencies: + react: "*" + react-dom: "*" + checksum: 879547f43ead839c3ef2a1d7b7626c2771013b4c480e7c49d74929d99778fd47b977a593922aa80947dba5aa60a7524f1b43dca1258a56a30d9ca143f12558cf + languageName: node + linkType: hard + "rc-trigger@npm:^2.2.0": version: 2.6.5 resolution: "rc-trigger@npm:2.6.5" @@ -20773,7 +20854,7 @@ __metadata: languageName: node linkType: hard -"rc-util@npm:^5.0.1, rc-util@npm:^5.16.1, rc-util@npm:^5.17.0, rc-util@npm:^5.18.1, rc-util@npm:^5.2.0, rc-util@npm:^5.20.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.25.2, rc-util@npm:^5.27.0, rc-util@npm:^5.28.0, rc-util@npm:^5.30.0, rc-util@npm:^5.31.1, rc-util@npm:^5.32.2, rc-util@npm:^5.34.1, rc-util@npm:^5.35.0, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1, rc-util@npm:^5.39.1": +"rc-util@npm:^5.0.1, rc-util@npm:^5.16.1, rc-util@npm:^5.17.0, rc-util@npm:^5.18.1, rc-util@npm:^5.2.0, rc-util@npm:^5.20.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.25.2, rc-util@npm:^5.27.0, rc-util@npm:^5.30.0, rc-util@npm:^5.31.1, rc-util@npm:^5.32.2, rc-util@npm:^5.34.1, rc-util@npm:^5.35.0, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1": version: 5.39.1 resolution: "rc-util@npm:5.39.1" dependencies: @@ -20786,7 +20867,35 @@ __metadata: languageName: node linkType: hard -"rc-virtual-list@npm:^3.11.1, rc-virtual-list@npm:^3.5.1, rc-virtual-list@npm:^3.5.2": +"rc-util@npm:^5.40.1, rc-util@npm:^5.43.0": + version: 5.43.0 + resolution: "rc-util@npm:5.43.0" + dependencies: + "@babel/runtime": ^7.18.3 + react-is: ^18.2.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 39f7904c9851f2b0a2dace5ac578f42000498412d7da5ef2063fd547db91d158dcb376bcbacf49fb7790d2721727bd38ea3483294ef51eb6099a793b2e17e9db + languageName: node + linkType: hard + +"rc-virtual-list@npm:^3.14.2": + version: 3.14.3 + resolution: "rc-virtual-list@npm:3.14.3" + dependencies: + "@babel/runtime": ^7.20.0 + classnames: ^2.2.6 + rc-resize-observer: ^1.0.0 + rc-util: ^5.36.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 7a2b1a53eeb7a03fcb536f0d76e626e44694ec25b247f22caba0f2a4e653db5ebf57cf3e8743abeadade80c16525cb96bb63c549483b3639704e5c0535a76836 + languageName: node + linkType: hard + +"rc-virtual-list@npm:^3.5.1, rc-virtual-list@npm:^3.5.2": version: 3.11.4 resolution: "rc-virtual-list@npm:3.11.4" dependencies: @@ -21455,7 +21564,7 @@ __metadata: languageName: node linkType: hard -"recharts@npm:^2.12.6": +"recharts@npm:^2.12.7": version: 2.12.7 resolution: "recharts@npm:2.12.7" dependencies: From 3b2c988e426dce36978e0b8b161c5b3a12118b46 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 25 Jun 2024 17:36:02 +0200 Subject: [PATCH 10/66] change(ui): dashboard redesign --- .../components/FilterSeries/FilterSeries.tsx | 132 +++-- .../components/WidgetForm/WidgetFormNew.tsx | 27 +- .../shared/Filters/FilterList/FilterList.tsx | 513 ++++++++++-------- 3 files changed, 371 insertions(+), 301 deletions(-) diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 7861fa2ad..45ef923bf 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -1,6 +1,5 @@ import React, {useState} from 'react'; import FilterList from 'Shared/Filters/FilterList'; -import {Icon} from 'UI'; import SeriesName from './SeriesName'; import cn from 'classnames'; import {observer} from 'mobx-react-lite'; @@ -9,6 +8,63 @@ import AddStepButton from "Components/Dashboard/components/FilterSeries/AddStepB import {Button, Space} from "antd"; import {ChevronDown, ChevronUp, Trash} from "lucide-react"; + +const FilterCountLabels = observer((props: { filters: any, toggleExpand: any }) => { + const events = props.filters.filter((i: any) => i && i.isEvent).length; + const filters = props.filters.filter((i: any) => i && !i.isEvent).length; + return
+ + {events > 0 && ( + + )} + + {filters > 0 && ( + + )} + +
; +}); + +const FilterSeriesHeader = observer((props: { + expanded: boolean, + hidden: boolean, + seriesIndex: number, + series: any, + onRemove: (seriesIndex: any) => void, + canDelete: boolean | undefined, + toggleExpand: () => void +}) => { + + const onUpdate = (name: any) => { + props.series.update('name', name) + } + return
+ + + {!props.expanded && + } + + + +
; +}) + interface Props { seriesIndex: number; series: any; @@ -20,62 +76,9 @@ interface Props { observeChanges?: () => void; excludeFilterKeys?: Array; canExclude?: boolean; + expandable?: boolean; } -const FilterSeriesHeader = observer((props: { - expanded: boolean, - hidden: boolean, - seriesIndex: number, - series: any, - onRemove: (seriesIndex: any) => void, - canDelete: boolean | undefined, - toggleExpand: () => void -}) => { - const events = props.series.filter.filters.filter((i: any) => i && i.isEvent).length; - const filters = props.series.filter.filters.filter((i: any) => i && !i.isEvent).length; - const onUpdate = (name: any) => { - props.series.update('name', name) - } - return
- - - {!props.expanded && ( - - {events > 0 && ( - - )} - - {filters > 0 && ( - - )} - - )} - - {/*{events === 0 && filters === 0 && !props.expanded && (*/} - {/* */} - {/*)}*/} - - - -
; -}) - function FilterSeries(props: Props) { const { observeChanges = () => { @@ -86,8 +89,9 @@ function FilterSeries(props: Props) { supportsEmpty = true, excludeFilterKeys = [], canExclude = false, + expandable = false } = props; - const [expanded, setExpanded] = useState(true); + const [expanded, setExpanded] = useState(false); const {series, seriesIndex} = props; const onUpdateFilter = (filterIndex: any, filter: any) => { @@ -124,6 +128,15 @@ function FilterSeries(props: Props) { toggleExpand={() => setExpanded(!expanded)}/> )} + {expandable && !expanded && ( + + setExpanded(!expanded)}/> +
)) @@ -114,7 +106,10 @@ const FilterSection = observer(({metric, excludeFilterKeys}: any) => {
onClick(true)}> -
- +
+ Add from library

Select from 12 available

@@ -41,7 +41,7 @@ function AddCardSelectionModal(props: Props) {
onClick(false)}> -
+

Create New Card

diff --git a/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx b/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx index 84f9f7fa3..c7139afb3 100644 --- a/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx +++ b/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx @@ -1,32 +1,63 @@ import React from 'react'; -import DashboardSelectionModal from "Components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal"; import {Grid2x2Check} from "lucide-react" -import {Button} from "antd"; +import {Button, Modal} from "antd"; +import Select from "Shared/Select/Select"; +import {Form} from "UI"; +import {useStore} from "App/mstore"; interface Props { metricId: string; } function AddToDashboardButton({metricId}: Props) { - const [show, setShow] = React.useState(false); + const {dashboardStore} = useStore(); + const dashboardOptions = dashboardStore.dashboards.map((i: any) => ({ + key: i.id, + label: i.name, + value: i.dashboardId, + })); + const [selectedId, setSelectedId] = React.useState(dashboardOptions[0].value); + + const onSave = (close: any) => { + const dashboard = dashboardStore.getDashboard(selectedId) + if (dashboard) { + dashboardStore.addWidgetToDashboard(dashboard, [metricId]).then(close) + } + } + + const onClick = () => { + Modal.confirm({ + title: 'Add to selected dashboard', + icon: null, + content: ( + + setSelectedId(value.value)} + onChange={({value}: any) => setSelectedId(value.value)} /> - + - + )); } diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 45ef923bf..36eb148f3 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -91,7 +91,7 @@ function FilterSeries(props: Props) { canExclude = false, expandable = false } = props; - const [expanded, setExpanded] = useState(false); + const [expanded, setExpanded] = useState(!expandable); const {series, seriesIndex} = props; const onUpdateFilter = (filterIndex: any, filter: any) => { diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 15376eb1c..32c63c5e6 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -97,7 +97,6 @@ function WidgetChart(props: Props) { if (!isMounted()) return; setLoading(true); dashboardStore.fetchMetricChartData(metric, payload, isWidget, period).then((res: any) => { - console.log('res', res) if (isMounted()) setData(res); }).finally(() => { setLoading(false); diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index b1f00c057..02e586420 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -57,7 +57,7 @@ function WidgetView(props: Props) { React.useEffect(() => { if (metricId && metricId !== 'create') { metricStore.fetch(metricId, dashboardStore.period).catch((e) => { - if (e.status === 404 || e.status === 422) { + if (e.response.status === 404 || e.response.status === 422) { setMetricNotFound(true); } }); diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx index d54528e9b..4fc81338a 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx @@ -5,7 +5,10 @@ import {useStore} from "App/mstore"; import {useObserver} from "mobx-react-lite"; import AddToDashboardButton from "Components/Dashboard/components/AddToDashboardButton"; import WidgetDateRange from "Components/Dashboard/components/WidgetDateRange/WidgetDateRange"; -import {Button, Space} from "antd"; +import {Button, Dropdown, MenuProps, Space, message, Modal} from "antd"; +import {BellIcon, EllipsisVertical, TrashIcon} from "lucide-react"; +import {useHistory} from "react-router"; +import {toast} from "react-toastify"; interface Props { onClick?: () => void; @@ -31,16 +34,69 @@ function WidgetViewHeader({onClick, onSave, undoChanges}: Props) { +
); } export default WidgetViewHeader; + +const CardViewMenu = () => { + const history = useHistory(); + const {dashboardStore, metricStore} = useStore(); + const widget = useObserver(() => metricStore.instance); + const items: MenuProps['items'] = [ + { + key: 'alert', + label: "Set Alerts", + icon: , + }, + { + key: 'remove', + danger: true, + label: 'Remove', + icon: , + }, + ]; + + const onClick: MenuProps['onClick'] = ({key}) => { + if (key === 'alert') { + message.info('Set Alerts'); + } else if (key === 'remove') { + Modal.confirm({ + title: 'Are you sure you want to remove this card?', + icon: null, + // content: 'Bla bla ...', + footer: (_, {OkBtn, CancelBtn}) => ( + <> + + + + ), + onOk: () => { + metricStore.delete(widget).then(r => { + history.goBack(); + }).catch(() => { + toast.error('Failed to remove card'); + }); + }, + }) + } + }; + + return ( +
+ +
+ ); +}; diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx index 0b50abdd4..6ff3ddda0 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx @@ -1,26 +1,23 @@ import React from 'react'; import WidgetIcon from './WidgetIcon'; -import { useStore } from 'App/mstore'; +import {useStore} from 'App/mstore'; +import {Button} from "antd"; +import {BellIcon} from "lucide-react"; interface Props { seriesId: string; initAlert?: Function; } + function AlertButton(props: Props) { - const { seriesId } = props; - const { dashboardStore, alertsStore } = useStore(); + const {seriesId} = props; + const {dashboardStore, alertsStore} = useStore(); const onClick = () => { dashboardStore.toggleAlertModal(true); - alertsStore.init({ query: { left: seriesId }}) + alertsStore.init({query: {left: seriesId}}) } return ( -
- -
+ +
+
- )} - {instance.msteams && ( -
- -
- alertsStore.edit({ msteamsInput: selected })} - /> -
+
+ {instance.exists() && ( + + )}
- )} - - {instance.email && ( -
- -
- alertsStore.edit({ emailInput: selected })} - /> -
-
- )} - - {instance.webhook && ( -
- - alertsStore.edit({ webhookInput: selected })} - /> -
- )}
- } - /> - - -
-
- -
- -
-
- {instance.exists() && ( - - )} -
-
- - ); + + ); }; export default observer(AlertForm); diff --git a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx index 3821a3f45..50e0c3cf6 100644 --- a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx +++ b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx @@ -1,10 +1,10 @@ -import React, { useEffect, useState } from 'react'; -import { SlideModal } from 'UI'; -import { useStore } from 'App/mstore' -import { observer } from 'mobx-react-lite' +import React, {useEffect, useState} from 'react'; +import {SlideModal} from 'UI'; +import {useStore} from 'App/mstore' +import {observer} from 'mobx-react-lite' import AlertForm from '../AlertForm'; -import { SLACK, TEAMS, WEBHOOK } from 'App/constants/schedule'; -import { confirm } from 'UI'; +import {SLACK, TEAMS, WEBHOOK} from 'App/constants/schedule'; +import {confirm} from 'UI'; interface Select { label: string; @@ -17,9 +17,10 @@ interface Props { metricId?: number; onClose?: () => void; } + function AlertFormModal(props: Props) { - const { alertsStore, settingsStore } = useStore() - const { metricId = null, showModal = false } = props; + const {alertsStore, settingsStore} = useStore() + const {metricId = null, showModal = false} = props; const [showForm, setShowForm] = useState(false); const webhooks = settingsStore.webhooks useEffect(() => { @@ -32,7 +33,7 @@ function AlertFormModal(props: Props) { const msTeamsChannels: Select[] = [] webhooks.forEach((hook) => { - const option = { value: hook.webhookId, label: hook.name } + const option = {value: hook.webhookId, label: hook.name} if (hook.type === SLACK) { slackChannels.push(option) } diff --git a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx new file mode 100644 index 000000000..a90ff63f1 --- /dev/null +++ b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx @@ -0,0 +1,99 @@ +import {useHistory} from "react-router"; +import {useStore} from "App/mstore"; +import {useObserver} from "mobx-react-lite"; +import {Button, Drawer, Dropdown, MenuProps, message, Modal} from "antd"; +import {BellIcon, EllipsisVertical, TrashIcon} from "lucide-react"; +import {toast} from "react-toastify"; +import React from "react"; +import {useModal} from "Components/ModalContext"; +import AlertFormModal from "Components/Alerts/AlertFormModal/AlertFormModal"; + +const CardViewMenu = () => { + const history = useHistory(); + const {alertsStore, dashboardStore, metricStore} = useStore(); + const widget = useObserver(() => metricStore.instance); + const {openModal, closeModal} = useModal(); + + const showAlertModal = () => { + const seriesId = widget.series[0] && widget.series[0].seriesId || ''; + alertsStore.init({query: {left: seriesId}}) + openModal(, { + // title: 'Set Alerts', + placement: 'right', + width: 620, + }); + } + + const items: MenuProps['items'] = [ + { + key: 'alert', + label: "Set Alerts", + icon: , + disabled: !widget.exists() || widget.metricType === 'predefined', + onClick: showAlertModal, + }, + { + key: 'remove', + danger: true, + label: 'Remove', + icon: , + onClick: () => { + Modal.confirm({ + title: 'Are you sure you want to remove this card?', + icon: null, + // content: 'Bla bla ...', + footer: (_, {OkBtn, CancelBtn}) => ( + <> + + + + ), + onOk: () => { + metricStore.delete(widget).then(r => { + history.goBack(); + }).catch(() => { + toast.error('Failed to remove card'); + }); + }, + }) + } + }, + ]; + + const onClick: MenuProps['onClick'] = ({key}) => { + if (key === 'alert') { + message.info('Set Alerts'); + } else if (key === 'remove') { + Modal.confirm({ + title: 'Are you sure you want to remove this card?', + icon: null, + // content: 'Bla bla ...', + footer: (_, {OkBtn, CancelBtn}) => ( + <> + + + + ), + onOk: () => { + metricStore.delete(widget).then(r => { + history.goBack(); + }).catch(() => { + toast.error('Failed to remove card'); + }); + }, + }) + } + }; + + return ( +
+ +
+ ); +}; + +export default CardViewMenu; diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx index 4fc81338a..49a22e3a1 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx @@ -5,10 +5,8 @@ import {useStore} from "App/mstore"; import {useObserver} from "mobx-react-lite"; import AddToDashboardButton from "Components/Dashboard/components/AddToDashboardButton"; import WidgetDateRange from "Components/Dashboard/components/WidgetDateRange/WidgetDateRange"; -import {Button, Dropdown, MenuProps, Space, message, Modal} from "antd"; -import {BellIcon, EllipsisVertical, TrashIcon} from "lucide-react"; -import {useHistory} from "react-router"; -import {toast} from "react-toastify"; +import {Button, Space} from "antd"; +import CardViewMenu from "Components/Dashboard/components/WidgetView/CardViewMenu"; interface Props { onClick?: () => void; @@ -48,55 +46,3 @@ function WidgetViewHeader({onClick, onSave, undoChanges}: Props) { } export default WidgetViewHeader; - -const CardViewMenu = () => { - const history = useHistory(); - const {dashboardStore, metricStore} = useStore(); - const widget = useObserver(() => metricStore.instance); - const items: MenuProps['items'] = [ - { - key: 'alert', - label: "Set Alerts", - icon: , - }, - { - key: 'remove', - danger: true, - label: 'Remove', - icon: , - }, - ]; - - const onClick: MenuProps['onClick'] = ({key}) => { - if (key === 'alert') { - message.info('Set Alerts'); - } else if (key === 'remove') { - Modal.confirm({ - title: 'Are you sure you want to remove this card?', - icon: null, - // content: 'Bla bla ...', - footer: (_, {OkBtn, CancelBtn}) => ( - <> - - - - ), - onOk: () => { - metricStore.delete(widget).then(r => { - history.goBack(); - }).catch(() => { - toast.error('Failed to remove card'); - }); - }, - }) - } - }; - - return ( -
- -
- ); -}; diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx index 6ff3ddda0..c9cbac62f 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx @@ -3,6 +3,8 @@ import WidgetIcon from './WidgetIcon'; import {useStore} from 'App/mstore'; import {Button} from "antd"; import {BellIcon} from "lucide-react"; +import {useModal} from "Components/ModalContext"; +import AlertFormModal from "Components/Alerts/AlertFormModal/AlertFormModal"; interface Props { seriesId: string; @@ -12,9 +14,17 @@ interface Props { function AlertButton(props: Props) { const {seriesId} = props; const {dashboardStore, alertsStore} = useStore(); + const {openModal, closeModal} = useModal(); const onClick = () => { - dashboardStore.toggleAlertModal(true); + // dashboardStore.toggleAlertModal(true); alertsStore.init({query: {left: seriesId}}) + openModal(, { + // title: 'Set Alerts', + placement: 'right', + width: 620, + }); } return (
+ )} + /> + + )} + /> + ); +} + +export default CardSessionsByList; diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx index 10fa154bd..b7a086d0c 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import {List, Typography} from 'antd'; +import {Button, Space} from 'antd'; import {filtersMap} from 'Types/filter/newFilter'; import {Icon} from 'UI'; -import {Progress, Empty} from 'antd'; -import cn from "classnames"; +import {Empty} from 'antd'; +import {ArrowRight} from "lucide-react"; +import CardSessionsByList from "Components/Dashboard/Widgets/CardSessionsByList"; +import {useModal} from "Components/ModalContext"; interface Props { metric?: any; @@ -15,6 +17,8 @@ interface Props { function SessionsBy(props: Props) { const {metric = {}, data = {values: []}, onClick = () => null, isTemplate} = props; const [selected, setSelected] = React.useState(null); + const total = data.values.length + const {openModal, closeModal} = useModal(); const onClickHandler = (event: any, data: any) => { const filters = Array(); @@ -34,8 +38,19 @@ function SessionsBy(props: Props) { onClick(filters); } + const showMore = () => { + openModal( + { + closeModal(); + onClickHandler(null, item) + }} selected={selected}/>, { + title: metric.name, + width: 600, + }) + } + return ( -
+
{data.values && data.values.length === 0 ? ( ) : ( - ( - onClickHandler(e, row)} - // actions={[row.sessionCount]} - style={{borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', padding: '6px 0'}} - className={cn('hover:bg-active-blue cursor-pointer', selected === row.name ? 'bg-gray-100' : '')} - > - - {row.name} - {row.sessionCount} -
- )} - description={ - - } - /> - {/*
{row.value}
*/} - +
+ + {total > 3 && ( +
+ +
)} - /> +
)}
); diff --git a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx index 683a090f9..2173b6ac8 100644 --- a/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPreview/WidgetPreview.tsx @@ -126,7 +126,7 @@ function WidgetPreview(props: Props) { {/*)}*/} -
+
From 4abed7321912e857cbfd552326fead048642dadd Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 26 Jun 2024 14:15:09 +0200 Subject: [PATCH 14/66] change(ui): examples --- .../Examples/SessionsBy/Component.tsx | 70 +++++++++++-------- .../NewDashModal/NewDashboardModal.tsx | 3 + .../DashboardList/NewDashModal/SelectCard.tsx | 13 ++-- .../components/WidgetForm/CardBuilder.tsx | 6 +- 4 files changed, 54 insertions(+), 38 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx index eda89c46f..2300ddeb2 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component.tsx @@ -1,5 +1,6 @@ import ExCard from '../ExCard' import React from 'react' +import CardSessionsByList from "Components/Dashboard/Widgets/CardSessionsByList"; function ByComponent({title, rows, lineWidth, onCard, type}: { title: string @@ -13,6 +14,11 @@ function ByComponent({title, rows, lineWidth, onCard, type}: { type: string lineWidth: number }) { + const _rows = rows.map((r) => ({ + ...r, + name: r.label, + sessionCount: r.value, + })).slice(0, 4) return (
- {rows.map((r) => ( -
-
{r.icon}
-
{r.label}
-
-
-
-
-
{r.value}
-
- ))} + null}/> + + {/*{rows.map((r) => (*/} + {/* */} + {/*
{r.icon}
*/} + {/*
{r.label}
*/} + {/* */} + {/* */} + {/* */} + {/*
*/} + {/*
{r.value}
*/} + {/*
*/} + {/*))}*/}
) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx index ed17b8217..ae48e05af 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx @@ -15,6 +15,7 @@ const NewDashboardModal: React.FC = ({ isAddingFromLibrary = false, }) => { const [step, setStep] = React.useState(0); + const [selectedCategory, setSelectedCategory] = React.useState('product-analytics'); useEffect(() => { return () => { @@ -28,6 +29,8 @@ const NewDashboardModal: React.FC = ({
{step === 0 && setStep(step + 1)} isLibrary={isAddingFromLibrary}/>} {step === 1 && setStep(0)}/>} diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx index 72ca572e2..6483f9a44 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx @@ -9,11 +9,12 @@ interface SelectCardProps { onClose: (refresh?: boolean) => void; onCard: () => void; isLibrary?: boolean; + selected?: string; + setSelectedCategory?: React.Dispatch>; } const SelectCard: React.FC = (props: SelectCardProps) => { - const {onCard, isLibrary = false} = props; - const [selected, setSelected] = React.useState('product-analytics'); + const {onCard, isLibrary = false, selected, setSelectedCategory} = props; const [selectedCards, setSelectedCards] = React.useState([]); const {metricStore, dashboardStore} = useStore(); const dashboardId = window.location.pathname.split('/')[3]; @@ -83,7 +84,7 @@ const SelectCard: React.FC = (props: SelectCardProps) => { )} - {!isLibrary && } + {!isLibrary && } {isLibrary ? : } @@ -111,15 +112,17 @@ const SelectCard: React.FC = (props: SelectCardProps) => { // ); interface CategorySelectorProps { - setSelected: React.Dispatch>; + setSelected?: React.Dispatch>; + selected?: string; } -const CategorySelector: React.FC = ({setSelected}) => ( +const CategorySelector: React.FC = ({setSelected, selected}) => ( ({ label:
onClick(true)}>
- + Add from library -

Select from 12 available

+ {/*

Select from 12 available

*/}
onClick(false)}>
- -

Create New Card

+ + Create New Card
From 5b51755328aae57e5487b9741775cae170ad7009 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Wed, 26 Jun 2024 21:45:14 +0530 Subject: [PATCH 18/66] Various style improvements --- .../Client/Integrations/Integrations.tsx | 10 +--- .../app/components/Client/Modules/Modules.tsx | 4 +- .../Dashboard/Widgets/CardSessionsByList.tsx | 10 ++-- .../DashboardList/DashboardList.tsx | 49 +++++-------------- .../DashboardList/NewDashModal/CreateCard.tsx | 4 +- .../NewDashModal/ExampleCards.tsx | 3 +- .../NewDashModal/Examples/Count.tsx | 2 + .../NewDashModal/Examples/ExCard.tsx | 4 +- .../Examples/SessionsBy/ByUrl.tsx | 1 + .../NewDashModal/Examples/Trend.tsx | 7 +-- .../NewDashModal/NewDashboardModal.tsx | 10 +++- .../DashboardList/NewDashModal/SelectCard.tsx | 5 +- .../DashboardSelectionModal.tsx | 5 +- .../DashboardView/DashboardView.module.css | 2 +- .../components/FilterSeries/AddStepButton.tsx | 2 +- .../components/FilterSeries/FilterSeries.tsx | 2 +- .../Funnels/FunnelIssues/FunnelIssues.tsx | 2 +- .../components/WidgetForm/CardBuilder.tsx | 3 +- .../components/WidgetForm/WidgetFormNew.tsx | 2 +- .../WidgetPreview/WidgetPreview.tsx | 2 +- .../WidgetWrapper/WidgetWrapper.tsx | 2 +- .../ForgotPassword/ForgotPassword.tsx | 2 +- frontend/app/components/Login/Login.tsx | 2 +- .../FilterAutoComplete/FilterAutoComplete.tsx | 2 +- .../Filters/FilterModal/FilterModal.tsx | 4 +- .../FilterSelection/FilterSelection.tsx | 2 +- .../FilterValueDropdown.tsx | 2 +- .../LiveSessionSearchField.tsx | 2 +- .../app/components/shared/Select/Select.tsx | 2 +- .../AiSessionSearchField.tsx | 2 +- .../SessionSearchField/SessionSearchField.tsx | 2 +- frontend/app/styles/general.css | 18 +++++++ 32 files changed, 87 insertions(+), 84 deletions(-) diff --git a/frontend/app/components/Client/Integrations/Integrations.tsx b/frontend/app/components/Client/Integrations/Integrations.tsx index 65c0ed6e7..e81a7038a 100644 --- a/frontend/app/components/Client/Integrations/Integrations.tsx +++ b/frontend/app/components/Client/Integrations/Integrations.tsx @@ -117,15 +117,7 @@ function Integrations(props: Props) {
0 ? 'p-2' : ''} - grid-cols-1 // default to 1 column - sm:grid-cols-1 // 1 column on small screens and up - md:grid-cols-2 // 2 columns on medium screens and up - lg:grid-cols-3 // 3 columns on large screens and up - xl:grid-cols-3 // 3 columns on extra-large screens + mt-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3 `)}> {allIntegrations.map((integration: any) => ( -
+

Modules

  • OpenReplay's modules are a collection of advanced features that provide enhanced functionality.
  • @@ -54,7 +54,7 @@ function Modules(props: Props) {
-
+
{modulesState.map((module) => (
diff --git a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx index 63f296cb0..262916873 100644 --- a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx +++ b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {List, Progress, Typography} from "antd"; +import { List, Progress, Typography } from "antd"; import cn from "classnames"; interface Props { @@ -8,7 +8,7 @@ interface Props { onClickHandler: (event: any, data: any) => void; } -function CardSessionsByList({list, selected, onClickHandler}: Props) { +function CardSessionsByList({ list, selected, onClickHandler }: Props) { return ( ( onClickHandler(e, row)} + onClick={(e) => onClickHandler(e, row)} // Remove onClick handler to disable click interaction style={{ borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', padding: '4px 10px', lineHeight: '1px' }} - className={cn('rounded hover:bg-active-blue cursor-pointer', selected === row.name ? 'bg-active-blue' : '')} + className={cn('rounded', selected === row.name ? 'bg-active-blue' : '')} // Remove hover:bg-active-blue and cursor-pointer >
- {row.name} + {row.name} {row.sessionCount}
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 442ce6790..77350083e 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -74,46 +74,22 @@ function DashboardList({siteId}: { siteId: string }) { return ( list.length === 0 && !dashboardStore.filter.showMine ? ( } + image={} + imageStyle={{height: 300}} description={(
- {dashboardsSearch !== '' - ? - No matching results +
+ + Create your first dashboard. - : ( -
- - Create your first dashboard. - - {/*
- A Dashboard is a collection of{' '} - - Utilize cards to visualize key user interactions or product - performance metrics. -
- } - className="text-center" - > - cards - {' '} - that can be shared across teams. -
*/} - -
-
- Organize your product and technical insights as cards in dashboards to see the bigger picture,
take action and improve user experience. -
-
- -
- -
-
- )} +
+ Organize your product and technical insights as cards in dashboards to see the bigger picture,
take action and improve user experience. +
+
+ +
+
)} /> @@ -138,6 +114,7 @@ function DashboardList({siteId}: { siteId: string }) { })} />) ); + } export default connect((state: any) => ({ diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx index df4d8a3fb..22ac90d79 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx @@ -83,7 +83,7 @@ function CreateCard(props: Props) { -
+
{metric.name}
@@ -94,7 +94,7 @@ function CreateCard(props: Props) {
- +
); } diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index 618a31ab4..58e36baeb 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -13,6 +13,7 @@ import ByUrl from "./Examples/SessionsBy/ByUrl"; import {ERRORS, FUNNEL, PERFORMANCE, TABLE, TIMESERIES, USER_PATH, WEB_VITALS} from "App/constants/card"; import {FilterKey} from "Types/filter/filterType"; import {Activity, BarChart, TableCellsMerge, TrendingUp} from "lucide-react"; +import { size } from "@floating-ui/react-dom-interactions"; const TYPE = { FUNNEL: 'funnel', @@ -31,7 +32,7 @@ const TYPE = { export const CARD_CATEGORIES = [ { - key: 'product-analytics', label: 'Product Analytics', icon: TrendingUp, types: [USER_PATH, ERRORS] + key: 'product-analytics', label: 'Product Analytics', icon: TrendingUp, size:32, types: [USER_PATH, ERRORS] }, {key: 'performance-monitoring', label: 'Performance Monitoring', icon: Activity, types: [TIMESERIES]}, {key: 'web-analytics', label: 'Web Analytics', icon: BarChart, types: [TABLE]}, diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx index 1f21a6c9a..044824ab0 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx @@ -9,6 +9,7 @@ import { import React from 'react'; import ExCard from './ExCard'; +import { size } from '@floating-ui/react-dom-interactions'; const TYPES = { Frustrations: 'frustrations', @@ -37,6 +38,7 @@ function ExampleCount(props: any) { { label: 'Errors', value: '1' }, { label: 'Users', value: '2' }, ]} + size='small' onChange={(v) => setType(v)} />
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx index 92a7db1f4..c36729632 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx @@ -13,10 +13,10 @@ function ExCard({ }) { return (
-
{title}
+
{title}
onCard(type)}>{children}
); diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx index 1b2de44e2..b6d35ef76 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx @@ -58,6 +58,7 @@ function ByUrl(props: any) { { label: 'Page Title', value: '1' }, ]} onChange={(v) => setMode(Number(v))} + size='small' />
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx index 5de714619..1e2cb8770 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx @@ -23,6 +23,7 @@ function ExampleTrend(props: any) { { label: 'Multi-Series', value: 'multi' }, ]} onChange={(v) => setIsMulti(v === 'multi')} + size='small' />
@@ -78,14 +79,14 @@ function ExampleTrend(props: any) { ) : null} -
+
-
CTA 1
+
Series 1
-
CTA 2
+
Series 2
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx index ae48e05af..79b26d019 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx @@ -25,7 +25,15 @@ const NewDashboardModal: React.FC = ({ return ( <> - +
{step === 0 && = (props: SelectCardProps) => { {/*/>*/} -
+
{dashboardId ? (isLibrary ? "Add Card" : "Create Card") : "Select a template to create a card"}
{isLibrary && ( @@ -124,6 +124,7 @@ const CategorySelector: React.FC = ({setSelected, selecte }))} value={selected} onChange={setSelected} + className='w-fit' /> ); @@ -134,7 +135,7 @@ interface ExampleCardsGridProps { const ExampleCardsGrid: React.FC = ({items}) => (
{items}
diff --git a/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx b/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx index 2ff69a334..1a1db124d 100644 --- a/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx @@ -1,6 +1,7 @@ import {useObserver} from 'mobx-react-lite'; import React from 'react'; import {Button, Modal, Form, Icon} from 'UI'; + import {useStore} from 'App/mstore' import Select from 'Shared/Select'; @@ -44,7 +45,7 @@ function DashboardSelectionModal(props: Props) { return useObserver(() => ( -
{'Add to selected dashboard'}
+
{'Add to selected dashboard'}
Add diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css index 42045607f..cda44bd57 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css @@ -2,4 +2,4 @@ & > tippy-popper > tippy-tooltip { padding: 0!important; } -} +} \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx index 7879ff095..cc3c08f92 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx @@ -23,7 +23,7 @@ function AddStepButton({series, excludeFilterKeys}: Props) { onFilterClick={onAddFilter} excludeFilterKeys={excludeFilterKeys} > - diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 36eb148f3..aa21ecea8 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -115,7 +115,7 @@ function FilterSeries(props: Props) { }; return ( -
+
{canExclude && } {!hideHeader && ( diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index da3c83c3f..e0513d416 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -59,7 +59,7 @@ function FunnelIssues() { return useObserver(() => (
-

Most significant issues identified in this funnel

+

Most significant issues identified in this funnel

diff --git a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx index 10778d064..867cb03c3 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx @@ -184,12 +184,13 @@ const SeriesList = observer(() => {
))} {hasSeries && ( - + diff --git a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx index 63f296cb0..262916873 100644 --- a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx +++ b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {List, Progress, Typography} from "antd"; +import { List, Progress, Typography } from "antd"; import cn from "classnames"; interface Props { @@ -8,7 +8,7 @@ interface Props { onClickHandler: (event: any, data: any) => void; } -function CardSessionsByList({list, selected, onClickHandler}: Props) { +function CardSessionsByList({ list, selected, onClickHandler }: Props) { return ( ( onClickHandler(e, row)} + onClick={(e) => onClickHandler(e, row)} // Remove onClick handler to disable click interaction style={{ borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', padding: '4px 10px', lineHeight: '1px' }} - className={cn('rounded hover:bg-active-blue cursor-pointer', selected === row.name ? 'bg-active-blue' : '')} + className={cn('rounded', selected === row.name ? 'bg-active-blue' : '')} // Remove hover:bg-active-blue and cursor-pointer >
- {row.name} + {row.name} {row.sessionCount}
diff --git a/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx b/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx index 2ea7d1153..09fb1eb1a 100644 --- a/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx +++ b/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx @@ -26,7 +26,7 @@ function AlertsView({ siteId }: IAlertsView) { return unmount; }, [history]); return ( -
+
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index c4ef9f2d6..77350083e 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -74,40 +74,22 @@ function DashboardList({siteId}: { siteId: string }) { return ( list.length === 0 && !dashboardStore.filter.showMine ? ( } + image={} + imageStyle={{height: 300}} description={(
- {dashboardsSearch !== '' - ? - No matching results +
+ + Create your first dashboard. - : ( -
- - You haven't created any dashboards yet - -
- A Dashboard is a collection of{' '} - - Utilize cards to visualize key user interactions or product - performance metrics. -
- } - className="text-center" - > - Cards - {' '} - that can be shared across teams. -
- -
- -
-
- )} +
+ Organize your product and technical insights as cards in dashboards to see the bigger picture,
take action and improve user experience. +
+
+ +
+
)} /> @@ -132,6 +114,7 @@ function DashboardList({siteId}: { siteId: string }) { })} />) ); + } export default connect((state: any) => ({ diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx index bb3a152b9..829852dd9 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx @@ -5,7 +5,7 @@ import Header from './Header'; function DashboardsView({history, siteId}: { history: any; siteId: string }) { return ( -
+
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx index df4d8a3fb..22ac90d79 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CreateCard.tsx @@ -83,7 +83,7 @@ function CreateCard(props: Props) { -
+
{metric.name}
@@ -94,7 +94,7 @@ function CreateCard(props: Props) {
- +
); } diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx index 1f21a6c9a..044824ab0 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Count.tsx @@ -9,6 +9,7 @@ import { import React from 'react'; import ExCard from './ExCard'; +import { size } from '@floating-ui/react-dom-interactions'; const TYPES = { Frustrations: 'frustrations', @@ -37,6 +38,7 @@ function ExampleCount(props: any) { { label: 'Errors', value: '1' }, { label: 'Users', value: '2' }, ]} + size='small' onChange={(v) => setType(v)} />
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx index b055c81fd..8fbe5e865 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx @@ -13,15 +13,15 @@ function ExCard({ onCard: (card: string) => void; height?: number; }) { - return ( -
-
{title}
-
onCard(type)}>{children}
-
- ); + return ( +
+
{title}
+
onCard(type)}>{children}
+
+ ); } export default ExCard diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx index 1b2de44e2..b6d35ef76 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx @@ -58,6 +58,7 @@ function ByUrl(props: any) { { label: 'Page Title', value: '1' }, ]} onChange={(v) => setMode(Number(v))} + size='small' />
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx index 5de714619..1e2cb8770 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx @@ -23,6 +23,7 @@ function ExampleTrend(props: any) { { label: 'Multi-Series', value: 'multi' }, ]} onChange={(v) => setIsMulti(v === 'multi')} + size='small' />
@@ -78,14 +79,14 @@ function ExampleTrend(props: any) {
) : null}
-
+
-
CTA 1
+
Series 1
-
CTA 2
+
Series 2
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx index ae48e05af..79b26d019 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx @@ -25,7 +25,15 @@ const NewDashboardModal: React.FC = ({ return ( <> - +
{step === 0 && = (props: SelectCardProps) => { {/*/>*/} -
+
{dashboardId ? (isLibrary ? "Add Card" : "Create Card") : "Select a template to create a card"}
{isLibrary && ( @@ -125,6 +125,7 @@ const CategorySelector: React.FC = ({setSelected, selecte }))} value={selected} onChange={setSelected} + className='w-fit' /> ); @@ -135,7 +136,7 @@ interface ExampleCardsGridProps { const ExampleCardsGrid: React.FC = ({items}) => (
{items}
diff --git a/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx b/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx index 2ff69a334..1a1db124d 100644 --- a/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardSelectionModal/DashboardSelectionModal.tsx @@ -1,6 +1,7 @@ import {useObserver} from 'mobx-react-lite'; import React from 'react'; import {Button, Modal, Form, Icon} from 'UI'; + import {useStore} from 'App/mstore' import Select from 'Shared/Select'; @@ -44,7 +45,7 @@ function DashboardSelectionModal(props: Props) { return useObserver(() => ( -
{'Add to selected dashboard'}
+
{'Add to selected dashboard'}
Add diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css index 42045607f..cda44bd57 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.module.css @@ -2,4 +2,4 @@ & > tippy-popper > tippy-tooltip { padding: 0!important; } -} +} \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx index 7879ff095..cc3c08f92 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx @@ -23,7 +23,7 @@ function AddStepButton({series, excludeFilterKeys}: Props) { onFilterClick={onAddFilter} excludeFilterKeys={excludeFilterKeys} > - diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 36eb148f3..aa21ecea8 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -115,7 +115,7 @@ function FilterSeries(props: Props) { }; return ( -
+
{canExclude && } {!hideHeader && ( diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index da3c83c3f..e0513d416 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -59,7 +59,7 @@ function FunnelIssues() { return useObserver(() => (
-

Most significant issues identified in this funnel

+

Most significant issues identified in this funnel

diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx index fa7ce7019..5edeec2d9 100644 --- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx +++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx @@ -9,7 +9,7 @@ interface Props { } function MetricsView({ siteId }: Props) { return useObserver(() => ( -
+
diff --git a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx index 10778d064..867cb03c3 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx @@ -184,12 +184,13 @@ const SeriesList = observer(() => {
))} {hasSeries && ( - + diff --git a/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx b/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx index da0e49935..8666ffbdb 100644 --- a/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx @@ -57,7 +57,7 @@ function DashboardEditModal(props: Props) { /> - + {/* - + */}
diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 174a97fba..837315497 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -20,6 +20,7 @@ interface IProps { renderReport?: any; } + type Props = IProps & RouteComponentProps; const MAX_CARDS = 29; @@ -43,7 +44,7 @@ function DashboardHeader(props: Props) { const onDelete = async () => { if ( await confirm({ - header: 'Confirm', + header: 'Delete Dashboard', confirmButton: 'Yes, delete', confirmation: `Are you sure you want to permanently delete this Dashboard?`, }) @@ -82,11 +83,11 @@ function DashboardHeader(props: Props) { className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer" />
-
+
-
+
dashboardStore.setPeriod(period)} right={true} + isAnt={true} + useButtonStyle={true} />
-
+
onEdit(false)} > - {dashboard?.description || 'Describe the purpose of this dashboard'} + {/* {dashboard?.description || 'Describe the purpose of this dashboard'} */}
diff --git a/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx b/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx index 0c170a9f8..bd8860c16 100644 --- a/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx +++ b/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx @@ -14,7 +14,7 @@ function DashboardOptions(props: Props) { const { editHandler, deleteHandler, renderReport, isEnterprise, isTitlePresent } = props; const menuItems = [ { icon: 'pencil', text: 'Rename', onClick: () => editHandler(true) }, - { icon: 'text-paragraph', text: `${!isTitlePresent ? 'Add' : 'Edit'} Description`, onClick: () => editHandler(false) }, + // { icon: 'text-paragraph', text: `${!isTitlePresent ? 'Add' : 'Edit'} Description`, onClick: () => editHandler(false) }, { icon: 'users', text: 'Visibility & Access', onClick: editHandler }, { icon: 'trash', text: 'Delete', onClick: deleteHandler }, { icon: 'pdf-download', text: 'Download Report', onClick: renderReport, disabled: !isEnterprise, tooltipTitle: ENTERPRISE_REQUEIRED } @@ -23,7 +23,6 @@ function DashboardOptions(props: Props) { return ( ); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index bbd945f0b..b318855ef 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -42,7 +42,7 @@ function DashboardWidgetGrid(props: Props) { show={list?.length === 0} icon="no-metrics-chart" title={ -
+
There are no cards in this dashboard diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx index 49a22e3a1..e32246b8f 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx @@ -1,48 +1,47 @@ import React from 'react'; -import cn from "classnames"; -import WidgetName from "Components/Dashboard/components/WidgetName"; -import {useStore} from "App/mstore"; -import {useObserver} from "mobx-react-lite"; -import AddToDashboardButton from "Components/Dashboard/components/AddToDashboardButton"; -import WidgetDateRange from "Components/Dashboard/components/WidgetDateRange/WidgetDateRange"; -import {Button, Space} from "antd"; -import CardViewMenu from "Components/Dashboard/components/WidgetView/CardViewMenu"; +import cn from 'classnames'; +import WidgetName from 'Components/Dashboard/components/WidgetName'; +import { useStore } from 'App/mstore'; +import { useObserver } from 'mobx-react-lite'; +import AddToDashboardButton from 'Components/Dashboard/components/AddToDashboardButton'; +import WidgetDateRange from 'Components/Dashboard/components/WidgetDateRange/WidgetDateRange'; +import { Button, Space } from 'antd'; +import CardViewMenu from 'Components/Dashboard/components/WidgetView/CardViewMenu'; interface Props { - onClick?: () => void; - onSave: () => void; - undoChanges?: () => void; + onClick?: () => void; + onSave: () => void; + undoChanges?: () => void; } -function WidgetViewHeader({onClick, onSave, undoChanges}: Props) { - const {metricStore, dashboardStore} = useStore(); - const widget = useObserver(() => metricStore.instance); +function WidgetViewHeader({ onClick, onSave, undoChanges }: Props) { + const { metricStore, dashboardStore } = useStore(); + const widget = useObserver(() => metricStore.instance); - return ( -
+

+ metricStore.merge({ name })} + canEdit={true} + /> +

+ + + + - - -
- ); + {metricStore.isSaving ? 'Saving...' : 'Update'} + + + +
+ ); } export default WidgetViewHeader; diff --git a/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx b/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx index ef2240e78..821c94959 100644 --- a/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx +++ b/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx @@ -2,7 +2,8 @@ import React from 'react'; import SessionSearchField from 'Shared/SessionSearchField'; import AiSessionSearchField from 'Shared/SessionSearchField/AiSessionSearchField'; import SavedSearch from 'Shared/SavedSearch'; -import { Button } from 'UI'; +// import { Button } from 'UI'; +import { Button } from 'antd'; import { connect } from 'react-redux'; import { clearSearch } from 'Duck/search'; import TagList from './components/TagList'; @@ -41,10 +42,12 @@ const MainSearchBar = (props: Props) => { diff --git a/frontend/app/components/shared/MainSearchBar/components/TagList.tsx b/frontend/app/components/shared/MainSearchBar/components/TagList.tsx index 0f1bdbc92..983622a32 100644 --- a/frontend/app/components/shared/MainSearchBar/components/TagList.tsx +++ b/frontend/app/components/shared/MainSearchBar/components/TagList.tsx @@ -7,8 +7,8 @@ import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { FilterKey } from 'Types/filter/filterType'; import { addOptionsToFilter } from 'Types/filter/newFilter'; -import { Button, Icon, confirm } from 'UI'; -import { Typography } from 'antd'; +import { Icon, confirm } from 'UI'; +import { Button, Typography } from 'antd'; import { toast } from 'react-toastify'; function TagList(props: { @@ -44,9 +44,15 @@ function TagList(props: { }); }; return ( - ); } diff --git a/frontend/app/components/shared/SavedSearch/SavedSearch.tsx b/frontend/app/components/shared/SavedSearch/SavedSearch.tsx index f5cdfb889..5770d5e76 100644 --- a/frontend/app/components/shared/SavedSearch/SavedSearch.tsx +++ b/frontend/app/components/shared/SavedSearch/SavedSearch.tsx @@ -1,5 +1,6 @@ import React, { useEffect } from 'react'; -import { Button, Icon } from 'UI'; +import { Icon } from 'UI'; +import { Button } from 'antd'; import { connect } from 'react-redux'; import { fetchList as fetchListSavedSearch } from 'Duck/search'; import cn from 'classnames'; @@ -27,11 +28,14 @@ function SavedSearch(props: Props) { return (
{ savedSearch.exists() && ( diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index 706f2d0fc..b1173b315 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -1,6 +1,6 @@ import { DownOutlined } from '@ant-design/icons'; import Period from 'Types/app/period'; -import { Dropdown, DatePicker } from 'antd'; +import { Dropdown, Button } from 'antd'; import cn from 'classnames'; import { observer } from 'mobx-react-lite'; import React from 'react'; @@ -20,14 +20,14 @@ interface Props { timezone?: string; isAnt?: boolean; small?: boolean; + useButtonStyle?: boolean; // New prop to control button style [x: string]: any; } function SelectDateRange(props: Props) { const [isCustom, setIsCustom] = React.useState(false); - const [isCustomOpen, setIsCustomOpen] = React.useState(false); - const { right = false, period, disableCustom = false, timezone } = props; + const { right = false, period, disableCustom = false, timezone, useButtonStyle = false } = props; let selectedValue = DATE_RANGE_OPTIONS.find( (obj: any) => obj.value === period.rangeName ); @@ -41,13 +41,11 @@ function SelectDateRange(props: Props) { setIsCustom(true); }, 1); } else { - // @ts-ignore props.onChange(new Period({ rangeName: value })); } }; const onApplyDateRange = (value: any) => { - // @ts-ignore const range = new Period({ rangeName: CUSTOM_RANGE, start: value.start, @@ -61,34 +59,31 @@ function SelectDateRange(props: Props) { const customRange = isCustomRange ? period.rangeFormatted() : ''; if (props.isAnt) { - const onAntUpdate = (val: any) => { - onChange(val); + const menuProps = { + items: options.map((opt) => ({ + label: opt.label, + key: opt.value, + })), + defaultSelectedKeys: selectedValue?.value ? [selectedValue.value] : undefined, + onClick: (e: any) => { + onChange(e.key); + }, }; + return (
- ({ - label: opt.label, - key: opt.value, - })), - defaultSelectedKeys: selectedValue?.value - ? [selectedValue.value] - : undefined, - onClick: (e: any) => { - onChange(e.key); - }, - }} - onChange={onAntUpdate} - style={{ width: 170 }} - defaultValue={selectedValue?.value ?? undefined} - > -
-
{isCustomRange ? customRange : selectedValue?.label}
- -
+ + {useButtonStyle ? ( + + ) : ( +
+ {isCustomRange ? customRange : selectedValue?.label} + +
+ )}
{isCustom && (
); } + return (
- + */}
diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 174a97fba..837315497 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -20,6 +20,7 @@ interface IProps { renderReport?: any; } + type Props = IProps & RouteComponentProps; const MAX_CARDS = 29; @@ -43,7 +44,7 @@ function DashboardHeader(props: Props) { const onDelete = async () => { if ( await confirm({ - header: 'Confirm', + header: 'Delete Dashboard', confirmButton: 'Yes, delete', confirmation: `Are you sure you want to permanently delete this Dashboard?`, }) @@ -82,11 +83,11 @@ function DashboardHeader(props: Props) { className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer" />
-
+
-
+
dashboardStore.setPeriod(period)} right={true} + isAnt={true} + useButtonStyle={true} />
-
+
onEdit(false)} > - {dashboard?.description || 'Describe the purpose of this dashboard'} + {/* {dashboard?.description || 'Describe the purpose of this dashboard'} */}
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx index f741e4073..5294648a2 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx @@ -19,9 +19,9 @@ function ExCard({ style={{width: '100%', height: height || 286}} >
{title}
-
onCard(type)}>{children}
+
onCard(type)}>{children}
); } diff --git a/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx b/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx index 0c170a9f8..bd8860c16 100644 --- a/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx +++ b/frontend/app/components/Dashboard/components/DashboardOptions/DashboardOptions.tsx @@ -14,7 +14,7 @@ function DashboardOptions(props: Props) { const { editHandler, deleteHandler, renderReport, isEnterprise, isTitlePresent } = props; const menuItems = [ { icon: 'pencil', text: 'Rename', onClick: () => editHandler(true) }, - { icon: 'text-paragraph', text: `${!isTitlePresent ? 'Add' : 'Edit'} Description`, onClick: () => editHandler(false) }, + // { icon: 'text-paragraph', text: `${!isTitlePresent ? 'Add' : 'Edit'} Description`, onClick: () => editHandler(false) }, { icon: 'users', text: 'Visibility & Access', onClick: editHandler }, { icon: 'trash', text: 'Delete', onClick: deleteHandler }, { icon: 'pdf-download', text: 'Download Report', onClick: renderReport, disabled: !isEnterprise, tooltipTitle: ENTERPRISE_REQUEIRED } @@ -23,7 +23,6 @@ function DashboardOptions(props: Props) { return ( ); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index bbd945f0b..b318855ef 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -42,7 +42,7 @@ function DashboardWidgetGrid(props: Props) { show={list?.length === 0} icon="no-metrics-chart" title={ -
+
There are no cards in this dashboard diff --git a/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx b/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx index ef2240e78..821c94959 100644 --- a/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx +++ b/frontend/app/components/shared/MainSearchBar/MainSearchBar.tsx @@ -2,7 +2,8 @@ import React from 'react'; import SessionSearchField from 'Shared/SessionSearchField'; import AiSessionSearchField from 'Shared/SessionSearchField/AiSessionSearchField'; import SavedSearch from 'Shared/SavedSearch'; -import { Button } from 'UI'; +// import { Button } from 'UI'; +import { Button } from 'antd'; import { connect } from 'react-redux'; import { clearSearch } from 'Duck/search'; import TagList from './components/TagList'; @@ -41,10 +42,12 @@ const MainSearchBar = (props: Props) => { diff --git a/frontend/app/components/shared/MainSearchBar/components/TagList.tsx b/frontend/app/components/shared/MainSearchBar/components/TagList.tsx index 0f1bdbc92..983622a32 100644 --- a/frontend/app/components/shared/MainSearchBar/components/TagList.tsx +++ b/frontend/app/components/shared/MainSearchBar/components/TagList.tsx @@ -7,8 +7,8 @@ import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { FilterKey } from 'Types/filter/filterType'; import { addOptionsToFilter } from 'Types/filter/newFilter'; -import { Button, Icon, confirm } from 'UI'; -import { Typography } from 'antd'; +import { Icon, confirm } from 'UI'; +import { Button, Typography } from 'antd'; import { toast } from 'react-toastify'; function TagList(props: { @@ -44,9 +44,15 @@ function TagList(props: { }); }; return ( - ); } diff --git a/frontend/app/components/shared/SavedSearch/SavedSearch.tsx b/frontend/app/components/shared/SavedSearch/SavedSearch.tsx index f5cdfb889..5770d5e76 100644 --- a/frontend/app/components/shared/SavedSearch/SavedSearch.tsx +++ b/frontend/app/components/shared/SavedSearch/SavedSearch.tsx @@ -1,5 +1,6 @@ import React, { useEffect } from 'react'; -import { Button, Icon } from 'UI'; +import { Icon } from 'UI'; +import { Button } from 'antd'; import { connect } from 'react-redux'; import { fetchList as fetchListSavedSearch } from 'Duck/search'; import cn from 'classnames'; @@ -27,11 +28,14 @@ function SavedSearch(props: Props) { return (
{ savedSearch.exists() && ( diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index 706f2d0fc..b1173b315 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -1,6 +1,6 @@ import { DownOutlined } from '@ant-design/icons'; import Period from 'Types/app/period'; -import { Dropdown, DatePicker } from 'antd'; +import { Dropdown, Button } from 'antd'; import cn from 'classnames'; import { observer } from 'mobx-react-lite'; import React from 'react'; @@ -20,14 +20,14 @@ interface Props { timezone?: string; isAnt?: boolean; small?: boolean; + useButtonStyle?: boolean; // New prop to control button style [x: string]: any; } function SelectDateRange(props: Props) { const [isCustom, setIsCustom] = React.useState(false); - const [isCustomOpen, setIsCustomOpen] = React.useState(false); - const { right = false, period, disableCustom = false, timezone } = props; + const { right = false, period, disableCustom = false, timezone, useButtonStyle = false } = props; let selectedValue = DATE_RANGE_OPTIONS.find( (obj: any) => obj.value === period.rangeName ); @@ -41,13 +41,11 @@ function SelectDateRange(props: Props) { setIsCustom(true); }, 1); } else { - // @ts-ignore props.onChange(new Period({ rangeName: value })); } }; const onApplyDateRange = (value: any) => { - // @ts-ignore const range = new Period({ rangeName: CUSTOM_RANGE, start: value.start, @@ -61,34 +59,31 @@ function SelectDateRange(props: Props) { const customRange = isCustomRange ? period.rangeFormatted() : ''; if (props.isAnt) { - const onAntUpdate = (val: any) => { - onChange(val); + const menuProps = { + items: options.map((opt) => ({ + label: opt.label, + key: opt.value, + })), + defaultSelectedKeys: selectedValue?.value ? [selectedValue.value] : undefined, + onClick: (e: any) => { + onChange(e.key); + }, }; + return (
- ({ - label: opt.label, - key: opt.value, - })), - defaultSelectedKeys: selectedValue?.value - ? [selectedValue.value] - : undefined, - onClick: (e: any) => { - onChange(e.key); - }, - }} - onChange={onAntUpdate} - style={{ width: 170 }} - defaultValue={selectedValue?.value ?? undefined} - > -
-
{isCustomRange ? customRange : selectedValue?.label}
- -
+ + {useButtonStyle ? ( + + ) : ( +
+ {isCustomRange ? customRange : selectedValue?.label} + +
+ )}
{isCustom && (
); } + return (
+
+ Array.from({length: pointsPerMonth}, (_, pointIndex) => ({ + time: month, + "Series 1": Math.floor(Math.random() * 90), + timestamp: Date.now() + (monthIndex * pointsPerMonth + pointIndex) * 86400000 + })) + ); + + return data; +} + +function generateAreaData(): any[] { + const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"]; + const pointsPerMonth = 3; // Number of points for each month + + const data = months.flatMap((month, monthIndex) => + Array.from({length: pointsPerMonth}, (_, pointIndex) => ({ + time: month, + "value": Math.floor(Math.random() * 90), + timestamp: Date.now() + (monthIndex * pointsPerMonth + pointIndex) * 86400000 + })) + ); + + return data; +} + +function generateRandomValue(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function generateBarChartDate(): any[] { + const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']; + return months.map(month => ({ + time: month, + value: generateRandomValue(1000, 5000), + })); +} diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx new file mode 100644 index 000000000..d50fcab52 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import {NoContent} from 'UI'; + +import { + AreaChart, Area, + CartesianGrid, Tooltip, + ResponsiveContainer, + XAxis, YAxis +} from 'recharts'; +import {NO_METRIC_DATA} from 'App/constants/messages' +import {AvgLabel, Styles} from "Components/Dashboard/Widgets/common"; +import ExCard from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard"; + +interface Props { + title: string; + type: string; + onCard: (card: string) => void; + onClick?: any; + data?: any, +} + +// interface Props { +// data: any, +// label?: string +// } + +function AreaChartCard(props: Props) { + const {data} = props; + const gradientDef = Styles.gradientDef(); + + return ( + +
{props.title}
+ + } + > + + <> + {/*
*/} + {/* */} + {/*
*/} + + + {gradientDef} + + + Styles.tickFormatter(val)} + label={{...Styles.axisLabelLeft, value: data?.label}} + /> + + + + + +
+
+ ); +} + +export default AreaChartCard; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx index 1283062d9..a34bda906 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx @@ -6,64 +6,60 @@ import {PERFORMANCE} from "App/constants/card"; import {Bar, BarChart, CartesianGrid, Legend, Rectangle, ResponsiveContainer, Tooltip, XAxis, YAxis} from "recharts"; import {Styles} from "Components/Dashboard/Widgets/common"; -const _data = [ - { - name: 'Jan', - uv: 4000, - pv: 2400, - }, - { - name: 'Feb', - uv: 3000, - pv: 1398, - }, - { - name: 'Mar', - uv: 2000, - pv: 9800, - }, - { - name: 'Apr', - uv: 2780, - pv: 3908, - }, - { - name: 'May', - uv: 1890, - pv: 4800, - }, - { - name: 'Jun', - uv: 2390, - pv: 3800, - }, - { - name: 'Jul', - uv: 3490, - pv: 4300, - }, -]; +interface Props { + title: string; + type: string; + onCard: (card: string) => void; + onClick?: any; + data?: any, +} -function BarChartCard(props: any) { +function BarChartCard(props: Props) { return ( - + {/**/} + {/* */} + {/* /!**!/*/} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* }/>*/} + {/* /!*}/>*!/*/} + {/* */} + {/**/} + + - {/**/} - - - + + Styles.tickFormatter(val)} + label={{...Styles.axisLabelLeft, value: "Number of Errors"}} + allowDecimals={false} + /> - }/> - {/*}/>*/} + + One} + dataKey="value" stackId="a" fill={Styles.colors[0]}/> + {/*3rd Party} dataKey="thirdParty" stackId="a"*/} + {/* fill={Styles.colors[2]}/>*/} diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/CallsWithErrorsExample.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/CallsWithErrorsExample.tsx new file mode 100644 index 000000000..c07c7f82b --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/CallsWithErrorsExample.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import ExCard from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard"; +import CallWithErrors from "Components/Dashboard/Widgets/PredefinedWidgets/CallWithErrors"; + +interface Props { + title: string; + type: string; + onCard: (card: string) => void; + onClick?: any; + data?: any, +} + +function CallsWithErrorsExample(props: Props) { + return ( + + + + ); +} + +export default CallsWithErrorsExample; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx index be2938e65..ccd9f3dc8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx @@ -13,17 +13,18 @@ function ExCard({ onCard: (card: string) => void; height?: number; }) { - return ( -
-
{title}
-
onCard(type)}>{children}
-
- ); + console.log(type) + return ( +
+
{title}
+
onCard(type)}>{children}
+
+ ); } export default ExCard diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUser.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUser.tsx index fd18227f0..074731dd7 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUser.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUser.tsx @@ -1,52 +1,53 @@ import React from 'react'; -import { Icon } from 'UI'; +import {Avatar, Icon} from 'UI'; import ExCard from '../ExCard'; import ByComponent from './Component'; +import {hashString} from "Types/session/session"; function ByUser(props: any) { - const rows = [ - { - label: 'Demo User', - progress: 85, - value: '2.5K', - icon: , - }, - { - label: 'Admin User', - progress: 25, - value: '405', - icon: , - }, - { - label: 'Management User', - progress: 5, - value: '302', - icon: , - }, - { - label: 'Sales User', - progress: 3, - value: '194', - icon: , - }, - { - label: 'Marketing User', - progress: 1, - value: '57', - icon: , - }, - ]; + const rows = [ + { + label: 'Demo User', + progress: 85, + value: '2.5K', + icon: , + }, + { + label: 'Admin User', + progress: 25, + value: '405', + icon: , + }, + { + label: 'Management User', + progress: 5, + value: '302', + icon: , + }, + { + label: 'Sales User', + progress: 3, + value: '194', + icon: , + }, + { + label: 'Marketing User', + progress: 1, + value: '57', + icon: , + }, + ]; - const lineWidth = 200; - return ( - - ); + const lineWidth = 200; + return ( + + ); } export default ByUser; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx index 1e2cb8770..611df39ff 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx @@ -1,96 +1,43 @@ -import { Segmented } from 'antd'; import React from 'react'; import ExCard from './ExCard'; +import AreaChartCard from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard"; +import CustomMetricLineChart from "Components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart"; +import {Styles} from "Components/Dashboard/Widgets/common"; -function ExampleTrend(props: any) { - const rows = [50, 40, 30, 20, 10]; - const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May']; +interface Props { + title: string; + type: string; + onCard: (card: string) => void; + onClick?: any; + data?: any, +} - const [isMulti, setIsMulti] = React.useState(false); - return ( - -
{props.title}
-
- setIsMulti(v === 'multi')} - size='small' - /> -
- - } - > -
-
- {rows.map((r) => ( -
-
{r}K
-
-
- ))} -
-
- {months.map((m) => ( -
{m}
- ))} -
- -
- - +
{props.title}
+
+ } + > + {/**/} + - -
- {isMulti ? ( -
- - - -
- ) : null} - -
-
-
-
Series 1
-
-
-
-
Series 2
-
-
- - ); + + ); } export default ExampleTrend; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx index 37f7fb980..8a1ea4a35 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx @@ -22,6 +22,7 @@ const SelectCard: React.FC = (props: SelectCardProps) => { const [libraryQuery, setLibraryQuery] = React.useState(''); const handleCardSelection = (card: string) => { + metricStore.init(); const selectedCard = CARD_LIST.find((c) => c.key === card) as CardType; const cardData: any = { diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 32c63c5e6..c36d44558 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -1,5 +1,5 @@ import React, {useState, useRef, useEffect} from 'react'; -import CustomMetriLineChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart'; +import CustomMetricLineChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart'; import CustomMetricPercentage from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage'; import CustomMetricTable from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable'; import CustomMetricPieChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart'; @@ -141,7 +141,7 @@ function WidgetChart(props: Props) { if (metricType === TIMESERIES) { if (viewType === 'lineChart') { return ( - case FilterKey.CALLS_ERRORS: - return + return // PERFORMANCE case FilterKey.IMPACTED_SESSIONS_BY_SLOW_PAGES: diff --git a/frontend/app/mstore/types/IconProvider.tsx b/frontend/app/mstore/types/IconProvider.tsx index d2d371879..061367bfe 100644 --- a/frontend/app/mstore/types/IconProvider.tsx +++ b/frontend/app/mstore/types/IconProvider.tsx @@ -1,6 +1,7 @@ -import {Icon} from "UI"; +import {Avatar, Icon} from "UI"; import React from "react"; import * as Flags from "country-flag-icons/react/3x2"; +import {hashString} from "Types/session/session"; interface IconProvider { getIcon(name: string): React.ReactNode; @@ -108,7 +109,7 @@ class OsIconProvider implements IconProvider { class UserIconProvider implements IconProvider { getIcon(name: string): React.ReactNode { - return + return } } diff --git a/frontend/app/mstore/types/filter.ts b/frontend/app/mstore/types/filter.ts index a1a4009fb..f4cbbd707 100644 --- a/frontend/app/mstore/types/filter.ts +++ b/frontend/app/mstore/types/filter.ts @@ -128,7 +128,7 @@ export default class Filter { addFunnelDefaultFilters() { this.filters = [] - this.addFilter({...filtersMap[FilterKey.CLICK], value: [''], operator: 'onAny'}) + this.addFilter({...filtersMap[FilterKey.LOCATION], value: [''], operator: 'isAny'}) this.addFilter({...filtersMap[FilterKey.CLICK], value: [''], operator: 'onAny'}) } } diff --git a/frontend/app/types/session/session.ts b/frontend/app/types/session/session.ts index f47a51e37..f109315e4 100644 --- a/frontend/app/types/session/session.ts +++ b/frontend/app/types/session/session.ts @@ -41,7 +41,7 @@ export function sortEvents(a: Record, b: Record) { return aTs - bTs; } -function hashString(s: string): number { +export function hashString(s: string): number { let mul = 1; let hash = 0; for (let i = 0; i < s.length; i++) { From 0d8dcc1ecac9cd42c088be0836a51c139cb529f3 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 27 Jun 2024 17:50:43 +0200 Subject: [PATCH 34/66] change(ui): example cards with data --- .../components/DashboardList/NewDashModal/Examples/ExCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx index ccd9f3dc8..1d25a0a66 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx @@ -16,7 +16,7 @@ function ExCard({ console.log(type) return (
{title}
From 90c6b3b536f01c891030abdfbf0d34374ef0a45d Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 27 Jun 2024 17:57:41 +0200 Subject: [PATCH 35/66] change(ui): funnel bar text color --- .../Funnels/FunnelWidget/FunnelBar.tsx | 240 +++++++++--------- 1 file changed, 121 insertions(+), 119 deletions(-) diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx index 0ca634028..c4a35fded 100644 --- a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx +++ b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx @@ -1,146 +1,148 @@ -import { durationFormatted } from 'App/date'; +import {durationFormatted} from 'App/date'; import React from 'react'; import FunnelStepText from './FunnelStepText'; -import { Icon } from 'UI'; +import {Icon} from 'UI'; +import {Space} from "antd"; interface Props { - filter: any; - index?: number; - focusStage?: (index: number, isFocused: boolean) => void - focusedFilter?: number | null + filter: any; + index?: number; + focusStage?: (index: number, isFocused: boolean) => void + focusedFilter?: number | null } function FunnelBar(props: Props) { - const { filter, index, focusStage, focusedFilter } = props; + const {filter, index, focusStage, focusedFilter} = props; - const isFocused = focusedFilter && index ? focusedFilter === index - 1 : false; - return ( -
- -
-
-
- {filter.completedPercentageTotal}% -
-
-
focusStage?.(index! - 1, filter.isActive)} - className={'hover:border border-red-lightest'} - /> -
-
- {/* @ts-ignore */} -
- - {filter.sessionsCount} Sessions - + const isFocused = focusedFilter && index ? focusedFilter === index - 1 : false; + return ( +
+ +
+
+
+ {filter.completedPercentageTotal}% +
+
+
focusStage?.(index! - 1, filter.isActive)} + className={'hover:border border-red-lightest'} + /> +
+
+ {/* @ts-ignore */} +
+ + {filter.sessionsCount} Sessions + ({filter.completedPercentage}%) Completed +
+ + 0 ? "red" : "gray-light"} size={16}/> + 0 ? 'color-red' : 'disabled')}>{filter.droppedCount} Sessions + 0 ? 'color-red' : 'disabled')}>({filter.droppedPercentage}%) Dropped + +
- {/* @ts-ignore */} -
- - {filter.droppedCount} Sessions - ({filter.droppedPercentage}%) Dropped -
-
-
- ); + ); } export function UxTFunnelBar(props: Props) { - const { filter } = props; + const {filter} = props; - return ( -
-
{filter.title}
-
-
-
- {((filter.completed/(filter.completed+filter.skipped))*100).toFixed(1)}% -
-
-
-
- {/* @ts-ignore */} -
-
- - {filter.completed}completed this step -
-
- - + return ( +
+
{filter.title}
+
+
+
+ {((filter.completed / (filter.completed + filter.skipped)) * 100).toFixed(1)}% +
+
+
+
+ {/* @ts-ignore */} +
+
+ + {filter.completed}completed this step +
+
+ + {durationFormatted(filter.avgCompletionTime)} - + Avg. completion time -
+
+
+ {/* @ts-ignore */} +
+ + {filter.skipped} skipped +
+
- {/* @ts-ignore */} -
- - {filter.skipped} skipped -
-
-
- ); + ); } export default FunnelBar; const calculatePercentage = (completed: number, dropped: number) => { - const total = completed + dropped; - if (dropped === 0) return 100; - if (total === 0) return 0; + const total = completed + dropped; + if (dropped === 0) return 100; + if (total === 0) return 0; - return Math.round((completed / dropped) * 100); + return Math.round((completed / dropped) * 100); }; From 6f793582f607d2d6e338b0f5be70ef2ce1fb11bb Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 27 Jun 2024 18:05:50 +0200 Subject: [PATCH 36/66] change(ui): example cards overlay click --- .../components/DashboardList/NewDashModal/Examples/ExCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx index 1d25a0a66..b64fac0a8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard.tsx @@ -13,12 +13,12 @@ function ExCard({ onCard: (card: string) => void; height?: number; }) { - console.log(type) return (
+
onCard(type)}>
{title}
Date: Thu, 27 Jun 2024 18:15:06 +0200 Subject: [PATCH 37/66] change(ui): path analysis filter card --- .../components/WidgetForm/CardBuilder.tsx | 35 ++++++++++-------- .../components/WidgetForm/WidgetFormNew.tsx | 36 +++++++++++-------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx index 867cb03c3..b7066b5d8 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx @@ -53,7 +53,7 @@ const MetricTabs = ({metric, writeOption}: any) => { } return ( - + ) } @@ -138,19 +138,26 @@ const MetricOptions = ({metric, writeOption}: any) => { ); }; -const PathAnalysisFilter = ({metric}) => ( -
- {metric.startType === 'start' ? 'Start Point' : 'End Point'} - metric.updateStartPoint(val)} - onRemoveFilter={() => { - }} - /> -
-); +const PathAnalysisFilter = observer(({metric}: any) => ( + +
+ {/*{metric.startType === 'start' ? 'Start Point' : 'End Point'}*/} + metric.updateStartPoint(val)} + onRemoveFilter={() => { + }} + /> +
+
+)); const SeriesList = observer(() => { const {metricStore, dashboardStore, aiFiltersStore} = useStore(); diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx index 3050acb94..014d0f6bb 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx @@ -35,7 +35,7 @@ function WidgetFormNew() { const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes(metric.metricType); return isPredefined ? : ( - <> + )} - + ); } @@ -140,17 +140,23 @@ const FilterSection = observer(({metric, excludeFilterKeys}: any) => { const PathAnalysisFilter = observer(({metric}: any) => ( -
- {metric.startType === 'start' ? 'Start Point' : 'End Point'} - metric.updateStartPoint(val)} - onRemoveFilter={() => { - }} - /> -
+ +
+ metric.updateStartPoint(val)} + onRemoveFilter={() => { + }} + /> +
+
)); const AdditionalFilters = observer(() => { @@ -158,9 +164,9 @@ const AdditionalFilters = observer(() => { const metric: any = metricStore.instance; return ( - <> + {metric.metricType === USER_PATH && } - + ) }); From 38ccea4e816626d21e850c1425883358ba19db0c Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Thu, 27 Jun 2024 23:07:06 +0530 Subject: [PATCH 38/66] UI Improvements. --- .../components/DashboardWidgetGrid/DashboardWidgetGrid.tsx | 4 ++-- .../Dashboard/components/WidgetDateRange/WidgetDateRange.tsx | 2 ++ .../Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx | 4 ++-- frontend/app/components/ForgotPassword/ForgotPassword.tsx | 5 +++-- .../app/components/ForgotPassword/ResetPasswordRequest.tsx | 2 +- frontend/app/components/Login/Login.tsx | 2 +- frontend/app/components/ui/Input/Input.tsx | 4 ++-- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index b318855ef..3c7702139 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -59,7 +59,7 @@ function DashboardWidgetGrid(props: Props) { >
{smallWidgets.length > 0 ? ( <> -
+
Web Vitals
@@ -85,7 +85,7 @@ function DashboardWidgetGrid(props: Props) { ) : null} {smallWidgets.length > 0 && regularWidgets.length > 0 ? ( -
+
All Cards
diff --git a/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx b/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx index 2527b1f34..d795c45bc 100644 --- a/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx +++ b/frontend/app/components/Dashboard/components/WidgetDateRange/WidgetDateRange.tsx @@ -27,6 +27,8 @@ function WidgetDateRange({ period={period} onChange={onChangePeriod} right={true} + isAnt={true} + useButtonStyle={true} /> ); diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx index 8fb7bec07..043d0fc04 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx @@ -93,9 +93,9 @@ function WidgetWrapperNew(props: Props & RouteComponentProps) { return (
-
{'Back to Login'}
+
diff --git a/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx b/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx index 5c970457c..4be5b00c1 100644 --- a/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx +++ b/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx @@ -75,7 +75,7 @@ function ResetPasswordRequest(props: Props) { required /> - diff --git a/frontend/app/components/Login/Login.tsx b/frontend/app/components/Login/Login.tsx index 519f693c3..e59be3a85 100644 --- a/frontend/app/components/Login/Login.tsx +++ b/frontend/app/components/Login/Login.tsx @@ -141,7 +141,7 @@ const Login: React.FC = ({errors, loading, authDetails, login, setJw
- onClick(true)}> -
- - Add from library - {/*

Select from 12 available

*/} -
-
+
onClick(true)}> + + Add from library + {/*

Select from 12 available

*/} +
+ - onClick(false)}> -
- - Create New Card -
-
+
onClick(false)}> + + Create New Card +
diff --git a/frontend/app/components/Dashboard/components/CardIssues/CardIssues.tsx b/frontend/app/components/Dashboard/components/CardIssues/CardIssues.tsx index 9495d37d0..00f9eae9f 100644 --- a/frontend/app/components/Dashboard/components/CardIssues/CardIssues.tsx +++ b/frontend/app/components/Dashboard/components/CardIssues/CardIssues.tsx @@ -89,7 +89,7 @@ function CardIssues() { }; return useObserver(() => ( -
+

Issues

diff --git a/frontend/app/components/Dashboard/components/CardUserList/CardUserList.tsx b/frontend/app/components/Dashboard/components/CardUserList/CardUserList.tsx index 3cbc720b6..e8d330da3 100644 --- a/frontend/app/components/Dashboard/components/CardUserList/CardUserList.tsx +++ b/frontend/app/components/Dashboard/components/CardUserList/CardUserList.tsx @@ -41,7 +41,7 @@ function CardUserList(props: RouteComponentProps) { }, [userId]); return ( -
+

Returning users between

diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index e0513d416..f3d16ee9e 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -57,7 +57,7 @@ function FunnelIssues() { }, [stages.length, drillDownPeriod, filter.filters, depsString, metricStore.sessionsPage]); return useObserver(() => ( -
+

Most significant issues identified in this funnel

diff --git a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx index a90ff63f1..ff422216a 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx @@ -1,7 +1,7 @@ import {useHistory} from "react-router"; import {useStore} from "App/mstore"; import {useObserver} from "mobx-react-lite"; -import {Button, Drawer, Dropdown, MenuProps, message, Modal} from "antd"; +import {Button, Dropdown, MenuProps, message, Modal} from "antd"; import {BellIcon, EllipsisVertical, TrashIcon} from "lucide-react"; import {toast} from "react-toastify"; import React from "react"; @@ -36,8 +36,7 @@ const CardViewMenu = () => { }, { key: 'remove', - danger: true, - label: 'Remove', + label: 'Delete', icon: , onClick: () => { Modal.confirm({ diff --git a/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx b/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx index 4be5b00c1..2be473d3b 100644 --- a/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx +++ b/frontend/app/components/ForgotPassword/ResetPasswordRequest.tsx @@ -76,7 +76,7 @@ function ResetPasswordRequest(props: Props) { /> )} diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx index c4a35fded..6a37e91fe 100644 --- a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx +++ b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx @@ -54,7 +54,7 @@ function FunnelBar(props: Props) { cursor: 'pointer', }} onClick={() => focusStage?.(index! - 1, filter.isActive)} - className={'hover:border border-red-lightest'} + className={'hover:opacity-75'} />
diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx index 22f95d3c2..82a6e7e4b 100644 --- a/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx +++ b/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx @@ -5,6 +5,7 @@ import cn from 'classnames'; import stl from './FunnelWidget.module.css'; import { observer } from 'mobx-react-lite'; import { NoContent, Icon } from 'UI'; +import { Tag, Tooltip } from 'antd'; import { useModal } from 'App/components/Modal'; interface Props { @@ -90,19 +91,21 @@ function FunnelWidget(props: Props) {
- Lost conversion -
- {funnel.lostConversions} - ({funnel.lostConversionsPercentage}%) -
+ Lost conversion + + + {funnel.lostConversions} + +
- Total conversion -
- {funnel.totalConversions} - ({funnel.totalConversionsPercentage}%) -
+ Total conversion + + + {funnel.totalConversions} + +
{funnel.totalDropDueToIssues > 0 &&
{funnel.totalDropDueToIssues} sessions dropped due to issues.
} diff --git a/frontend/app/components/Signup/SignupForm/SignupForm.tsx b/frontend/app/components/Signup/SignupForm/SignupForm.tsx index ebc2ffe40..57b10e097 100644 --- a/frontend/app/components/Signup/SignupForm/SignupForm.tsx +++ b/frontend/app/components/Signup/SignupForm/SignupForm.tsx @@ -93,7 +93,7 @@ const SignupForm: React.FC = ({ tenants, errors, loading, signu
Logo
-
+

Create Account @@ -134,6 +134,7 @@ const SignupForm: React.FC = ({ tenants, errors, loading, signu onChange={write} required={true} icon='envelope' + className='rounded-lg' /> @@ -146,6 +147,7 @@ const SignupForm: React.FC = ({ tenants, errors, loading, signu onChange={write} required={true} icon='key' + className='rounded-lg' /> @@ -157,6 +159,7 @@ const SignupForm: React.FC = ({ tenants, errors, loading, signu onChange={write} required={true} icon='user-alt' + className='rounded-lg' /> @@ -168,13 +171,14 @@ const SignupForm: React.FC = ({ tenants, errors, loading, signu onChange={write} required={true} icon='buildings' + className='rounded-lg' /> {passwordError && ( // = ({ tenants, errors, loading, signu )} {errors && errors.length && ( )} -
From 21229f3ba669cd5118e9483d5bfb2aebe5c75538 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Fri, 28 Jun 2024 18:22:05 +0530 Subject: [PATCH 40/66] Various style improvements in dashboards --- .../CustomMetricOverviewChart.tsx | 2 +- .../CustomMetricsWidgets/SessionsBy.tsx | 4 +- .../DashboardEditModal/DashboardEditModal.tsx | 17 +-- .../DashboardHeader/DashboardHeader.tsx | 10 +- .../DashboardList/DashboardList.tsx | 105 ++++++++++-------- .../NewDashModal/CardsLibrary.tsx | 2 +- .../NewDashModal/Examples/ExCard.tsx | 2 +- .../DashboardList/NewDashModal/SelectCard.tsx | 4 +- .../DashboardWidgetGrid.tsx | 4 +- .../components/FilterSeries/AddStepButton.tsx | 4 +- .../FilterSeries/SeriesName/SeriesName.tsx | 5 +- .../Funnels/FunnelIssues/FunnelIssues.tsx | 2 +- .../components/WidgetForm/CardBuilder.tsx | 9 +- .../components/WidgetForm/WidgetForm.tsx | 9 +- .../components/WidgetForm/WidgetFormNew.tsx | 13 +-- .../components/WidgetName/WidgetName.tsx | 4 +- .../WidgetSessions/WidgetSessions.tsx | 2 +- .../components/WidgetView/WidgetView.tsx | 34 +++--- .../WidgetView/WidgetViewHeader.tsx | 3 +- .../components/WidgetWrapper/CardMenu.tsx | 2 +- frontend/app/components/Login/Login.tsx | 1 + .../FilterSelection/FilterSelection.tsx | 2 +- frontend/app/components/ui/Modal/Modal.tsx | 2 +- 23 files changed, 125 insertions(+), 117 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx index de6fb9c87..d892682f6 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx @@ -27,7 +27,7 @@ function CustomMetricOverviewChart(props: Props) { />

- + 3 && (
diff --git a/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx b/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx index 8666ffbdb..23fee3374 100644 --- a/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardEditModal/DashboardEditModal.tsx @@ -1,6 +1,8 @@ import { useObserver } from 'mobx-react-lite'; import React from 'react'; -import { Button, Modal, Form, Icon, Checkbox, Input } from 'UI'; +import { Modal, Form, Icon, Checkbox, Input } from 'UI'; +import {Button} from 'antd'; +import { CloseOutlined } from '@ant-design/icons'; import { useStore } from 'App/mstore' interface Props { @@ -32,14 +34,13 @@ function DashboardEditModal(props: Props) {
{ 'Edit Dashboard' }
- } /> +
@@ -91,13 +92,13 @@ function DashboardEditModal(props: Props) {
- +
diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 837315497..f0cc31b9b 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -61,7 +61,7 @@ function DashboardHeader(props: Props) { closeHandler={() => setShowEditModal(false)} focusTitle={focusTitle} /> - + /> */}
+ {dashboard?.name} } onDoubleClick={() => onEdit(true)} - className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer" + className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dashed hover:border-gray-medium cursor-pointer" />
@@ -112,7 +112,7 @@ function DashboardHeader(props: Props) {
{/* @ts-ignore */} - +

onEdit(false)} diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 77350083e..a9e634354 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -1,26 +1,25 @@ -import {LockOutlined, TeamOutlined} from '@ant-design/icons'; -import {Empty, Switch, Table, TableColumnsType, Tag, Tooltip, Typography} from 'antd'; -import {observer} from 'mobx-react-lite'; +import { LockOutlined, TeamOutlined } from '@ant-design/icons'; +import { Empty, Switch, Table, TableColumnsType, Tag, Tooltip, Typography } from 'antd'; +import { observer } from 'mobx-react-lite'; import React from 'react'; -import {connect} from 'react-redux'; -import {withRouter} from 'react-router-dom'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; -import {checkForRecent} from 'App/date'; -import {useStore} from 'App/mstore'; +import { checkForRecent } from 'App/date'; +import { useStore } from 'App/mstore'; import Dashboard from 'App/mstore/types/dashboard'; -import {dashboardSelected, withSiteId} from 'App/routes'; +import { dashboardSelected, withSiteId } from 'App/routes'; -import AnimatedSVG, {ICONS} from 'Shared/AnimatedSVG/AnimatedSVG'; +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import CreateDashboardButton from "Components/Dashboard/components/CreateDashboardButton"; -import {useHistory} from "react-router"; +import { useHistory } from "react-router"; -function DashboardList({siteId}: { siteId: string }) { - const {dashboardStore} = useStore(); +function DashboardList({ siteId }: { siteId: string }) { + const { dashboardStore } = useStore(); const list = dashboardStore.filteredList; const dashboardsSearch = dashboardStore.filter.query; const history = useHistory(); - const tableConfig: TableColumnsType = [ { title: 'Title', @@ -28,14 +27,6 @@ function DashboardList({siteId}: { siteId: string }) { width: '25%', render: (t) =>
{t}
, }, - { - title: 'Description', - ellipsis: { - showTitle: false, - }, - width: '25%', - dataIndex: 'description', - }, { title: 'Last Modified', dataIndex: 'updatedAt', @@ -53,45 +44,62 @@ function DashboardList({siteId}: { siteId: string }) { }, { title: ( -
+
Visibility
- - dashboardStore.updateKey('filter', { - ...dashboardStore.filter, - showMine: !dashboardStore.filter.showMine, - })} checkedChildren={'Public'} unCheckedChildren={'Private'}/> + + + dashboardStore.updateKey('filter', { + ...dashboardStore.filter, + showMine: !dashboardStore.filter.showMine, + })} checkedChildren={'Team'} unCheckedChildren={'Private'} /> +
), width: '16.67%', dataIndex: 'isPublic', render: (isPublic: boolean) => ( - : }> + : }> {isPublic ? 'Team' : 'Private'} ), }, ]; + + const emptyDescription = dashboardsSearch !== '' ? ( +
+
+ + No search results found. + +
+ Try adjusting your search criteria or creating a new dashboard. +
+
+
+ ) : ( +
+
+ + Create your first dashboard. + +
+ Organize your product and technical insights as cards in dashboards to see the bigger picture. +
+
+ +
+
+
+ ); + + const emptyImage = dashboardsSearch !== '' ? ICONS.NO_RESULTS : ICONS.NO_DASHBOARDS; + return ( list.length === 0 && !dashboardStore.filter.showMine ? ( } - - imageStyle={{height: 300}} - description={( -
-
- - Create your first dashboard. - -
- Organize your product and technical insights as cards in dashboards to see the bigger picture,
take action and improve user experience. -
-
- -
-
-
- )} + image={} + imageStyle={{ height: 300 }} + description={emptyDescription} /> ) : (

) + /> + ) ); - + } export default connect((state: any) => ({ diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx index 13b5e7d35..e000bd2d8 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary.tsx @@ -52,7 +52,7 @@ function CardsLibrary(props: Props) {
onItemClick(metric.metricId)}> -
onCard(type)}>
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx index 8a1ea4a35..f908fe004 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx @@ -73,7 +73,7 @@ const SelectCard: React.FC = (props: SelectCardProps) => { <>
- {dashboardId ? (isLibrary ? "Add Card" : "Create Card") : "Select a template to create a card"} + {dashboardId ? (isLibrary ? "Your Library" : "Create Card") : "Select a template to create a card"}
{isLibrary && ( @@ -84,7 +84,7 @@ const SelectCard: React.FC = (props: SelectCardProps) => { ) : ''} setLibraryQuery(value.target.value)} style={{width: 200}} /> diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index 3c7702139..de42e052b 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -59,7 +59,7 @@ function DashboardWidgetGrid(props: Props) { >
{smallWidgets.length > 0 ? ( <> -
+
Web Vitals
@@ -85,7 +85,7 @@ function DashboardWidgetGrid(props: Props) { ) : null} {smallWidgets.length > 0 && regularWidgets.length > 0 ? ( -
+
All Cards
diff --git a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx index cc3c08f92..55d005927 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/AddStepButton.tsx @@ -23,8 +23,8 @@ function AddStepButton({series, excludeFilterKeys}: Props) { onFilterClick={onAddFilter} excludeFilterKeys={excludeFilterKeys} > - ); diff --git a/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx b/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx index d6a69c73d..9c4f58a66 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx @@ -1,5 +1,6 @@ import React, { useState, useRef, useEffect } from 'react'; import { Icon } from 'UI'; +import {Input} from 'antd'; interface Props { name: string; @@ -35,15 +36,15 @@ function SeriesName(props: Props) { return (
{ editing ? ( - setEditing(true)} + className='bg-white' /> ) : (
{name && name.trim() === '' ? 'Series ' + (seriesIndex + 1) : name }
diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index f3d16ee9e..c30cf87c5 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -57,7 +57,7 @@ function FunnelIssues() { }, [stages.length, drillDownPeriod, filter.filters, depsString, metricStore.sessionsPage]); return useObserver(() => ( -
+

Most significant issues identified in this funnel

diff --git a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx index b7066b5d8..a7f883049 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx @@ -5,7 +5,7 @@ import {metricOf, issueOptions, issueCategories} from 'App/constants/filterOptio import {FilterKey} from 'Types/filter/filterType'; import {withSiteId, dashboardMetricDetails, metricDetails} from 'App/routes'; import {Icon, confirm} from 'UI'; -import {Card, Input, Space, Button, Segmented} from 'antd'; +import {Card, Input, Space, Button, Segmented, Alert} from 'antd'; import {AudioWaveform} from "lucide-react"; import FilterSeries from '../FilterSeries'; import Select from 'Shared/Select'; @@ -28,16 +28,13 @@ const AIInput = ({value, setValue, placeholder, onEnter}) => ( placeholder={placeholder} value={value} onChange={(e) => setValue(e.target.value)} - className='w-full mb-2' + className='w-full mb-2 bg-white' onKeyDown={(e) => e.key === 'Enter' && onEnter()} /> ); const PredefinedMessage = () => ( -
- -
Filtering and drill-downs will be supported soon for this card type.
-
+ ); const MetricTabs = ({metric, writeOption}: any) => { diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx index f85f0cce1..fe5730f25 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx @@ -4,6 +4,7 @@ import {FilterKey} from 'Types/filter/filterType'; import {useStore} from 'App/mstore'; import {observer} from 'mobx-react-lite'; import {Button, Icon, confirm, Tooltip} from 'UI'; +import {Input, Alert} from 'antd' import FilterSeries from '../FilterSeries'; import Select from 'Shared/Select'; import {withSiteId, dashboardMetricDetails, metricDetails} from 'App/routes'; @@ -26,7 +27,6 @@ import {eventKeys} from 'App/types/filter/newFilter'; import {renderClickmapThumbnail} from './renderMap'; import Widget from 'App/mstore/types/widget'; import FilterItem from 'Shared/Filters/FilterItem'; -import {Input} from 'antd' interface Props { history: any; @@ -261,12 +261,7 @@ function WidgetForm(props: Props) { )} {isPredefined && ( -
- -
- Filtering and drill-downs will be supported soon for this card type. -
-
+ )} {testingKey ? - Define Steps +
+ Filter - +
); } @@ -172,8 +172,5 @@ const AdditionalFilters = observer(() => { const PredefinedMessage = () => ( -
- -
Filtering and drill-downs will be supported soon for this card type.
-
+ ); diff --git a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx index 00abe60ec..ae3ab3355 100644 --- a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx +++ b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx @@ -1,5 +1,6 @@ import React, { useState, useRef, useEffect } from 'react'; import { Icon, Tooltip } from 'UI'; +import { Input } from 'antd'; import cn from 'classnames'; interface Props { @@ -53,10 +54,9 @@ function WidgetName(props: Props) { return (
{ editing ? ( - onBlur()} diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index f08cfff7c..a23d6ea10 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -115,7 +115,7 @@ function WidgetSessions(props: Props) { }; return ( -
+

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

diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index 02e586420..8202016ca 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -137,28 +137,34 @@ function WidgetView(props: Props) {
} > - - +
+
+ +
- +
+ +
{/*
*/} {/* */} {/*
*/} - +
+ - {widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ( - <> - {(widget.metricType === TABLE || widget.metricType === TIMESERIES || widget.metricType === CLICKMAP || widget.metricType === INSIGHTS) && - } - {widget.metricType === FUNNEL && } - - )} + {widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ( + <> + {(widget.metricType === TABLE || widget.metricType === TIMESERIES || widget.metricType === CLICKMAP || widget.metricType === INSIGHTS) && + } + {widget.metricType === FUNNEL && } + + )} - {widget.metricType === USER_PATH && } - {widget.metricType === RETENTION && } - + {widget.metricType === USER_PATH && } + {widget.metricType === RETENTION && } +
+
diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx index 49a22e3a1..ea0cbf829 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx @@ -26,7 +26,8 @@ function WidgetViewHeader({onClick, onSave, undoChanges}: Props) {

metricStore.merge({name})} - canEdit={true}/> + canEdit={true} + />

diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/CardMenu.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/CardMenu.tsx index c2d5494fb..90426a56c 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/CardMenu.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/CardMenu.tsx @@ -21,7 +21,7 @@ function CardMenu({card}: any) { }, { key: 'hide', - label: 'Hide', + label: 'Remove', icon: , }, ]; diff --git a/frontend/app/components/Login/Login.tsx b/frontend/app/components/Login/Login.tsx index e59be3a85..ca187b1d6 100644 --- a/frontend/app/components/Login/Login.tsx +++ b/frontend/app/components/Login/Login.tsx @@ -110,6 +110,7 @@ const Login: React.FC = ({errors, loading, authDetails, login, setJw onChange={(e) => setEmail(e.target.value)} required icon="envelope" + /> diff --git a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx index c8eb01438..b8de307bd 100644 --- a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx +++ b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx @@ -47,7 +47,7 @@ function FilterSelection(props: Props) { }) ) : (
setShowModal(true)} > diff --git a/frontend/app/components/ui/Modal/Modal.tsx b/frontend/app/components/ui/Modal/Modal.tsx index 8c1701fe6..3ebcf0c17 100644 --- a/frontend/app/components/ui/Modal/Modal.tsx +++ b/frontend/app/components/ui/Modal/Modal.tsx @@ -50,7 +50,7 @@ function Modal(props: Props) { style={{ zIndex: '9999', backgroundColor: 'rgba(0, 0, 0, 0.2)'}} onClick={handleClose} > -
+
{children}
From 82e36c05f6689fc765fdde5e7aea5c710586de03 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Fri, 28 Jun 2024 20:58:36 +0530 Subject: [PATCH 41/66] UI Improvements --- .../DashboardHeader/DashboardHeader.tsx | 28 ++++++++++++------- .../DashboardList/DashboardList.tsx | 17 +++++++++-- .../components/FilterSeries/AddStepButton.tsx | 2 +- .../shared/Breadcrumb/BackButton.tsx | 20 +++++++++++++ .../app/components/ui/PageTitle/PageTitle.tsx | 2 +- 5 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 frontend/app/components/shared/Breadcrumb/BackButton.tsx diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index f0cc31b9b..3a9fbeff5 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import Breadcrumb from 'Shared/Breadcrumb'; +//import {Breadcrumb} from 'Shared/Breadcrumb'; +import BackButton from '../../../shared/Breadcrumb/BackButton'; import {withSiteId} from 'App/routes'; import {withRouter, RouteComponentProps} from 'react-router-dom'; import {Button, PageTitle, confirm, Tooltip} from 'UI'; @@ -61,17 +62,24 @@ function DashboardHeader(props: Props) { closeHandler={() => setShowEditModal(false)} focusTitle={focusTitle} /> - {/* */} +
+ + + + {/* */} + + + = [ { title: 'Title', @@ -93,14 +98,22 @@ function DashboardList({ siteId }: { siteId: string }) { ); const emptyImage = dashboardsSearch !== '' ? ICONS.NO_RESULTS : ICONS.NO_DASHBOARDS; + const imageDimensions = dashboardsSearch !== '' ? searchImageDimensions : defaultImageDimensions; return ( list.length === 0 && !dashboardStore.filter.showMine ? ( +
} - imageStyle={{ height: 300 }} + image={} + imageStyle={{ + width: imageDimensions.width, + height: imageDimensions.height, + margin: 'auto', + padding: '2rem 0' + }} description={emptyDescription} /> +
) : (
- diff --git a/frontend/app/components/shared/Breadcrumb/BackButton.tsx b/frontend/app/components/shared/Breadcrumb/BackButton.tsx new file mode 100644 index 000000000..0eb961a84 --- /dev/null +++ b/frontend/app/components/shared/Breadcrumb/BackButton.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Button } from 'antd'; +import { useHistory } from 'react-router-dom'; +import { LeftOutlined } from '@ant-design/icons'; + +function BackButton({ siteId }) { + const history = useHistory(); + + const handleBackClick = () => { + history.goBack(); + }; + + return ( + + ); +} + +export default BackButton; diff --git a/frontend/app/components/ui/PageTitle/PageTitle.tsx b/frontend/app/components/ui/PageTitle/PageTitle.tsx index 50047ac03..b68e21952 100644 --- a/frontend/app/components/ui/PageTitle/PageTitle.tsx +++ b/frontend/app/components/ui/PageTitle/PageTitle.tsx @@ -14,7 +14,7 @@ function PageTitle({ title, actionButton = null, subTitle = '', className = '', return (
-

+

{title}

{ actionButton &&
{actionButton}
} From aaf65c532dcb0ea4f63235c9c300556b88ef41b9 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 12:33:51 +0200 Subject: [PATCH 42/66] change(ui): removed extra spaces --- .../components/WidgetForm/WidgetFormNew.tsx | 288 +++++++++--------- 1 file changed, 142 insertions(+), 146 deletions(-) diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx index 7b4e959e9..ceab4346d 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx @@ -1,176 +1,172 @@ import React from 'react'; -import {Card, Space, Typography, Button, Alert} from "antd"; -import {useStore} from "App/mstore"; -import {eventKeys} from "Types/filter/newFilter"; +import { Card, Space, Typography, Button, Alert } from 'antd'; +import { useStore } from 'App/mstore'; +import { eventKeys } from 'Types/filter/newFilter'; import { - CLICKMAP, - ERRORS, - FUNNEL, - INSIGHTS, - PERFORMANCE, - RESOURCE_MONITORING, - RETENTION, - TABLE, - USER_PATH, WEB_VITALS -} from "App/constants/card"; -import FilterSeries from "Components/Dashboard/components/FilterSeries/FilterSeries"; -import {metricOf} from "App/constants/filterOptions"; -import {AudioWaveform, ChevronDown, ChevronUp, PlusIcon} from "lucide-react"; -import {observer} from "mobx-react-lite"; -import AddStepButton from "Components/Dashboard/components/FilterSeries/AddStepButton"; -import {Icon} from "UI"; -import FilterItem from "Shared/Filters/FilterItem"; -import {FilterKey} from "Types/filter/filterType"; + CLICKMAP, + ERRORS, + FUNNEL, + INSIGHTS, + PERFORMANCE, + RESOURCE_MONITORING, + RETENTION, + TABLE, + USER_PATH, WEB_VITALS +} from 'App/constants/card'; +import FilterSeries from 'Components/Dashboard/components/FilterSeries/FilterSeries'; +import { metricOf } from 'App/constants/filterOptions'; +import { AudioWaveform, ChevronDown, ChevronUp, PlusIcon } from 'lucide-react'; +import { observer } from 'mobx-react-lite'; +import AddStepButton from 'Components/Dashboard/components/FilterSeries/AddStepButton'; +import { Icon } from 'UI'; +import FilterItem from 'Shared/Filters/FilterItem'; +import { FilterKey } from 'Types/filter/filterType'; function WidgetFormNew() { - const {metricStore, dashboardStore, aiFiltersStore} = useStore(); - const metric: any = metricStore.instance; + const { metricStore, dashboardStore, aiFiltersStore } = useStore(); + const metric: any = metricStore.instance; - const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; - const filtersLength = metric.series[0].filter.filters.filter((i: any) => i && !i.isEvent).length; - const isClickMap = metric.metricType === CLICKMAP; - const isPathAnalysis = metric.metricType === USER_PATH; - const excludeFilterKeys = isClickMap || isPathAnalysis ? eventKeys : []; - const hasFilters = filtersLength > 0 || eventsLength > 0; - const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes(metric.metricType); + const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; + const filtersLength = metric.series[0].filter.filters.filter((i: any) => i && !i.isEvent).length; + const isClickMap = metric.metricType === CLICKMAP; + const isPathAnalysis = metric.metricType === USER_PATH; + const excludeFilterKeys = isClickMap || isPathAnalysis ? eventKeys : []; + const hasFilters = filtersLength > 0 || eventsLength > 0; + const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes(metric.metricType); - return isPredefined ? : ( - - - - {!hasFilters && ( - - )} - - - {hasFilters && ( - - )} - - ); + return isPredefined ? : ( + + + {!hasFilters && ()} + {hasFilters && ()} + + ); } export default observer(WidgetFormNew); -function DefineSteps({metric, excludeFilterKeys}: any) { - return ( -
- Filter - -
- ); +function DefineSteps({ metric, excludeFilterKeys }: any) { + return ( + +
+ Filter + +
+
+ ); } -const FilterSection = observer(({metric, excludeFilterKeys}: any) => { - // const timeseriesOptions = metricOf.filter((i) => i.type === 'timeseries'); - // const tableOptions = metricOf.filter((i) => i.type === 'table'); - const isTable = metric.metricType === TABLE; - const isClickMap = metric.metricType === CLICKMAP; - const isFunnel = metric.metricType === FUNNEL; - const isInsights = metric.metricType === INSIGHTS; - const isPathAnalysis = metric.metricType === USER_PATH; - const isRetention = metric.metricType === RETENTION; - const canAddSeries = metric.series.length < 3; - const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; - // const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1); +const FilterSection = observer(({ metric, excludeFilterKeys }: any) => { + // const timeseriesOptions = metricOf.filter((i) => i.type === 'timeseries'); + // const tableOptions = metricOf.filter((i) => i.type === 'table'); + const isTable = metric.metricType === TABLE; + const isClickMap = metric.metricType === CLICKMAP; + const isFunnel = metric.metricType === FUNNEL; + const isInsights = metric.metricType === INSIGHTS; + const isPathAnalysis = metric.metricType === USER_PATH; + const isRetention = metric.metricType === RETENTION; + const canAddSeries = metric.series.length < 3; + const eventsLength = metric.series[0].filter.filters.filter((i: any) => i && i.isEvent).length; + // const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1); - const isSingleSeries = isTable || isFunnel || isClickMap || isInsights || isRetention + const isSingleSeries = isTable || isFunnel || isClickMap || isInsights || isRetention; - // const onAddFilter = (filter: any) => { - // metric.series[0].filter.addFilter(filter); - // metric.updateKey('hasChanged', true) - // } + // const onAddFilter = (filter: any) => { + // metric.series[0].filter.addFilter(filter); + // metric.updateKey('hasChanged', true) + // } - return ( - <> - { - metric.series.length > 0 && metric.series - .slice(0, isSingleSeries ? 1 : metric.series.length) - .map((series: any, index: number) => ( -
- metric.updateKey('hasChanged', true)} - hideHeader={isTable || isClickMap || isInsights || isPathAnalysis || isFunnel} - seriesIndex={index} - series={series} - onRemoveSeries={() => metric.removeSeries(index)} - canDelete={metric.series.length > 1} - emptyMessage={ - isTable - ? 'Filter data using any event or attribute. Use Add Step button below to do so.' - : 'Add user event or filter to define the series by clicking Add Step.' - } - expandable={isSingleSeries} - /> -
- )) - } + return ( + <> + { + metric.series.length > 0 && metric.series + .slice(0, isSingleSeries ? 1 : metric.series.length) + .map((series: any, index: number) => ( +
+ metric.updateKey('hasChanged', true)} + hideHeader={isTable || isClickMap || isInsights || isPathAnalysis || isFunnel} + seriesIndex={index} + series={series} + onRemoveSeries={() => metric.removeSeries(index)} + canDelete={metric.series.length > 1} + emptyMessage={ + isTable + ? 'Filter data using any event or attribute. Use Add Step button below to do so.' + : 'Add user event or filter to define the series by clicking Add Step.' + } + expandable={isSingleSeries} + /> +
+ )) + } - {!isSingleSeries && canAddSeries && ( - - - - )} - - ); -}) + }} + disabled={!canAddSeries} + size="small" + > + + + New Chart Series + + + + )} + + ); +}); -const PathAnalysisFilter = observer(({metric}: any) => ( - -
- metric.updateStartPoint(val)} - onRemoveFilter={() => { - }} - /> -
-
+const PathAnalysisFilter = observer(({ metric }: any) => ( + +
+ metric.updateStartPoint(val)} + onRemoveFilter={() => { + }} + /> +
+
)); const AdditionalFilters = observer(() => { - const {metricStore, dashboardStore, aiFiltersStore} = useStore(); - const metric: any = metricStore.instance; + const { metricStore, dashboardStore, aiFiltersStore } = useStore(); + const metric: any = metricStore.instance; - return ( - - {metric.metricType === USER_PATH && } - - ) + return ( + // + metric.metricType === USER_PATH && + // + ); }); const PredefinedMessage = () => ( - + ); From bfe165692e881c1d9e9734ffdd367f9f066bfd1e Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 12:58:48 +0200 Subject: [PATCH 43/66] change(ui): webvitals size to 2 col --- .../CustomMetricOverviewChart/CustomMetricOverviewChart.tsx | 2 +- .../Dashboard/components/WidgetChart/WidgetChart.tsx | 4 ++-- frontend/app/mstore/types/widget.ts | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx index d892682f6..4b23cea29 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart/CustomMetricOverviewChart.tsx @@ -27,7 +27,7 @@ function CustomMetricOverviewChart(props: Props) { />
- + Unknown metric type; }; return ( - -
{renderChart()}
+ +
{renderChart()}
); } diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 90606c99f..0eb5411dc 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -233,9 +233,7 @@ export default class Widget { this.metricOf === FilterKey.PAGES_RESPONSE_TIME_DISTRIBUTION || this.metricType === USER_PATH ? 4 - : this.metricType === WEB_VITALS - ? 1 - : 2 + : 2 } }; From 69fb477ae16b797731bba855f9225291b9c40d9d Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 13:20:12 +0200 Subject: [PATCH 44/66] change(ui): webvitals size to 2 col --- .../DashboardWidgetGrid.tsx | 159 ++++++------------ 1 file changed, 56 insertions(+), 103 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index de42e052b..e017d9615 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -1,117 +1,70 @@ import React from 'react'; -import {useStore} from 'App/mstore'; +import { useStore } from 'App/mstore'; import WidgetWrapper from '../WidgetWrapper'; -import {NoContent, Loader, Icon} from 'UI'; -import {useObserver} from 'mobx-react-lite'; +import { NoContent, Loader, Icon } from 'UI'; +import { useObserver } from 'mobx-react-lite'; import Widget from 'App/mstore/types/widget'; import MetricTypeList from '../MetricTypeList'; -import WidgetWrapperNew from "Components/Dashboard/components/WidgetWrapper/WidgetWrapperNew"; -import {Empty} from "antd"; +import WidgetWrapperNew from 'Components/Dashboard/components/WidgetWrapper/WidgetWrapperNew'; +import { Empty } from 'antd'; interface Props { - siteId: string; - dashboardId: string; - onEditHandler: () => void; - id?: string; + siteId: string; + dashboardId: string; + onEditHandler: () => void; + id?: string; } function DashboardWidgetGrid(props: Props) { - const {dashboardId, siteId} = props; - const {dashboardStore} = useStore(); - const loading = useObserver(() => dashboardStore.isLoading); - const dashboard = dashboardStore.selectedDashboard; - const list = useObserver(() => dashboard?.widgets); - const smallWidgets: Widget[] = []; - const regularWidgets: Widget[] = []; + const { dashboardId, siteId } = props; + const { dashboardStore } = useStore(); + const loading = useObserver(() => dashboardStore.isLoading); + const dashboard = dashboardStore.selectedDashboard; + const list = useObserver(() => dashboard?.widgets); - list?.forEach((item) => { - if (item.config.col === 1) { - smallWidgets.push(item); - } else { - regularWidgets.push(item); - } - }); - - const smallWidgetsLen = smallWidgets.length; - - return useObserver(() => ( - // @ts-ignore - list?.length === 0 ? : ( - - -
-
- There are no cards in this dashboard -
-
- Create a card from any of the below types or pick an existing one from your library. -
-
- {/*
*/} - {/* */} - {/*
*/} - + return useObserver(() => ( + // @ts-ignore + list?.length === 0 ? : ( + + +
+
+ There are no cards in this dashboard +
+
+ Create a card from any of the below types or pick an existing one from your library. +
+
+ + } + > +
+ { + list?.map((item: any, index: any) => ( + + + dashboard?.swapWidgetPosition(dragIndex, hoverIndex) } - > -
{smallWidgets.length > 0 ? ( - <> -
- - Web Vitals -
- - {smallWidgets && - smallWidgets.map((item: any, index: any) => ( - - - dashboard?.swapWidgetPosition(dragIndex, hoverIndex) - - } dashboardId={dashboardId} - siteId={siteId} - isWidget={true} - grid="vitals" - /> - - ))} - - - ) : null} - - {smallWidgets.length > 0 && regularWidgets.length > 0 ? ( -
- - All Cards -
- ) : null} - - {regularWidgets && - regularWidgets.map((item: any, index: any) => ( - - - dashboard?.swapWidgetPosition(dragIndex, hoverIndex) - } - dashboardId={dashboardId} - siteId={siteId} - isWidget={true} - grid="other" - /> - - ))} -
- - - ) - )); + dashboardId={dashboardId} + siteId={siteId} + isWidget={true} + grid="other" + /> +
+ )) + } +
+
+
+ ) + )); } export default DashboardWidgetGrid; From d84ff1f7e0b9f62150dee12a1d1167023836d74a Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 13:32:19 +0200 Subject: [PATCH 45/66] change(ui): card create modal height --- .../NewDashModal/NewDashboardModal.tsx | 97 ++++++++++--------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx index 5c975a9d1..a30db5c9d 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/NewDashboardModal.tsx @@ -1,60 +1,61 @@ -import React, {useEffect} from 'react'; -import {Modal} from 'antd'; +import React, { useEffect } from 'react'; +import { Modal } from 'antd'; import SelectCard from './SelectCard'; -import CreateCard from "Components/Dashboard/components/DashboardList/NewDashModal/CreateCard"; -import colors from "tailwindcss/colors"; +import CreateCard from 'Components/Dashboard/components/DashboardList/NewDashModal/CreateCard'; +import colors from 'tailwindcss/colors'; interface NewDashboardModalProps { - onClose: () => void; - open: boolean; - isAddingFromLibrary?: boolean; + onClose: () => void; + open: boolean; + isAddingFromLibrary?: boolean; } const NewDashboardModal: React.FC = ({ - onClose, - open, - isAddingFromLibrary = false, + onClose, + open, + isAddingFromLibrary = false }) => { - const [step, setStep] = React.useState(0); - const [selectedCategory, setSelectedCategory] = React.useState('product-analytics'); + const [step, setStep] = React.useState(0); + const [selectedCategory, setSelectedCategory] = React.useState('product-analytics'); - useEffect(() => { - return () => { - setStep(0); - } - }, [open]); + useEffect(() => { + return () => { + setStep(0); + }; + }, [open]); - return ( - <> - -
- {step === 0 && setStep(step + 1)} - isLibrary={isAddingFromLibrary}/>} - {step === 1 && setStep(0)}/>} -
-
- - ) - ; + return ( + <> + +
+ {step === 0 && setStep(step + 1)} + isLibrary={isAddingFromLibrary} />} + {step === 1 && setStep(0)} />} +
+
+ + ) + ; }; export default NewDashboardModal; From 5e1effc15166c6f8fc75402765f30c7383104ce8 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 13:35:48 +0200 Subject: [PATCH 46/66] change(ui): card create modal height --- .../NewDashModal/ExampleCards.tsx | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index 5ab52b1cc..e6426f46d 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -489,8 +489,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_CPU, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -500,8 +498,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_DOM_CONTENT_LOADED, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -512,8 +508,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_DOM_CONTENT_LOAD_START, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -524,8 +518,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_FIRST_CONTENTFUL_PIXEL, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -536,8 +528,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_FIRST_PAINT, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -548,8 +538,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_FPS, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -560,8 +548,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_IMAGE_LOAD_TIME, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -572,8 +558,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_PAGE_LOAD_TIME, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -584,8 +568,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_PAGES_DOM_BUILD_TIME, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -596,8 +578,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_PAGES_RESPONSE_TIME, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -608,8 +588,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_REQUEST_LOADT_IME, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -619,8 +597,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_RESPONSE_TIME, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -631,8 +607,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_SESSION_DURATION, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -643,8 +617,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_TILL_FIRST_BYTE, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -655,8 +627,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_TIME_TO_INTERACTIVE, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -667,8 +637,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_TIME_TO_RENDER, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, @@ -679,8 +647,6 @@ export const CARD_LIST: CardType[] = [ cardType: WEB_VITALS, metricOf: FilterKey.AVG_USED_JS_HEAP_SIZE, category: CARD_CATEGORIES[4].key, - width: 1, - height: 148, data: generateWebVitalData(), example: WebVital, }, From 281a2f5a1dbb581e19ea22ee00cf11c27284d85e Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 13:49:47 +0200 Subject: [PATCH 47/66] change(ui): webvitals rename --- .../DashboardList/NewDashModal/ExampleCards.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index e6426f46d..d75890e6a 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -484,7 +484,7 @@ export const CARD_LIST: CardType[] = [ // Web vitals { - title: 'CPU Load', + title: 'Avg. CPU Load', key: FilterKey.AVG_CPU, cardType: WEB_VITALS, metricOf: FilterKey.AVG_CPU, @@ -493,7 +493,7 @@ export const CARD_LIST: CardType[] = [ example: WebVital, }, { - title: 'DOM Content Loaded', + title: 'Avg. DOM Content Load Time', key: FilterKey.AVG_DOM_CONTENT_LOADED, cardType: WEB_VITALS, metricOf: FilterKey.AVG_DOM_CONTENT_LOADED, @@ -513,7 +513,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'First Meaningful Paint', + title: 'Avg. First Meaningful Paint Time', key: FilterKey.AVG_FIRST_CONTENTFUL_PIXEL, cardType: WEB_VITALS, metricOf: FilterKey.AVG_FIRST_CONTENTFUL_PIXEL, @@ -523,7 +523,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'First Paint', + title: 'Avg. First Paint Time', key: FilterKey.AVG_FIRST_PAINT, cardType: WEB_VITALS, metricOf: FilterKey.AVG_FIRST_PAINT, @@ -533,7 +533,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'Frame Rate', + title: 'Avg. Frame Rate', key: FilterKey.AVG_FPS, cardType: WEB_VITALS, metricOf: FilterKey.AVG_FPS, @@ -543,7 +543,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'Image Load Time', + title: 'Avg. Load Time of Images', key: FilterKey.AVG_IMAGE_LOAD_TIME, cardType: WEB_VITALS, metricOf: FilterKey.AVG_IMAGE_LOAD_TIME, @@ -553,7 +553,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'Page Load Time', + title: 'Avg. Load Time of Pages', key: FilterKey.AVG_PAGE_LOAD_TIME, cardType: WEB_VITALS, metricOf: FilterKey.AVG_PAGE_LOAD_TIME, @@ -563,7 +563,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'DOM Build Time', + title: 'Avg. DOM Build Time', key: FilterKey.AVG_PAGES_DOM_BUILD_TIME, cardType: WEB_VITALS, metricOf: FilterKey.AVG_PAGES_DOM_BUILD_TIME, From 6fcef5dff513a466baf2be4ece72291f94289552 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 14:56:38 +0200 Subject: [PATCH 48/66] change(ui): sessions per browser example --- .../SessionsPerBrowser/SessionsPerBrowser.tsx | 66 +++++++++---------- .../Dashboard/Widgets/common/Styles.js | 2 +- .../NewDashModal/ExampleCards.tsx | 4 +- .../Examples/SessionsPerBrowserExample.tsx | 38 +++++++++++ .../WidgetPredefinedChart.tsx | 2 +- 5 files changed, 76 insertions(+), 36 deletions(-) create mode 100644 frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample.tsx diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx index ca6c836e3..1644d77d1 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser/SessionsPerBrowser.tsx @@ -2,43 +2,43 @@ import React from 'react'; import { NoContent } from 'UI'; import { Styles } from '../../common'; import Bar from './Bar'; -import { NO_METRIC_DATA } from 'App/constants/messages' +import { NO_METRIC_DATA } from 'App/constants/messages'; interface Props { - data: any - metric?: any + data: any; } -function SessionsPerBrowser(props: Props) { - const { data, metric } = props; - const firstAvg = metric.data.chart[0] && metric.data.chart[0].count; - const getVersions = item => { - return Object.keys(item) - .filter(i => i !== 'browser' && i !== 'count' && i !== 'time' && i !== 'timestamp') - .map(i => ({ key: 'v' +i, value: item[i]})) - } - return ( - -
- {metric.data.chart.map((item, i) => - - )} -
-
- ); +function SessionsPerBrowser(props: Props) { + const { data } = props; + const firstAvg = data.chart[0] && data.chart[0].count; + + const getVersions = item => { + return Object.keys(item) + .filter(i => i !== 'browser' && i !== 'count' && i !== 'time' && i !== 'timestamp') + .map(i => ({ key: 'v' + i, value: item[i] })); + }; + return ( + +
+ {data.chart.map((item, i) => + + )} +
+
+ ); } export default SessionsPerBrowser; diff --git a/frontend/app/components/Dashboard/Widgets/common/Styles.js b/frontend/app/components/Dashboard/Widgets/common/Styles.js index 31f9711b6..0f8854911 100644 --- a/frontend/app/components/Dashboard/Widgets/common/Styles.js +++ b/frontend/app/components/Dashboard/Widgets/common/Styles.js @@ -6,7 +6,7 @@ const colors = ['#6774E2', '#929ACD', '#3EAAAF', '#565D97', '#8F9F9F', '#376F72' const colorsx = ['#256669', '#38999e', '#3eaaaf', '#51b3b7', '#78c4c7', '#9fd5d7', '#c5e6e7'].reverse(); const compareColors = ['#394EFF', '#4D5FFF', '#808DFF', '#B3BBFF', '#E5E8FF']; const compareColorsx = ["#222F99", "#2E3ECC", "#394EFF", "#6171FF", "#8895FF", "#B0B8FF", "#D7DCFF"].reverse(); -const customMetricColors = ['#3EAAAF', '#394EFF', '#565D97']; +const customMetricColors = ['#394EFF', '#3EAAAF', '#565D97']; const colorsPie = colors.concat(["#DDDDDD"]); const countView = count => { diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index d75890e6a..aa66bfa40 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -19,6 +19,8 @@ import BarChartCard from "Components/Dashboard/components/DashboardList/NewDashM import AreaChartCard from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard"; import CallsWithErrorsExample from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/CallsWithErrorsExample"; +import SessionsPerBrowserExample + from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample'; export const CARD_CATEGORY = { PRODUCT_ANALYTICS: 'product-analytics', @@ -260,7 +262,7 @@ export const CARD_LIST: CardType[] = [ metricOf: FilterKey.SESSIONS_PER_BROWSER, category: CARD_CATEGORIES[1].key, data: generateRandomBarsData(), - example: Bars, + example: SessionsPerBrowserExample, }, { diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample.tsx new file mode 100644 index 000000000..f5710b759 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import ExCard from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard'; +import InsightsCard from 'Components/Dashboard/Widgets/CustomMetricsWidgets/InsightsCard'; +import { InsightIssue } from 'App/mstore/types/widget'; +import SessionsPerBrowser from 'Components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser'; + +interface Props { + title: string; + type: string; + onCard: (card: string) => void; +} + +function SessionsPerBrowserExample(props: Props) { + const data = { + chart: [ + { + 'browser': 'Chrome', + 'count': 1524, + '126.0.0': 1157, + '125.0.0': 224 + }, + { + 'browser': 'Edge', + 'count': 159, + '126.0.0': 145 + } + ] + }; + return ( + + + + ); +} + +export default SessionsPerBrowserExample; diff --git a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx index a7ae663d2..a3c5d81f1 100644 --- a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx @@ -76,7 +76,7 @@ function WidgetPredefinedChart(props: Props) { case FilterKey.RESOURCES_VS_VISUALLY_COMPLETE: return case FilterKey.SESSIONS_PER_BROWSER: - return + return case FilterKey.SLOWEST_DOMAINS: return case FilterKey.TIME_TO_RENDER: From 20ccee48d1e0042d751f14980751b72bf1f775fc Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 15:41:13 +0200 Subject: [PATCH 49/66] change(ui): slowest domains card change --- .../Dashboard/Widgets/CardSessionsByList.tsx | 6 +- .../CustomMetricsWidgets/SessionsBy.tsx | 146 +++++++++--------- .../SlowestDomains/SlowestDomains.tsx | 97 ++++++++---- .../NewDashModal/ExampleCards.tsx | 8 +- .../Examples/SessionsBy/ByUrl.tsx | 108 +++++++------ .../Examples/SessionsBy/SlowestDomains.tsx | 49 ++++++ .../NewDashModal/Examples/SlowestDomain.tsx | 1 + .../WidgetPredefinedChart.tsx | 2 +- 8 files changed, 260 insertions(+), 157 deletions(-) create mode 100644 frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains.tsx diff --git a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx index 262916873..a150c787f 100644 --- a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx +++ b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx @@ -4,11 +4,11 @@ import cn from "classnames"; interface Props { list: any; - selected: any; - onClickHandler: (event: any, data: any) => void; + selected?: any; + onClickHandler?: (event: any, data: any) => void; } -function CardSessionsByList({ list, selected, onClickHandler }: Props) { +function CardSessionsByList({ list, selected, onClickHandler = () => null }: Props) { return ( void; - isTemplate?: boolean; + metric?: any; + data: any; + onClick?: (filters: any) => void; + isTemplate?: boolean; } function SessionsBy(props: Props) { - const {metric = {}, data = {values: []}, onClick = () => null, isTemplate} = props; - const [selected, setSelected] = React.useState(null); - const total = data.values.length - const {openModal, closeModal} = useModal(); + const { metric = {}, data = { values: [] }, onClick = () => null, isTemplate } = props; + const [selected, setSelected] = React.useState(null); + const total = data.values.length; + const { openModal, closeModal } = useModal(); - const onClickHandler = (event: any, data: any) => { - const filters = Array(); - let filter = {...filtersMap[metric.metricOf]}; - filter.value = [data.name]; - filter.type = filter.key; - delete filter.key; - delete filter.operatorOptions; - delete filter.category; - delete filter.icon; - delete filter.label; - delete filter.options; + const onClickHandler = (event: any, data: any) => { + const filters = Array(); + let filter = { ...filtersMap[metric.metricOf] }; + filter.value = [data.name]; + filter.type = filter.key; + delete filter.key; + delete filter.operatorOptions; + delete filter.category; + delete filter.icon; + delete filter.label; + delete filter.options; - setSelected(data.name) + setSelected(data.name); - filters.push(filter); - onClick(filters); - } + filters.push(filter); + onClick(filters); + }; - const showMore = () => { - openModal( - { - closeModal(); - onClickHandler(null, item) - }} selected={selected}/>, { - title: metric.name, - width: 600, - }) - } + const showMore = () => { + openModal( + { + closeModal(); + onClickHandler(null, item); + }} selected={selected} />, { + title: metric.name, + width: 600 + }); + }; - return ( -
- {data.values && data.values.length === 0 ? ( - - - No data for the selected time period -
- } - /> - ) : ( -
- - {total > 3 && ( -
- -
- )} -
- )} + return ( +
+ {data.values && data.values.length === 0 ? ( + + + No data for the selected time period +
+ } + /> + ) : ( +
+ + {total > 3 && ( +
+ +
+ )}
- ); + )} + + ); } export default SessionsBy; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx index 758a6575a..661a5842f 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx @@ -1,38 +1,83 @@ import React from 'react'; -import { NoContent } from 'UI'; +import { Icon, NoContent } from 'UI'; import { Styles } from '../../common'; import { numberWithCommas } from 'App/utils'; import Bar from './Bar'; -import { NO_METRIC_DATA } from 'App/constants/messages' +import { NO_METRIC_DATA } from 'App/constants/messages'; +import CardSessionsByList from 'Components/Dashboard/Widgets/CardSessionsByList'; +import { List, Progress, Typography } from 'antd'; +import cn from 'classnames'; interface Props { - data: any - metric?: any + data: any; } + function SlowestDomains(props: Props) { - const { data, metric } = props; - const firstAvg = metric.data.chart[0] && metric.data.chart[0].value; - return ( - -
- {metric.data.chart.map((item, i) => - ({ + name: item.domain, + icon: , + value: Math.round(item.value) + 'ms', + progress: Math.round((item.value * 100) / highest) + })); + + return ( + +
+ ( + onClickHandler(e, row)} // Remove onClick handler to disable click interaction + style={{ + borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', + padding: '4px 10px', + lineHeight: '1px' + }} + className={cn('rounded')} // Remove hover:bg-active-blue and cursor-pointer + > + +
+ {row.name} + {row.value} +
+ + +
+ )} /> - )} -
-
- ); + + )} + /> + +
+ ); } export default SlowestDomains; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index aa66bfa40..499a560c7 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -21,6 +21,8 @@ import CallsWithErrorsExample from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/CallsWithErrorsExample"; import SessionsPerBrowserExample from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample'; +import SlowestDomains + from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains'; export const CARD_CATEGORY = { PRODUCT_ANALYTICS: 'product-analytics', @@ -256,7 +258,7 @@ export const CARD_LIST: CardType[] = [ }, { - title: 'Sessions per Browser', + title: 'Sessions by Browser & Version', key: FilterKey.SESSIONS_PER_BROWSER, cardType: PERFORMANCE, metricOf: FilterKey.SESSIONS_PER_BROWSER, @@ -271,8 +273,8 @@ export const CARD_LIST: CardType[] = [ cardType: PERFORMANCE, metricOf: FilterKey.SLOWEST_DOMAINS, category: CARD_CATEGORIES[1].key, - data: generateRandomBarsData(), - example: Bars, + // data: generateRandomBarsData(), + example: SlowestDomains, }, { diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx index b6d35ef76..28c0b9560 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { Circle } from '../Count'; import ExCard from '../ExCard'; +import ByComponent from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/Component'; function ByUrl(props: any) { const [mode, setMode] = React.useState(0); @@ -47,57 +48,62 @@ function ByUrl(props: any) { const lineWidth = 240; return ( - -
{props.title}
-
setMode(Number(v))} - size='small' - /> -
- - } - > -
- {rows.map((r) => ( -
- {r.icon} -
-
{mode === 0 ? r.label : r.ptitle}
-
-
-
-
-
-
{r.value}
-
- ))} -
- + + // + //
{props.title}
+ //
setMode(Number(v))} + // size='small' + // /> + //
+ //
+ // } + // > + //
+ // {rows.map((r) => ( + //
+ // {r.icon} + //
+ //
{mode === 0 ? r.label : r.ptitle}
+ //
+ //
+ //
+ //
+ //
+ //
{r.value}
+ //
+ // ))} + //
+ // ); } diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains.tsx new file mode 100644 index 000000000..428c04bb3 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import ByComponent from './Component'; +import { LinkOutlined } from '@ant-design/icons'; + +function SlowestDomains(props: any) { + const rows = [ + { + label: 'res.cloudinary.com', + value: '500', + progress: 75, + icon: + }, + { + label: 'mintbase.vercel.app', + value: '306', + progress: 60, + icon: + }, + { + label: 'downloads.intercomcdn.com', + value: '198', + progress: 30, + icon: + }, + { + label: 'static.intercomassets.com', + value: '47', + progress: 15, + icon: + }, + { + label: 'mozbar.moz.com', + value: '5', + progress: 5, + icon: + } + ]; + + const lineWidth = 200; + return ( + + ); +} + +export default SlowestDomains; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx index d39062eb2..baded8f84 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { Circle } from './Count'; import ExCard from './ExCard'; +// TODO - delete this function SlowestDomain(props: any) { const rows = [ { diff --git a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx index a3c5d81f1..dc019b8f8 100644 --- a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx @@ -78,7 +78,7 @@ function WidgetPredefinedChart(props: Props) { case FilterKey.SESSIONS_PER_BROWSER: return case FilterKey.SLOWEST_DOMAINS: - return + return case FilterKey.TIME_TO_RENDER: return From 23e7b87002a347cf86c5d39a7cedbaefcb9d381c Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Mon, 1 Jul 2024 19:30:04 +0530 Subject: [PATCH 50/66] UI Improvements --- .../DashboardMetricSelection.tsx | 3 +- .../FilterSeries/ExcludeFilters.tsx | 4 +- .../components/FilterSeries/FilterSeries.tsx | 2 +- .../FilterSeries/SeriesName/SeriesName.tsx | 9 ++- .../components/WidgetForm/CardBuilder.tsx | 2 +- .../components/WidgetForm/WidgetForm.tsx | 2 +- .../components/WidgetForm/WidgetFormNew.tsx | 2 +- .../components/WidgetName/WidgetName.tsx | 6 +- .../Onboarding/components/SideMenu.tsx | 10 ++-- .../NoSessionsMessage/NoSessionsMessage.js | 60 +++++++++++-------- frontend/app/layout/SideMenu.tsx | 4 +- 11 files changed, 60 insertions(+), 44 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx b/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx index 67284b59c..26ee72a2d 100644 --- a/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx +++ b/frontend/app/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection.tsx @@ -1,10 +1,9 @@ import React, { useEffect } from 'react'; import WidgetWrapper from '../WidgetWrapper'; import { useObserver } from 'mobx-react-lite'; -import { Icon } from 'UI'; +import { Icon, Loader } from 'UI'; import cn from 'classnames'; import { useStore } from 'App/mstore'; -import { Loader } from 'UI'; interface IWiProps { category: Record diff --git a/frontend/app/components/Dashboard/components/FilterSeries/ExcludeFilters.tsx b/frontend/app/components/Dashboard/components/FilterSeries/ExcludeFilters.tsx index ad893528a..d7ae15483 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/ExcludeFilters.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/ExcludeFilters.tsx @@ -6,7 +6,7 @@ import React from 'react'; import FilterItem from 'Shared/Filters/FilterItem'; import cn from 'classnames'; -import { Button } from 'UI'; +import { Button } from 'antd'; interface Props { filter: Filter; @@ -47,7 +47,7 @@ function ExcludeFilters(props: Props) { ))}
) : ( - )} diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index e87a4dd54..61c8ddb3a 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -85,7 +85,7 @@ function FilterSeries(props: Props) { }, canDelete, hideHeader = false, - emptyMessage = 'Add user event or filter to define the series by clicking Add Step.', + emptyMessage = 'Add an event or filter step to define the series.', supportsEmpty = true, excludeFilterKeys = [], canExclude = false, diff --git a/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx b/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx index 9c4f58a66..54f94aff9 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx @@ -1,6 +1,6 @@ import React, { useState, useRef, useEffect } from 'react'; import { Icon } from 'UI'; -import {Input} from 'antd'; +import {Input, Tooltip} from 'antd'; interface Props { name: string; @@ -50,7 +50,12 @@ function SeriesName(props: Props) {
{name && name.trim() === '' ? 'Series ' + (seriesIndex + 1) : name }
)} -
setEditing(true)}>
+ +
setEditing(true)}> + + + +
); } diff --git a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx index a7f883049..e7cfea94f 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx @@ -182,7 +182,7 @@ const SeriesList = observer(() => { emptyMessage={ metric.metricType === TABLE ? 'Filter data using any event or attribute. Use Add Step button below to do so.' - : 'Add user event or filter to define the series by clicking Add Step.' + : 'Add an event or filter step to define the series.' } />
diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx index fe5730f25..7019f0826 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx @@ -318,7 +318,7 @@ function WidgetForm(props: Props) { emptyMessage={ isTable ? 'Filter data using any event or attribute. Use Add Step button below to do so.' - : 'Add user event or filter to define the series by clicking Add Step.' + : 'Add an event or filter step to define the series.' } /> diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx index ceab4346d..8e317f8ba 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetFormNew.tsx @@ -103,7 +103,7 @@ const FilterSection = observer(({ metric, excludeFilterKeys }: any) => { emptyMessage={ isTable ? 'Filter data using any event or attribute. Use Add Step button below to do so.' - : 'Add user event or filter to define the series by clicking Add Step.' + : 'Add an event or filter step to define the series.' } expandable={isSingleSeries} /> diff --git a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx index ae3ab3355..2db526d7a 100644 --- a/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx +++ b/frontend/app/components/Dashboard/components/WidgetName/WidgetName.tsx @@ -80,7 +80,11 @@ function WidgetName(props: Props) { )} - { canEdit &&
setEditing(true)}>
} + { canEdit &&
setEditing(true)}> + + + +
} ); } diff --git a/frontend/app/components/Onboarding/components/SideMenu.tsx b/frontend/app/components/Onboarding/components/SideMenu.tsx index 93a742417..a9571bdcf 100644 --- a/frontend/app/components/Onboarding/components/SideMenu.tsx +++ b/frontend/app/components/Onboarding/components/SideMenu.tsx @@ -52,7 +52,7 @@ function SideMenu(props: Props) { color={activeTab === OB_TABS.INSTALLING ? 'teal' : 'gray'} /> } - className={'!rounded hover-fill-teal'} + className={'!rounded-lg hover-fill-teal'} > Setup OpenReplay @@ -66,7 +66,7 @@ function SideMenu(props: Props) { color={activeTab === OB_TABS.IDENTIFY_USERS ? 'teal' : 'gray'} /> } - className={'!rounded hover-fill-teal'} + className={'!rounded-lg hover-fill-teal'} > Identify Users @@ -80,7 +80,7 @@ function SideMenu(props: Props) { color={activeTab === OB_TABS.MANAGE_USERS ? 'teal' : 'gray'} /> } - className={'!rounded hover-fill-teal'} + className={'!rounded-lg hover-fill-teal'} > Invite Collaborators @@ -94,7 +94,7 @@ function SideMenu(props: Props) { color={activeTab === OB_TABS.INTEGRATIONS ? 'teal' : 'gray'} /> } - className={'!rounded hover-fill-teal'} + className={'!rounded-lg hover-fill-teal'} > Integrations @@ -109,7 +109,7 @@ function SideMenu(props: Props) { color={activeTab === 'support' ? 'teal' : 'gray'} /> } - className={'!rounded hover-fill-teal'} + className={'!rounded-lg hover-fill-teal'} > Support diff --git a/frontend/app/components/shared/NoSessionsMessage/NoSessionsMessage.js b/frontend/app/components/shared/NoSessionsMessage/NoSessionsMessage.js index a24daa891..2dec6fc5d 100644 --- a/frontend/app/components/shared/NoSessionsMessage/NoSessionsMessage.js +++ b/frontend/app/components/shared/NoSessionsMessage/NoSessionsMessage.js @@ -1,11 +1,16 @@ import React from 'react'; -import { Icon, Button } from 'UI'; +import { Alert, Space, Button } from 'antd'; import { connect } from 'react-redux'; import { onboarding as onboardingRoute } from 'App/routes'; import { withRouter } from 'react-router-dom'; import * as routes from '../../../routes'; +import { indigo } from 'tailwindcss/colors'; +import { SquareArrowOutUpRight } from 'lucide-react'; + const withSiteId = routes.withSiteId; +const indigoWithOpacity = `rgba(${parseInt(indigo[500].slice(1, 3), 16)}, ${parseInt(indigo[500].slice(3, 5), 16)}, ${parseInt(indigo[500].slice(5, 7), 16)}, 0.1)`; // 0.5 is the opacity level + const NoSessionsMessage = (props) => { const { @@ -19,32 +24,35 @@ const NoSessionsMessage = (props) => { return ( <> {showNoSessions && ( -
-
-
-
- -
-
- It might take a few minutes for first recording to appear. - - Troubleshoot - - . -
- -
+
+ + + + + + } + /> +
-
)} ); diff --git a/frontend/app/layout/SideMenu.tsx b/frontend/app/layout/SideMenu.tsx index e96cdc297..5b2a57cdb 100644 --- a/frontend/app/layout/SideMenu.tsx +++ b/frontend/app/layout/SideMenu.tsx @@ -177,7 +177,7 @@ function SideMenu(props: Props) { key={item.key} style={{ paddingLeft: '20px' }} icon={} - className={cn('!rounded hover-fill-teal')} + className={cn('!rounded-lg hover-fill-teal')} > {item.label} @@ -200,7 +200,7 @@ function SideMenu(props: Props) { icon={} style={{ paddingLeft: '20px' }} - className={cn('!rounded hover-fill-teal')} + className={cn('!rounded-lg hover-fill-teal')} itemIcon={item.leading ? : null}> {item.label} From f35456b3f8cd684ff177d146d5ff9e2d86bbf4f0 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Mon, 1 Jul 2024 20:03:49 +0530 Subject: [PATCH 51/66] UI Improvements --- .../Assist/AssistSearchField/AssistSearchField.tsx | 8 ++++---- .../Dashboard/components/Alerts/AlertsSearch.tsx | 8 +++++--- .../Dashboard/components/Alerts/AlertsView.tsx | 13 +++++++++++-- .../components/DashboardList/DashboardSearch.tsx | 2 +- .../MetricViewHeader/MetricViewHeader.tsx | 13 ++++++++----- .../components/MetricsSearch/MetricsSearch.tsx | 9 +++++---- .../UsabilityTesting/UsabilityTesting.tsx | 5 +++-- .../SessionSearchField/SessionSearchField.tsx | 2 +- 8 files changed, 38 insertions(+), 22 deletions(-) diff --git a/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx b/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx index 09c1ce06c..e49ac65d9 100644 --- a/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx +++ b/frontend/app/components/Assist/AssistSearchField/AssistSearchField.tsx @@ -7,7 +7,7 @@ import { edit as editFilter, fetchFilterSearch, } from 'Duck/liveSearch'; -import { Button } from 'UI'; +import { Button } from 'antd'; import { useModal } from 'App/components/Modal'; import SessionSearchField from 'Shared/SessionSearchField'; import { MODULES } from 'Components/Client/Modules'; @@ -42,11 +42,11 @@ function AssistSearchField(props: Props) {
{props.isEnterprise && props.modules.includes(MODULES.OFFLINE_RECORDINGS) - ? : null + ? : null } - + + + + +
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx index e0ad2048c..219145c18 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardSearch.tsx @@ -29,7 +29,7 @@ function DashboardSearch() { allowClear name="dashboardsSearch" className="w-full" - placeholder="Filter by title or description" + placeholder="Filter by dashboard title" onChange={write} onSearch={(value) => dashboardStore.updateKey('filter', { ...dashboardStore.filter, query: value })} /> diff --git a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx index 3c7b27b3b..67055980f 100644 --- a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import {PageTitle, Button, Toggler, Icon} from "UI"; -import {Segmented} from 'antd'; +import {PageTitle, Toggler, Icon} from "UI"; +import {Segmented, Button} from 'antd'; +import { PlusOutlined } from '@ant-design/icons'; import MetricsSearch from '../MetricsSearch'; import Select from 'Shared/Select'; import {useStore} from 'App/mstore'; @@ -24,10 +25,11 @@ function MetricViewHeader({siteId}: { siteId: string }) {
- + icon={} + >Create Card
@@ -119,7 +121,8 @@ function ListViewToggler() { const listView = useObserver(() => metricStore.listView); return (
- diff --git a/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx b/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx index 368816ce2..efb197dcc 100644 --- a/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx +++ b/frontend/app/components/Dashboard/components/MetricsSearch/MetricsSearch.tsx @@ -2,6 +2,7 @@ import { useObserver } from 'mobx-react-lite'; import React, { useEffect, useState } from 'react'; import { useStore } from 'App/mstore'; import { Icon } from 'UI'; +import {Input} from 'antd'; import { debounce } from 'App/utils'; let debounceUpdate: any = () => {}; @@ -22,12 +23,12 @@ function MetricsSearch() { return useObserver(() => (
- -
diff --git a/frontend/app/components/UsabilityTesting/UsabilityTesting.tsx b/frontend/app/components/UsabilityTesting/UsabilityTesting.tsx index 9c5d374d9..063592c6d 100644 --- a/frontend/app/components/UsabilityTesting/UsabilityTesting.tsx +++ b/frontend/app/components/UsabilityTesting/UsabilityTesting.tsx @@ -8,7 +8,7 @@ import AnimatedSVG from 'Shared/AnimatedSVG'; import { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import { Loader, NoContent, Pagination, Link, Icon } from 'UI'; import { checkForRecent, getDateFromMill } from 'App/date'; -import { ArrowRightOutlined } from '@ant-design/icons'; +import { ArrowRightOutlined, PlusOutlined } from '@ant-design/icons'; import { useHistory, useParams } from 'react-router-dom'; import { withSiteId, usabilityTestingEdit, usabilityTestingView } from 'App/routes'; import { debounce } from 'App/utils'; @@ -110,9 +110,10 @@ function TestsTable() { Usability Tests
- + {showModal && ( From b3ee59c6e313f5b551507cd644cb4f6a70829b4e Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 16:59:37 +0200 Subject: [PATCH 52/66] change(ui): speed index example, slowest domains example and card type change --- .../Dashboard/Widgets/ListWithIcons.tsx | 65 +++++++ .../SlowestDomains/SlowestDomains.tsx | 54 +----- .../SpeedIndexByLocation/Scale.js | 18 +- .../SpeedIndexByLocation.module.css | 14 +- .../SpeedIndexByLocation.tsx | 176 +++++++++--------- .../NewDashModal/ExampleCards.tsx | 7 +- .../NewDashModal/Examples/AreaChartCard.tsx | 2 +- .../Examples/SessionsBy/Component.tsx | 94 +++------- .../Examples/SpeedIndexByLocationExample.tsx | 94 ++++++++++ .../WidgetPredefinedChart.tsx | 2 +- 10 files changed, 307 insertions(+), 219 deletions(-) create mode 100644 frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx create mode 100644 frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx diff --git a/frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx b/frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx new file mode 100644 index 000000000..0b69fb4cc --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { List, Progress, Typography } from 'antd'; +import cn from 'classnames'; + +interface ListItem { + icon?: any; + title: string; + progress: number; + value?: number; +} + +interface Props { + list: ListItem[]; +} + +function ListWithIcons({ list = [] }: Props) { + return ( + ( + onClickHandler(e, row)} // Remove onClick handler to disable click interaction + style={{ + borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', + padding: '4px 10px', + lineHeight: '1px' + }} + className={cn('rounded')} // Remove hover:bg-active-blue and cursor-pointer + > + +
+ {row.name} + {row.value} +
+ + +
+ )} + /> + + )} + /> + ); +} + +export default ListWithIcons; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx index 661a5842f..7a2afeb9d 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx @@ -1,12 +1,7 @@ import React from 'react'; import { Icon, NoContent } from 'UI'; -import { Styles } from '../../common'; -import { numberWithCommas } from 'App/utils'; -import Bar from './Bar'; import { NO_METRIC_DATA } from 'App/constants/messages'; -import CardSessionsByList from 'Components/Dashboard/Widgets/CardSessionsByList'; -import { List, Progress, Typography } from 'antd'; -import cn from 'classnames'; +import ListWithIcons from 'Components/Dashboard/Widgets/ListWithIcons'; interface Props { data: any; @@ -15,7 +10,7 @@ interface Props { function SlowestDomains(props: Props) { const { data } = props; // TODO - move this to the store - const highest = data.chart[0].value; + const highest = data.chart[0]?.value; const list = data.chart.slice(0, 4).map((item: any) => ({ name: item.domain, icon: , @@ -31,50 +26,7 @@ function SlowestDomains(props: Props) { title={NO_METRIC_DATA} >
- ( - onClickHandler(e, row)} // Remove onClick handler to disable click interaction - style={{ - borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', - padding: '4px 10px', - lineHeight: '1px' - }} - className={cn('rounded')} // Remove hover:bg-active-blue and cursor-pointer - > - -
- {row.name} - {row.value} -
- - -
- )} - /> - - )} - /> +
); diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js index 6b944518c..707f21eb9 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js @@ -1,25 +1,25 @@ -import React from 'react' +import React from 'react'; import { Styles } from '../../common'; import cn from 'classnames'; import stl from './scale.module.css'; function Scale({ colors }) { - const lastIndex = (Styles.colorsTeal.length - 1) - + const lastIndex = (Styles.compareColors.length - 1); + return ( -
- {Styles.colorsTeal.map((c, i) => ( +
+ {Styles.compareColors.map((c, i) => (
- { i === 0 &&
Slow
} - { i === lastIndex &&
Fast
} + {i === 0 &&
Slow
} + {i === lastIndex &&
Fast
}
))}
- ) + ); } -export default Scale +export default Scale; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css index a42f4af12..ec2c46f02 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css @@ -15,7 +15,7 @@ &:focus, &:hover { - fill: $teal !important; + fill: #2E3ECC !important; outline: 0; } } @@ -25,23 +25,23 @@ } .heat_index5 { - fill: #3EAAAF !important; + fill: #B0B8FF !important; } .heat_index4 { - fill:#5FBABF !important; + fill:#6171FF !important; } .heat_index3 { - fill: #7BCBCF !important; + fill: #394EFF !important; } .heat_index2 { - fill: #96DCDF !important; + fill: #2E3ECC !important; } .heat_index1 { - fill: #ADDCDF !important; + fill: #222F99 !important; } .tooltip { @@ -52,4 +52,4 @@ background-color: white; font-size: 12px; line-height: 1.2; -} \ No newline at end of file +} diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx index ca049a677..ef9565b2b 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx @@ -8,99 +8,105 @@ import WorldMap from '@svg-maps/world'; import { SVGMap } from 'react-svg-map'; import stl from './SpeedIndexByLocation.module.css'; import cn from 'classnames'; -import { NO_METRIC_DATA } from 'App/constants/messages' +import { NO_METRIC_DATA } from 'App/constants/messages'; interface Props { - metric?: any; + data?: any; } + function SpeedIndexByLocation(props: Props) { - const { metric } = props; - const wrapper: any = React.useRef(null); - let map: any = null; - const [tooltipStyle, setTooltipStyle] = React.useState({ display: 'none' }); - const [pointedLocation, setPointedLocation] = React.useState(null); - const dataMap: any = React.useMemo(() => { - const data: any = {}; - const max = metric.data.chart.reduce((acc: any, item: any) => Math.max(acc, item.value), 0); - const min = metric.data.chart.reduce((acc: any, item: any) => Math.min(acc, item.value), 0); - metric.data.chart.forEach((item: any) => { - if (!item || !item.userCountry) { return } - item.perNumber = positionOfTheNumber(min, max, item.value, 5); - data[item.userCountry.toLowerCase()] = item; - }); - return data; - }, []); + const { data } = props; + console.log('data', data); + const wrapper: any = React.useRef(null); + let map: any = null; + const [tooltipStyle, setTooltipStyle] = React.useState({ display: 'none' }); + const [pointedLocation, setPointedLocation] = React.useState(null); - const getLocationClassName = (location: any) => { - const i = dataMap[location.id] ? dataMap[location.id].perNumber : 0; - const cls = stl['heat_index' + i]; - return cn(stl.location, cls); + const dataMap: any = React.useMemo(() => { + const _data: any = {}; + const max = data.chart?.reduce((acc: any, item: any) => Math.max(acc, item.value), 0); + const min = data.chart?.reduce((acc: any, item: any) => Math.min(acc, item.value), 0); + data.chart?.forEach((item: any) => { + console.log('item', item); + if (!item || !item.userCountry) { + return; + } + item.perNumber = positionOfTheNumber(min, max, item.value, 5); + _data[item.userCountry.toLowerCase()] = item; + }); + return _data; + }, [data.chart]); + + const getLocationClassName = (location: any) => { + const i = dataMap[location.id] ? dataMap[location.id].perNumber : 0; + const cls = stl['heat_index' + i]; + return cn(stl.location, cls); + }; + + const getLocationName = (event: any) => { + if (!event) return null; + const id = event.target.attributes.id.value; + const name = event.target.attributes.name.value; + const percentage = dataMap[id] ? dataMap[id].perNumber : 0; + return { name, id, percentage }; + }; + + const handleLocationMouseOver = (event: any) => { + const pointedLocation = getLocationName(event); + setPointedLocation(pointedLocation); + }; + + const handleLocationMouseOut = () => { + setTooltipStyle({ display: 'none' }); + setPointedLocation(null); + }; + + const handleLocationMouseMove = (event: any) => { + const tooltipStyle = { + display: 'block', + top: event.clientY + 10, + left: event.clientX - 100 }; + setTooltipStyle(tooltipStyle); + }; - const getLocationName = (event: any) => { - if (!event) return null; - const id = event.target.attributes.id.value; - const name = event.target.attributes.name.value; - const percentage = dataMap[id] ? dataMap[id].perNumber : 0; - return { name, id, percentage }; - }; - - const handleLocationMouseOver = (event: any) => { - const pointedLocation = getLocationName(event); - setPointedLocation(pointedLocation); - }; - - const handleLocationMouseOut = () => { - setTooltipStyle({ display: 'none' }); - setPointedLocation(null); - }; - - const handleLocationMouseMove = (event: any) => { - const tooltipStyle = { - display: 'block', - top: event.clientY + 10, - left: event.clientX - 100, - }; - setTooltipStyle(tooltipStyle); - }; - - return ( - -
- + return ( + +
+ +
+ +
+
+ +
+
+ {pointedLocation && ( + <> +
{pointedLocation.name}
+
+ Avg: {dataMap[pointedLocation.id] ? numberWithCommas(parseInt(dataMap[pointedLocation.id].value)) : 0}
- -
-
- -
-
- {pointedLocation && ( - <> -
{pointedLocation.name}
-
- Avg: {dataMap[pointedLocation.id] ? numberWithCommas(parseInt(dataMap[pointedLocation.id].value)) : 0} -
- - )} -
- - ); + + )} +
+
+ ); } export default observer(SpeedIndexByLocation); diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index 499a560c7..d46d4d79b 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -23,6 +23,8 @@ import SessionsPerBrowserExample from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample'; import SlowestDomains from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains'; +import SpeedIndexByLocationExample + from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample'; export const CARD_CATEGORY = { PRODUCT_ANALYTICS: 'product-analytics', @@ -234,7 +236,8 @@ export const CARD_LIST: CardType[] = [ category: CARD_CATEGORIES[1].key, data: { chart: generateAreaData(), - label: "Number of Calls", + label: "Page Response Time (ms)", + unit: 'ms', namesMap: [ "Series 1" ] @@ -289,7 +292,7 @@ export const CARD_LIST: CardType[] = [ "Series 1" ] }, - example: AreaChartCard, + example: SpeedIndexByLocationExample, }, { diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx index d50fcab52..871c4519d 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx @@ -46,7 +46,7 @@ function AreaChartCard(props: Props) { {/*
*/} {/* */} {/*
*/} - + void - type: string - lineWidth: number +function ByComponent({ title, rows, lineWidth, onCard, type }: { + title: string + rows: { + label: string + progress: number + value: string + icon: React.ReactNode + }[] + onCard: (card: string) => void + type: string + lineWidth: number }) { - const _rows = rows.map((r) => ({ - ...r, - name: r.label, - sessionCount: r.value, - })).slice(0, 4) - return ( - -
- null}/> - - {/*{rows.map((r) => (*/} - {/* */} - {/*
{r.icon}
*/} - {/*
{r.label}
*/} - {/* */} - {/* */} - {/* */} - {/*
*/} - {/*
{r.value}
*/} - {/*
*/} - {/*))}*/} -
- - ) + const _rows = rows.map((r) => ({ + ...r, + name: r.label, + sessionCount: r.value + })).slice(0, 4); + return ( + +
+ null} /> +
+
+ ); } -export default ByComponent +export default ByComponent; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx new file mode 100644 index 000000000..98a88eef7 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import ExCard from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard'; +import InsightsCard from 'Components/Dashboard/Widgets/CustomMetricsWidgets/InsightsCard'; +import { InsightIssue } from 'App/mstore/types/widget'; +import SessionsPerBrowser from 'Components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser'; +import SpeedIndexByLocation from 'Components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation'; + +interface Props { + title: string; + type: string; + onCard: (card: string) => void; +} + +function SpeedIndexByLocationExample(props: Props) { + const data = { + 'value': 1480, + 'chart': [ + { + 'userCountry': 'AT', + 'value': 415 + }, + { + 'userCountry': 'PL', + 'value': 433.1666666666667 + }, + { + 'userCountry': 'FR', + 'value': 502 + }, + { + 'userCountry': 'IT', + 'value': 540.4117647058823 + }, + { + 'userCountry': 'TH', + 'value': 662.0 + }, + { + 'userCountry': 'ES', + 'value': 740.5454545454545 + }, + { + 'userCountry': 'SG', + 'value': 889.6666666666666 + }, + { + 'userCountry': 'TW', + 'value': 1008.0 + }, + { + 'userCountry': 'HU', + 'value': 1027.0 + }, + { + 'userCountry': 'DE', + 'value': 1054.4583333333333 + }, + { + 'userCountry': 'BE', + 'value': 1126.0 + }, + { + 'userCountry': 'TR', + 'value': 1174.0 + }, + { + 'userCountry': 'US', + 'value': 1273.3015873015872 + }, + { + 'userCountry': 'GB', + 'value': 1353.8095238095239 + }, + { + 'userCountry': 'VN', + 'value': 1473.8181818181818 + }, + { + 'userCountry': 'HK', + 'value': 1654.6666666666667 + }, + ], + 'unit': 'ms' + }; + return ( + + + + ); +} + +export default SpeedIndexByLocationExample; diff --git a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx index dc019b8f8..174bc93f1 100644 --- a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx @@ -60,7 +60,7 @@ function WidgetPredefinedChart(props: Props) { case FilterKey.PAGES_RESPONSE_TIME_DISTRIBUTION: return case FilterKey.SPEED_LOCATION: - return + return case FilterKey.CPU: return case FilterKey.CRASHES: From 394222ed603100279b004bcca36b47fc2f55b576 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Mon, 1 Jul 2024 20:46:51 +0530 Subject: [PATCH 53/66] Minor improvements --- frontend/app/components/Client/Sites/ProjectKey.tsx | 7 ++++++- frontend/app/components/Client/Sites/Sites.tsx | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/Client/Sites/ProjectKey.tsx b/frontend/app/components/Client/Sites/ProjectKey.tsx index 67391720c..a00b32d07 100644 --- a/frontend/app/components/Client/Sites/ProjectKey.tsx +++ b/frontend/app/components/Client/Sites/ProjectKey.tsx @@ -1,8 +1,13 @@ import { withCopy } from 'HOCs'; import React from 'react'; +import { Tag } from "antd"; function ProjectKey({ value }: any) { - return
{value}
; + return
+ + {value} + +
; } export default withCopy(ProjectKey); diff --git a/frontend/app/components/Client/Sites/Sites.tsx b/frontend/app/components/Client/Sites/Sites.tsx index b9f046442..ccab226c2 100644 --- a/frontend/app/components/Client/Sites/Sites.tsx +++ b/frontend/app/components/Client/Sites/Sites.tsx @@ -77,7 +77,7 @@ const Sites = ({ loading, sites, user, init }: PropsFromRedux) => {
{project.host}
- {project.platform === 'web' ? null : MOBILE BETA} + {project.platform === 'web' ? null : MOBILE BETA}
From caa55de1b6a0299a6496559e28e9a58022db920d Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 17:19:58 +0200 Subject: [PATCH 54/66] change(ui): funnel bar style changes --- .../NewDashModal/ExampleCards.tsx | 21 +- .../NewDashModal/Examples/BarChart.tsx | 114 ++++---- .../Funnels/FunnelWidget/FunnelBar.tsx | 243 +++++++++--------- 3 files changed, 191 insertions(+), 187 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index d46d4d79b..4aa314c95 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -235,14 +235,14 @@ export const CARD_LIST: CardType[] = [ metricOf: FilterKey.PAGES_RESPONSE_TIME_DISTRIBUTION, category: CARD_CATEGORIES[1].key, data: { - chart: generateAreaData(), - label: "Page Response Time (ms)", + chart: generateBarChartData(), + label: "Number of Calls", unit: 'ms', namesMap: [ "Series 1" ] }, - example: AreaChartCard, + example: BarChartCard, }, { @@ -252,7 +252,7 @@ export const CARD_LIST: CardType[] = [ metricOf: FilterKey.RESOURCES_VS_VISUALLY_COMPLETE, category: CARD_CATEGORIES[1].key, data: { - chart: generateBarChartDate(), + chart: generateBarChartData(), namesMap: [ "Series 1" ] @@ -303,6 +303,8 @@ export const CARD_LIST: CardType[] = [ category: CARD_CATEGORIES[1].key, data: { chart: generateAreaData(), + label: "Time to Render (ms)", + unit: 'ms', namesMap: [ "Series 1" ] @@ -318,9 +320,10 @@ export const CARD_LIST: CardType[] = [ category: CARD_CATEGORIES[1].key, data: { chart: generateAreaData(), + label: "Number of Sessions", namesMap: [ "Series 1" - ] + ], }, example: AreaChartCard, }, @@ -386,7 +389,7 @@ export const CARD_LIST: CardType[] = [ metricOf: FilterKey.IMPACTED_SESSIONS_BY_JS_ERRORS, category: CARD_CATEGORIES[3].key, data: { - chart: generateBarChartDate(), + chart: generateBarChartData(), }, example: BarChartCard, }, @@ -397,7 +400,7 @@ export const CARD_LIST: CardType[] = [ metricOf: FilterKey.RESOURCES_BY_PARTY, category: CARD_CATEGORIES[3].key, data: { - chart: generateBarChartDate(), + chart: generateBarChartData(), }, example: BarChartCard, }, @@ -417,7 +420,7 @@ export const CARD_LIST: CardType[] = [ metricOf: FilterKey.ERRORS_PER_TYPE, category: CARD_CATEGORIES[3].key, data: { - chart: generateBarChartDate(), + chart: generateBarChartData(), }, example: BarChartCard, }, @@ -725,7 +728,7 @@ function generateRandomValue(min: number, max: number): number { return Math.floor(Math.random() * (max - min + 1)) + min; } -function generateBarChartDate(): any[] { +function generateBarChartData(): any[] { const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']; return months.map(month => ({ time: month, diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx index a34bda906..cab940cc4 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/BarChart.tsx @@ -1,70 +1,70 @@ -import {GitCommitHorizontal} from 'lucide-react'; +import { GitCommitHorizontal } from 'lucide-react'; import React from 'react'; import ExCard from './ExCard'; -import {PERFORMANCE} from "App/constants/card"; -import {Bar, BarChart, CartesianGrid, Legend, Rectangle, ResponsiveContainer, Tooltip, XAxis, YAxis} from "recharts"; -import {Styles} from "Components/Dashboard/Widgets/common"; +import { PERFORMANCE } from 'App/constants/card'; +import { Bar, BarChart, CartesianGrid, Legend, Rectangle, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; +import { Styles } from 'Components/Dashboard/Widgets/common'; interface Props { - title: string; - type: string; - onCard: (card: string) => void; - onClick?: any; - data?: any, + title: string; + type: string; + onCard: (card: string) => void; + onClick?: any; + data?: any, } function BarChartCard(props: Props) { - return ( - + {/**/} + {/* */} + {/* /!**!/*/} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* }/>*/} + {/* /!*}/>*!/*/} + {/* */} + {/**/} + + + - {/**/} - {/* */} - {/* /!**!/*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* }/>*/} - {/* /!*}/>*!/*/} - {/* */} - {/**/} + + + Styles.tickFormatter(val)} + label={{ ...Styles.axisLabelLeft, value: props.data?.label || 'Number of Errors' }} + allowDecimals={false} + /> + + + One} + dataKey="value" stackId="a" fill={Styles.colors[0]} /> + {/*3rd Party} dataKey="thirdParty" stackId="a"*/} + {/* fill={Styles.colors[2]}/>*/} + +
+ - - - - - Styles.tickFormatter(val)} - label={{...Styles.axisLabelLeft, value: "Number of Errors"}} - allowDecimals={false} - /> - - - One} - dataKey="value" stackId="a" fill={Styles.colors[0]}/> - {/*3rd Party} dataKey="thirdParty" stackId="a"*/} - {/* fill={Styles.colors[2]}/>*/} - - - - - ); + ); } export default BarChartCard; diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx index 6a37e91fe..4006b7c32 100644 --- a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx +++ b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx @@ -1,148 +1,149 @@ -import {durationFormatted} from 'App/date'; +import { durationFormatted } from 'App/date'; import React from 'react'; import FunnelStepText from './FunnelStepText'; -import {Icon} from 'UI'; -import {Space} from "antd"; +import { Icon } from 'UI'; +import { Space } from 'antd'; +import { Styles } from 'Components/Dashboard/Widgets/common'; interface Props { - filter: any; - index?: number; - focusStage?: (index: number, isFocused: boolean) => void - focusedFilter?: number | null + filter: any; + index?: number; + focusStage?: (index: number, isFocused: boolean) => void; + focusedFilter?: number | null; } function FunnelBar(props: Props) { - const {filter, index, focusStage, focusedFilter} = props; + const { filter, index, focusStage, focusedFilter } = props; - const isFocused = focusedFilter && index ? focusedFilter === index - 1 : false; - return ( -
- -
-
-
- {filter.completedPercentageTotal}% -
-
-
focusStage?.(index! - 1, filter.isActive)} - className={'hover:opacity-75'} - /> -
-
- {/* @ts-ignore */} -
- - {filter.sessionsCount} Sessions - + const isFocused = focusedFilter && index ? focusedFilter === index - 1 : false; + return ( +
+ +
+
+
+ {filter.completedPercentageTotal}% +
+
+
focusStage?.(index! - 1, filter.isActive)} + className={'hover:opacity-75'} + /> +
+
+ {/* @ts-ignore */} +
+ + {filter.sessionsCount} Sessions + ({filter.completedPercentage}%) Completed -
- - 0 ? "red" : "gray-light"} size={16}/> - 0 ? 'color-red' : 'disabled')}>{filter.droppedCount} Sessions - 0 ? 'color-red' : 'disabled')}>({filter.droppedPercentage}%) Dropped - -
- ); + + 0 ? 'red' : 'gray-light'} size={16} /> + 0 ? 'color-red' : 'disabled')}>{filter.droppedCount} Sessions + 0 ? 'color-red' : 'disabled')}>({filter.droppedPercentage}%) Dropped + +
+
+ ); } export function UxTFunnelBar(props: Props) { - const {filter} = props; + const { filter } = props; - return ( -
-
{filter.title}
-
-
-
- {((filter.completed / (filter.completed + filter.skipped)) * 100).toFixed(1)}% -
-
-
-
- {/* @ts-ignore */} -
-
- - {filter.completed}completed this step -
-
- - + return ( +
+
{filter.title}
+
+
+
+ {((filter.completed / (filter.completed + filter.skipped)) * 100).toFixed(1)}% +
+
+
+
+ {/* @ts-ignore */} +
+
+ + {filter.completed}completed this step +
+
+ + {durationFormatted(filter.avgCompletionTime)} - + Avg. completion time -
-
- {/* @ts-ignore */} -
- - {filter.skipped} skipped -
-
+
- ); + {/* @ts-ignore */} +
+ + {filter.skipped} skipped +
+
+
+ ); } export default FunnelBar; const calculatePercentage = (completed: number, dropped: number) => { - const total = completed + dropped; - if (dropped === 0) return 100; - if (total === 0) return 0; + const total = completed + dropped; + if (dropped === 0) return 100; + if (total === 0) return 0; - return Math.round((completed / dropped) * 100); + return Math.round((completed / dropped) * 100); }; From b6c26bcf03e438f8c40c1d916cf3c90ee717c223 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 17:24:02 +0200 Subject: [PATCH 55/66] change(ui): dashboard list show created by --- .../components/DashboardList/DashboardList.tsx | 14 +++++++------- frontend/app/mstore/types/dashboard.ts | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 60c567054..64290f498 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -41,10 +41,10 @@ function DashboardList({ siteId }: { siteId: string }) { render: (date) => checkForRecent(date, 'LLL dd, yyyy, hh:mm a'), }, { - title: 'Modified By', - dataIndex: 'updatedBy', + title: 'Created By', + dataIndex: 'ownerEmail', width: '16.67%', - sorter: (a, b) => a.updatedBy.localeCompare(b.updatedBy), + sorter: (a, b) => a.ownerEmail.localeCompare(b.ownerEmail), sortDirections: ['ascend', 'descend'], }, { @@ -104,13 +104,13 @@ function DashboardList({ siteId }: { siteId: string }) { list.length === 0 && !dashboardStore.filter.showMine ? (
} - imageStyle={{ - width: imageDimensions.width, + image={} + imageStyle={{ + width: imageDimensions.width, height: imageDimensions.height, margin: 'auto', padding: '2rem 0' - }} + }} description={emptyDescription} />
diff --git a/frontend/app/mstore/types/dashboard.ts b/frontend/app/mstore/types/dashboard.ts index b1d1a4743..cea9a26fe 100644 --- a/frontend/app/mstore/types/dashboard.ts +++ b/frontend/app/mstore/types/dashboard.ts @@ -17,6 +17,7 @@ export default class Dashboard { currentWidget: Widget = new Widget() config: any = {} createdAt: number = new Date().getTime() + ownerEmail: string = "" constructor() { makeAutoObservable(this) @@ -65,6 +66,7 @@ export default class Dashboard { this.isPublic = json.isPublic this.key = json.dashboardId this.createdAt = DateTime.fromMillis(new Date(json.createdAt).getTime()) + this.ownerEmail = json.ownerEmail if (json.widgets) { const smallWidgets: any[] = json.widgets.filter(wi => wi.config.col === 1) const otherWidgets: any[] = json.widgets.filter(wi => wi.config.col !== 1) From 04754504cebbd3b61ccf531e07ca83dbbb68efb7 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 17:24:25 +0200 Subject: [PATCH 56/66] change(ui): dashboard list show created by --- .../Dashboard/components/DashboardList/DashboardList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 64290f498..9289e1376 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -41,7 +41,7 @@ function DashboardList({ siteId }: { siteId: string }) { render: (date) => checkForRecent(date, 'LLL dd, yyyy, hh:mm a'), }, { - title: 'Created By', + title: 'Owner', dataIndex: 'ownerEmail', width: '16.67%', sorter: (a, b) => a.ownerEmail.localeCompare(b.ownerEmail), From 31efd79d5a312d461947366f457a80dd0ed38e90 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 17:28:03 +0200 Subject: [PATCH 57/66] change(ui): dashboard list show created by --- .../Dashboard/components/DashboardList/DashboardList.tsx | 4 ++-- frontend/app/mstore/types/dashboard.ts | 4 ++-- frontend/app/mstore/types/widget.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx index 9289e1376..7740ec10b 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardList.tsx @@ -42,9 +42,9 @@ function DashboardList({ siteId }: { siteId: string }) { }, { title: 'Owner', - dataIndex: 'ownerEmail', + dataIndex: 'owner', width: '16.67%', - sorter: (a, b) => a.ownerEmail.localeCompare(b.ownerEmail), + sorter: (a, b) => a.owner.localeCompare(b.owner), sortDirections: ['ascend', 'descend'], }, { diff --git a/frontend/app/mstore/types/dashboard.ts b/frontend/app/mstore/types/dashboard.ts index cea9a26fe..a82702596 100644 --- a/frontend/app/mstore/types/dashboard.ts +++ b/frontend/app/mstore/types/dashboard.ts @@ -17,7 +17,7 @@ export default class Dashboard { currentWidget: Widget = new Widget() config: any = {} createdAt: number = new Date().getTime() - ownerEmail: string = "" + owner: string = "" constructor() { makeAutoObservable(this) @@ -66,7 +66,7 @@ export default class Dashboard { this.isPublic = json.isPublic this.key = json.dashboardId this.createdAt = DateTime.fromMillis(new Date(json.createdAt).getTime()) - this.ownerEmail = json.ownerEmail + this.owner = json.ownerName if (json.widgets) { const smallWidgets: any[] = json.widgets.filter(wi => wi.config.col === 1) const otherWidgets: any[] = json.widgets.filter(wi => wi.config.col !== 1) diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 0eb5411dc..12887b57f 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -155,7 +155,7 @@ export default class Widget { ? json.series.map((series: any) => new FilterSeries().fromJson(series)) : [new FilterSeries()]; this.dashboards = json.dashboards || []; - this.owner = json.ownerEmail; + this.owner = json.ownerName; this.lastModified = json.editedAt || json.createdAt ? DateTime.fromMillis(json.editedAt || json.createdAt) From 1f06bb9401935658a3c5d2de6204e096cb50ef64 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 1 Jul 2024 17:50:03 +0200 Subject: [PATCH 58/66] change(ui): errors by domain examples and card type chagne --- .../ErrorsPerDomain/ErrorsPerDomain.tsx | 56 ++++++++++--------- .../NewDashModal/ExampleCards.tsx | 4 +- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx index c33ef2be8..1f261c38c 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx @@ -1,38 +1,40 @@ import React from 'react'; -import { NoContent } from 'UI'; +import { Icon, NoContent } from 'UI'; import { Styles } from '../../common'; import { numberWithCommas } from 'App/utils'; import Bar from './Bar'; -import { NO_METRIC_DATA } from 'App/constants/messages' +import { NO_METRIC_DATA } from 'App/constants/messages'; +import ListWithIcons from 'Components/Dashboard/Widgets/ListWithIcons'; interface Props { - data: any + data: any; } + function ErrorsPerDomain(props: Props) { - const { data } = props; - // const firstAvg = 10; - const firstAvg = data.chart[0] && data.chart[0].errorsCount; - return ( - -
- {data.chart.map((item, i) => - - )} -
-
- ); + const { data } = props; + // const firstAvg = 10; + // const firstAvg = data.chart[0] && data.chart[0].errorsCount; + + const highest = data.chart[0] && data.chart[0].errorsCount; + const list = data.chart.slice(0, 4).map((item: any) => ({ + name: item.domain, + icon: , + value: Math.round(item.errorsCount), + progress: Math.round((item.errorsCount * 100) / highest) + })); + + return ( + +
+ +
+
+ ); } export default ErrorsPerDomain; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index 4aa314c95..3732dd995 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -410,8 +410,8 @@ export const CARD_LIST: CardType[] = [ cardType: ERRORS, metricOf: FilterKey.ERRORS_PER_DOMAINS, category: CARD_CATEGORIES[3].key, - example: Bars, - data: generateRandomBarsData(), + example: SlowestDomains, + // data: generateRandomBarsData(), }, { title: 'Errors by Type', From 11453b80a2b237c0da43d9c0bca070e7960e6338 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 2 Jul 2024 10:15:50 +0200 Subject: [PATCH 59/66] change(ui): dashboard interactive --- .../PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx | 6 ------ .../components/DashboardWidgetGrid/DashboardWidgetGrid.tsx | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx index 1f261c38c..ab2e4b6b3 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/ErrorsPerDomain/ErrorsPerDomain.tsx @@ -1,8 +1,5 @@ import React from 'react'; import { Icon, NoContent } from 'UI'; -import { Styles } from '../../common'; -import { numberWithCommas } from 'App/utils'; -import Bar from './Bar'; import { NO_METRIC_DATA } from 'App/constants/messages'; import ListWithIcons from 'Components/Dashboard/Widgets/ListWithIcons'; @@ -12,9 +9,6 @@ interface Props { function ErrorsPerDomain(props: Props) { const { data } = props; - // const firstAvg = 10; - // const firstAvg = data.chart[0] && data.chart[0].errorsCount; - const highest = data.chart[0] && data.chart[0].errorsCount; const list = data.chart.slice(0, 4).map((item: any) => ({ name: item.domain, diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index e017d9615..33f472da2 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -54,7 +54,7 @@ function DashboardWidgetGrid(props: Props) { } dashboardId={dashboardId} siteId={siteId} - isWidget={true} + isWidget={false} grid="other" /> From a62a19a38d8745f25f2eb3edaa5ced6f37ef6f2b Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 2 Jul 2024 10:45:10 +0200 Subject: [PATCH 60/66] change(ui): dashboard back button --- .../CustomMetricsWidgets/SessionsBy.tsx | 3 +- .../DashboardHeader/DashboardHeader.tsx | 204 +++++++++--------- .../WidgetWrapper/WidgetWrapperNew.tsx | 2 +- .../shared/Breadcrumb/BackButton.tsx | 22 +- 4 files changed, 116 insertions(+), 115 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx index 5ad6fdf3e..33352d59c 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx @@ -38,7 +38,8 @@ function SessionsBy(props: Props) { onClick(filters); }; - const showMore = () => { + const showMore = (e: any) => { + e.stopPropagation(); openModal( { closeModal(); diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 3a9fbeff5..09f2348f6 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -1,24 +1,24 @@ import React from 'react'; //import {Breadcrumb} from 'Shared/Breadcrumb'; import BackButton from '../../../shared/Breadcrumb/BackButton'; -import {withSiteId} from 'App/routes'; -import {withRouter, RouteComponentProps} from 'react-router-dom'; -import {Button, PageTitle, confirm, Tooltip} from 'UI'; +import { withSiteId } from 'App/routes'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { Button, PageTitle, confirm, Tooltip } from 'UI'; import SelectDateRange from 'Shared/SelectDateRange'; -import {useStore} from 'App/mstore'; -import {useModal} from 'App/components/Modal'; +import { useStore } from 'App/mstore'; +import { useModal } from 'App/components/Modal'; import DashboardOptions from '../DashboardOptions'; import withModal from 'App/components/Modal/withModal'; -import {observer} from 'mobx-react-lite'; +import { observer } from 'mobx-react-lite'; import DashboardEditModal from '../DashboardEditModal'; -import CreateDashboardButton from "Components/Dashboard/components/CreateDashboardButton"; -import CreateCard from "Components/Dashboard/components/DashboardList/NewDashModal/CreateCard"; -import CreateCardButton from "Components/Dashboard/components/CreateCardButton"; +import CreateDashboardButton from 'Components/Dashboard/components/CreateDashboardButton'; +import CreateCard from 'Components/Dashboard/components/DashboardList/NewDashModal/CreateCard'; +import CreateCardButton from 'Components/Dashboard/components/CreateCardButton'; interface IProps { - dashboardId: string; - siteId: string; - renderReport?: any; + dashboardId: string; + siteId: string; + renderReport?: any; } @@ -26,49 +26,49 @@ type Props = IProps & RouteComponentProps; const MAX_CARDS = 29; function DashboardHeader(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 period = dashboardStore.period; + const { siteId, dashboardId } = props; + const { dashboardStore } = useStore(); + const { showModal } = useModal(); + const [focusTitle, setFocusedInput] = React.useState(true); + const [showEditModal, setShowEditModal] = React.useState(false); + const period = dashboardStore.period; - const dashboard: any = dashboardStore.selectedDashboard; - const canAddMore: boolean = dashboard?.widgets?.length <= MAX_CARDS; + const dashboard: any = dashboardStore.selectedDashboard; + const canAddMore: boolean = dashboard?.widgets?.length <= MAX_CARDS; - const onEdit = (isTitle: boolean) => { - dashboardStore.initDashboard(dashboard); - setFocusedInput(isTitle); - setShowEditModal(true); - }; + const onEdit = (isTitle: boolean) => { + dashboardStore.initDashboard(dashboard); + setFocusedInput(isTitle); + setShowEditModal(true); + }; - const onDelete = async () => { - if ( - await confirm({ - header: 'Delete Dashboard', - confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this Dashboard?`, - }) - ) { - dashboardStore.deleteDashboard(dashboard).then(() => { - props.history.push(withSiteId(`/dashboard`, siteId)); - }); - } - }; - return ( -
- setShowEditModal(false)} - focusTitle={focusTitle} - /> - -
-
+ const onDelete = async () => { + if ( + await confirm({ + header: 'Delete Dashboard', + confirmButton: 'Yes, delete', + confirmation: `Are you sure you want to permanently delete this Dashboard?` + }) + ) { + dashboardStore.deleteDashboard(dashboard).then(() => { + props.history.push(withSiteId(`/dashboard`, siteId)); + }); + } + }; + return ( +
+ setShowEditModal(false)} + focusTitle={focusTitle} + /> - - - {/* +
+ + + + {/* */} - - - - {dashboard?.name} - - } - onDoubleClick={() => onEdit(true)} - className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dashed hover:border-gray-medium cursor-pointer" - /> -
-
- - -
- dashboardStore.setPeriod(period)} - right={true} - isAnt={true} - useButtonStyle={true} - /> -
- -
- -
-
-
-
- {/* @ts-ignore */} - -

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

-
-
+ + {dashboard?.name} + + } + onDoubleClick={() => onEdit(true)} + className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dashed hover:border-gray-medium cursor-pointer" + />
- ); +
+ + +
+ dashboardStore.setPeriod(period)} + right={true} + isAnt={true} + useButtonStyle={true} + /> +
+ +
+ +
+
+
+
+ {/* @ts-ignore */} + +

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

+
+
+
+ ); } export default withRouter(withModal(observer(DashboardHeader))); diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx index 043d0fc04..126e347b1 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetWrapperNew.tsx @@ -75,7 +75,7 @@ function WidgetWrapperNew(props: Props & RouteComponentProps) { }); const onChartClick = () => { - if (!isWidget || isPredefined) return; + // if (!isWidget || isPredefined) return; props.history.push( withSiteId(dashboardMetricDetails(dashboard?.dashboardId, widget.metricId), siteId) ); diff --git a/frontend/app/components/shared/Breadcrumb/BackButton.tsx b/frontend/app/components/shared/Breadcrumb/BackButton.tsx index 0eb961a84..334aebbd7 100644 --- a/frontend/app/components/shared/Breadcrumb/BackButton.tsx +++ b/frontend/app/components/shared/Breadcrumb/BackButton.tsx @@ -3,18 +3,20 @@ import { Button } from 'antd'; import { useHistory } from 'react-router-dom'; import { LeftOutlined } from '@ant-design/icons'; -function BackButton({ siteId }) { - const history = useHistory(); +function BackButton() { + const history = useHistory(); + const siteId = location.pathname.split('/')[1]; - const handleBackClick = () => { - history.goBack(); - }; + const handleBackClick = () => { + console.log('siteId', siteId); + history.push(`/${siteId}/dashboard`); + }; - return ( - - ); + return ( + + ); } export default BackButton; From b38eda8821678563f73272e30012d826019daf9e Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 2 Jul 2024 11:29:14 +0200 Subject: [PATCH 61/66] fix(ui): issues drilldown payload --- .../Dashboard/Widgets/CardSessionsByList.tsx | 98 ++++++------- .../CustomMetricsWidgets/SessionsBy.tsx | 3 +- .../shared/Breadcrumb/BackButton.tsx | 1 - frontend/app/mstore/types/sessionsCardData.ts | 132 ++++++++---------- 4 files changed, 111 insertions(+), 123 deletions(-) diff --git a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx index a150c787f..135c5cb76 100644 --- a/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx +++ b/frontend/app/components/Dashboard/Widgets/CardSessionsByList.tsx @@ -1,60 +1,60 @@ import React from 'react'; -import { List, Progress, Typography } from "antd"; -import cn from "classnames"; +import { List, Progress, Typography } from 'antd'; +import cn from 'classnames'; interface Props { - list: any; - selected?: any; - onClickHandler?: (event: any, data: any) => void; + list: any; + selected?: any; + onClickHandler?: (event: any, data: any) => void; } function CardSessionsByList({ list, selected, onClickHandler = () => null }: Props) { - return ( - ( - onClickHandler(e, row)} // Remove onClick handler to disable click interaction - style={{ - borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', - padding: '4px 10px', - lineHeight: '1px' - }} - className={cn('rounded', selected === row.name ? 'bg-active-blue' : '')} // Remove hover:bg-active-blue and cursor-pointer - > - -
- {row.name} - {row.sessionCount} -
+ return ( + ( + onClickHandler(e, row)} // Remove onClick handler to disable click interaction + style={{ + borderBottom: '1px dotted rgba(0, 0, 0, 0.05)', + padding: '4px 10px', + lineHeight: '1px' + }} + className={cn('rounded', selected === row.name ? 'bg-active-blue' : '')} // Remove hover:bg-active-blue and cursor-pointer + > + +
+ {row.displayName} + {row.sessionCount} +
- -
- )} - /> - + +
)} - /> - ); + /> + + )} + /> + ); } export default CardSessionsByList; diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx index 33352d59c..288e40992 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/SessionsBy.tsx @@ -67,6 +67,7 @@ function SessionsBy(props: Props) { /> ) : (
+ {/* TODO - remove slice once the api pagination is fixed */} @@ -74,7 +75,7 @@ function SessionsBy(props: Props) {
diff --git a/frontend/app/components/shared/Breadcrumb/BackButton.tsx b/frontend/app/components/shared/Breadcrumb/BackButton.tsx index 334aebbd7..a93ad705f 100644 --- a/frontend/app/components/shared/Breadcrumb/BackButton.tsx +++ b/frontend/app/components/shared/Breadcrumb/BackButton.tsx @@ -8,7 +8,6 @@ function BackButton() { const siteId = location.pathname.split('/')[1]; const handleBackClick = () => { - console.log('siteId', siteId); history.push(`/${siteId}/dashboard`); }; diff --git a/frontend/app/mstore/types/sessionsCardData.ts b/frontend/app/mstore/types/sessionsCardData.ts index 459ecd3c3..2e98f05d2 100644 --- a/frontend/app/mstore/types/sessionsCardData.ts +++ b/frontend/app/mstore/types/sessionsCardData.ts @@ -1,98 +1,86 @@ -import {numberWithCommas} from "App/utils"; -import {countries} from "App/constants"; +import { numberWithCommas } from 'App/utils'; +import { countries } from 'App/constants'; import { - BrowserIconProvider, - CountryIconProvider, DeviceIconProvider, - IconProvider, - IssueIconProvider, OsIconProvider, - UrlIconProvider, UserIconProvider -} from "./IconProvider"; + BrowserIconProvider, + CountryIconProvider, DeviceIconProvider, + IconProvider, + IssueIconProvider, OsIconProvider, + UrlIconProvider, UserIconProvider +} from './IconProvider'; +import React from 'react'; interface NameFormatter { - format(name: string): string; + format(name: string): string; } class BaseFormatter implements NameFormatter { - format(name: string): string { - return name.replace(/_/g, ' ').replace(/\w\S*/g, (w) => (w.replace(/^\w/, (c) => c.toUpperCase()))).trim(); - } + format(name: string): string { + return name.replace(/_/g, ' ').replace(/\w\S*/g, (w) => (w.replace(/^\w/, (c) => c.toUpperCase()))).trim(); + } } class BrowserFormatter extends BaseFormatter { - format(name: string): string { - return super.format(name); - } + format(name: string): string { + return super.format(name); + } } class CountryFormatter extends BaseFormatter { - format(name: string): string { - if (name === 'UN') { - return 'Unknown Country'; - } - return countries[name.toUpperCase()] || name; + format(name: string): string { + if (name === 'UN') { + return 'Unknown Country'; } + return countries[name.toUpperCase()] || name; + } } class IssueFormatter extends BaseFormatter { - format(name: string): string { - return super.format(name); - } + format(name: string): string { + return super.format(name); + } } export class SessionsByRow { - name: string; - sessionCount: number; - progress: number; - icon: React.ReactNode; + name: string; + displayName: string; + sessionCount: number; + progress: number; + icon: React.ReactNode; - fromJson(json: any, totalSessions: number, metricType: string) { - const {nameFormatter, iconProvider} = this.getFormatters(metricType); - this.name = nameFormatter.format(json.name) || 'Unidentified'; - this.sessionCount = numberWithCommas(json.sessionCount); - this.progress = Math.round((json.sessionCount / totalSessions) * 100); - this.icon = iconProvider.getIcon(json.name); - return this; - } + fromJson(json: any, totalSessions: number, metricType: string) { + const { nameFormatter, iconProvider } = this.getFormatters(metricType); + this.name = json.name; + this.displayName = nameFormatter.format(json.name) || 'Unidentified'; + this.sessionCount = numberWithCommas(json.sessionCount); + this.progress = Math.round((json.sessionCount / totalSessions) * 100); + this.icon = iconProvider.getIcon(json.name); + return this; + } - private getFormatters(metricType: string): { nameFormatter: NameFormatter; iconProvider: IconProvider } { - switch (metricType) { - case 'userBrowser': - return {nameFormatter: new BrowserFormatter(), iconProvider: new BrowserIconProvider()}; - case 'userCountry': - return {nameFormatter: new CountryFormatter(), iconProvider: new CountryIconProvider()}; - case 'issue': - return {nameFormatter: new IssueFormatter(), iconProvider: new IssueIconProvider()}; - case 'location': - return {nameFormatter: new BaseFormatter(), iconProvider: new UrlIconProvider()}; - case 'userDevice': - return {nameFormatter: new BaseFormatter(), iconProvider: new DeviceIconProvider()}; - case 'platform': - return {nameFormatter: new BaseFormatter(), iconProvider: new OsIconProvider()}; - case 'userId': - return {nameFormatter: new BaseFormatter(), iconProvider: new UserIconProvider()}; - default: - return {nameFormatter: new BaseFormatter(), iconProvider: new DefaultIconProvider()}; - } + private getFormatters(metricType: string): { nameFormatter: NameFormatter; iconProvider: IconProvider } { + switch (metricType) { + case 'userBrowser': + return { nameFormatter: new BrowserFormatter(), iconProvider: new BrowserIconProvider() }; + case 'userCountry': + return { nameFormatter: new CountryFormatter(), iconProvider: new CountryIconProvider() }; + case 'issue': + return { nameFormatter: new IssueFormatter(), iconProvider: new IssueIconProvider() }; + case 'location': + return { nameFormatter: new BaseFormatter(), iconProvider: new UrlIconProvider() }; + case 'userDevice': + return { nameFormatter: new BaseFormatter(), iconProvider: new DeviceIconProvider() }; + case 'platform': + return { nameFormatter: new BaseFormatter(), iconProvider: new OsIconProvider() }; + case 'userId': + return { nameFormatter: new BaseFormatter(), iconProvider: new UserIconProvider() }; + default: + return { nameFormatter: new BaseFormatter(), iconProvider: new DefaultIconProvider() }; } + } } class DefaultIconProvider implements IconProvider { - getIcon(name: string): string { - return 'ic-user-path'; - } + getIcon(name: string): string { + return 'ic-user-path'; + } } - -// Usage example -// const data = [ -// { -// values: [ -// {name: 'chrome', sessionCount: 120}, -// {name: 'firefox', sessionCount: 80}, -// {name: 'safari', sessionCount: 50}, -// ] -// } -// ]; -// const totalSessions = 1000; -// const metricOf = 'browser'; -// -// data[0]['values'] = data[0]['values'].map((s: any) => new SessionsByRow().fromJson(s, totalSessions, metricOf)); From b75e008471b8af2a8799b770bc787ba04d135522 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Tue, 2 Jul 2024 15:04:05 +0530 Subject: [PATCH 62/66] various ui improvements --- .../app/components/Session_/Issues/Issues.js | 6 +-- .../Controls/components/KeyboardHelp.tsx | 9 +++-- .../Player/Controls/components/ReadNote.tsx | 32 ++++++++++----- frontend/app/components/Session_/Subheader.js | 9 +++-- .../Session_/components/NotePopup.tsx | 6 +-- .../components/shared/Bookmark/Bookmark.tsx | 7 ++-- .../LiveSessionList/LiveSessionList.tsx | 4 +- .../shared/ReloadButton/ReloadButton.tsx | 8 ++-- .../components/Notes/NoteItem.tsx | 36 ++++++++++------- .../components/Notes/TeamBadge.tsx | 2 +- .../components/SessionList/SessionList.tsx | 2 +- .../SessionCopyLink/SessionCopyLink.tsx | 11 +++-- .../shared/SharePopup/SharePopup.tsx | 6 +-- .../SortOrderButton/SortOrderButton.tsx | 40 ++++++++----------- .../app/components/ui/ItemMenu/ItemMenu.tsx | 6 +-- frontend/app/components/ui/Link/Link.js | 2 +- frontend/app/services/NotesService.ts | 4 +- 17 files changed, 105 insertions(+), 85 deletions(-) diff --git a/frontend/app/components/Session_/Issues/Issues.js b/frontend/app/components/Session_/Issues/Issues.js index b1ef46f39..db5671454 100644 --- a/frontend/app/components/Session_/Issues/Issues.js +++ b/frontend/app/components/Session_/Issues/Issues.js @@ -3,7 +3,7 @@ import { connect } from 'react-redux'; import { Popover, Icon } from 'UI'; import IssuesModal from './IssuesModal'; import { fetchProjects, fetchMeta } from 'Duck/assignments'; -import { Popover as AntPopover, Button } from 'antd'; +import { Tooltip, Button } from 'antd'; @connect( (state) => ({ @@ -67,11 +67,11 @@ class Issues extends React.Component { )} >
- + - +
); diff --git a/frontend/app/components/Session_/Player/Controls/components/KeyboardHelp.tsx b/frontend/app/components/Session_/Player/Controls/components/KeyboardHelp.tsx index 0d15d581e..981616ba7 100644 --- a/frontend/app/components/Session_/Player/Controls/components/KeyboardHelp.tsx +++ b/frontend/app/components/Session_/Player/Controls/components/KeyboardHelp.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Icon } from 'UI'; -import { Popover, Button } from 'antd'; +import {Keyboard} from 'lucide-react' +import { Button, Tooltip } from 'antd'; import { useModal } from "../../../../Modal"; const Key = ({ label }: { label: string }) =>
{label}
; @@ -35,7 +36,7 @@ function ShortcutGrid() { return (
Keyboard Shortcuts
-
+
@@ -61,6 +62,7 @@ function ShortcutGrid() { function KeyboardHelp() { const { showModal } = useModal(); return ( + + ); } diff --git a/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx b/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx index 8b3ad1b15..af18b5962 100644 --- a/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx +++ b/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx @@ -1,11 +1,12 @@ import React from 'react'; import { Icon } from 'UI'; +import { Button, Tag } from 'antd'; +import { PlayCircleOutlined } from '@ant-design/icons'; import { tagProps, Note } from 'App/services/NotesService'; import { formatTimeOrDate } from 'App/date'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { TeamBadge } from 'Shared/SessionsTabOverview/components/Notes'; -import { Tag } from 'antd' interface Props { note?: Note; @@ -21,7 +22,7 @@ function ReadNote(props: Props) { return (
@@ -50,8 +51,8 @@ function ReadNote(props: Props) { className="flex items-center justify-center" >
@@ -71,23 +72,32 @@ function ReadNote(props: Props) { {props.note.message}
-
+
+
{props.note.tag ? ( {props.note.tag} ) : null} + + {!props.note.isPublic ? null : } + -
- - Play Session
+ +
diff --git a/frontend/app/components/Session_/Subheader.js b/frontend/app/components/Session_/Subheader.js index 6e6f697f9..0ca04e1d8 100644 --- a/frontend/app/components/Session_/Subheader.js +++ b/frontend/app/components/Session_/Subheader.js @@ -1,7 +1,7 @@ import React, { useMemo } from 'react'; import { useStore } from 'App/mstore'; import KeyboardHelp from 'Components/Session_/Player/Controls/components/KeyboardHelp'; -import { Icon, Tooltip } from 'UI'; +import { Icon } from 'UI'; import QueueControls from './QueueControls'; import Bookmark from 'Shared/Bookmark'; import SharePopup from '../shared/SharePopup/SharePopup'; @@ -13,7 +13,7 @@ import { connect } from 'react-redux'; import SessionTabs from 'Components/Session/Player/SharedComponents/SessionTabs'; import { IFRAME } from 'App/constants/storageKeys'; import cn from 'classnames'; -import { Switch, Button as AntButton, Popover } from 'antd'; +import { Switch, Button as AntButton, Popover, Tooltip } from 'antd'; import { ShareAltOutlined } from '@ant-design/icons'; const localhostWarn = (project) => project + '_localhost_warn'; @@ -96,6 +96,7 @@ function SubHeader(props) { )} style={{ width: 'max-content' }} > + @@ -104,11 +105,11 @@ function SubHeader(props) { showCopyLink={true} trigger={
- + - +
} /> diff --git a/frontend/app/components/Session_/components/NotePopup.tsx b/frontend/app/components/Session_/components/NotePopup.tsx index ae45fc926..cedeec750 100644 --- a/frontend/app/components/Session_/components/NotePopup.tsx +++ b/frontend/app/components/Session_/components/NotePopup.tsx @@ -2,7 +2,7 @@ import CreateNote from 'Components/Session_/Player/Controls/components/CreateNot import React from 'react'; import { connect } from 'react-redux'; import { PlayerContext } from 'App/components/Session/playerContext'; -import { Button, Popover } from 'antd'; +import { Button, Tooltip } from 'antd'; import { MessageOutlined } from '@ant-design/icons'; import { useModal } from 'App/components/Modal'; @@ -22,7 +22,7 @@ function NotePopup({ tooltipActive }: { tooltipActive: boolean }) { }; return ( - + - + ); } diff --git a/frontend/app/components/shared/Bookmark/Bookmark.tsx b/frontend/app/components/shared/Bookmark/Bookmark.tsx index d7c549f88..225476b68 100644 --- a/frontend/app/components/shared/Bookmark/Bookmark.tsx +++ b/frontend/app/components/shared/Bookmark/Bookmark.tsx @@ -1,4 +1,4 @@ -import { Button, Popover } from 'antd'; +import { Button, Tooltip } from 'antd'; import { BookmarkCheck, Bookmark as BookmarkIcn, Vault } from 'lucide-react'; import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; @@ -13,6 +13,7 @@ interface Props { isEnterprise: boolean; noMargin?: boolean; } + function Bookmark(props: Props) { const { sessionId, favorite, isEnterprise, noMargin } = props; const [isFavorite, setIsFavorite] = useState(favorite); @@ -48,7 +49,7 @@ function Bookmark(props: Props) { return (
- + - +
); } diff --git a/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx b/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx index 5f67e292d..03ff62f8a 100644 --- a/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx +++ b/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx @@ -41,7 +41,7 @@ function LiveSessionList(props: Props) { var timeoutId: any; const { filters } = filter; const hasUserFilter = filters.map((i: any) => i.key).includes(KEYS.USERID); - const sortOptions = [{ label: 'Newest', value: 'timestamp' }].concat( + const sortOptions = [{ label: 'Freshness', value: 'timestamp' }].concat( metaList .map((i: any) => ({ label: capitalize(i), @@ -105,6 +105,7 @@ function LiveSessionList(props: Props) { onChange={onSortChange} value={sortOptions.find((i: any) => i.value === filter.sort) || sortOptions[0]} /> +
props.applyFilter({ order: state })} @@ -204,3 +205,4 @@ export default withPermissions(['ASSIST_LIVE'])( } )(LiveSessionList) ); + diff --git a/frontend/app/components/shared/ReloadButton/ReloadButton.tsx b/frontend/app/components/shared/ReloadButton/ReloadButton.tsx index 774d427fe..03285c749 100644 --- a/frontend/app/components/shared/ReloadButton/ReloadButton.tsx +++ b/frontend/app/components/shared/ReloadButton/ReloadButton.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { CircularLoader, Icon, Tooltip, Button } from 'UI'; +import {Button, Tooltip} from 'antd'; +import { ListRestart } from 'lucide-react'; import cn from 'classnames'; interface Props { @@ -12,8 +13,9 @@ interface Props { export default function ReloadButton(props: Props) { const { loading, onClick, iconSize = '20', iconName = 'arrow-repeat', className = '' } = props; return ( - - ); diff --git a/frontend/app/components/shared/SessionsTabOverview/components/Notes/NoteItem.tsx b/frontend/app/components/shared/SessionsTabOverview/components/Notes/NoteItem.tsx index af09b5928..723b7226f 100644 --- a/frontend/app/components/shared/SessionsTabOverview/components/Notes/NoteItem.tsx +++ b/frontend/app/components/shared/SessionsTabOverview/components/Notes/NoteItem.tsx @@ -35,35 +35,43 @@ function NoteItem(props: Props) { }); }; const menuItems = [ - { icon: 'link-45deg', text: 'Copy Note URL', onClick: onCopy }, + { icon: 'link-45deg', text: 'Copy Link', onClick: onCopy }, { icon: 'trash', text: 'Delete', onClick: onDelete }, ]; const safeStrMessage = props.note.message.length > 150 ? props.note.message.slice(0, 150) + '...' : props.note.message; return ( -
+
0 - ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` - : `?note=${props.note.noteId}`) - } - > -
-
{safeStrMessage}
-
- {props.note.tag ? ( + session(props.note.sessionId) + + (props.note.timestamp > 0 + ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` + : `?note=${props.note.noteId}`) + } + > +
+
+ + {props.note.tag ? ( {props.note.tag} ) : null} -
- By + +
+ {safeStrMessage} +
+
+
+ +
+ By {props.note.userName},{' '} {formatTimeOrDate(props.note.createdAt as unknown as number, timezone)}
diff --git a/frontend/app/components/shared/SessionsTabOverview/components/Notes/TeamBadge.tsx b/frontend/app/components/shared/SessionsTabOverview/components/Notes/TeamBadge.tsx index 8f509b5eb..9affbc7e1 100644 --- a/frontend/app/components/shared/SessionsTabOverview/components/Notes/TeamBadge.tsx +++ b/frontend/app/components/shared/SessionsTabOverview/components/Notes/TeamBadge.tsx @@ -5,7 +5,7 @@ export default function TeamBadge() { return (
- Team + Team
) } \ No newline at end of file diff --git a/frontend/app/components/shared/SessionsTabOverview/components/SessionList/SessionList.tsx b/frontend/app/components/shared/SessionsTabOverview/components/SessionList/SessionList.tsx index 08549dba9..dfd2a8504 100644 --- a/frontend/app/components/shared/SessionsTabOverview/components/SessionList/SessionList.tsx +++ b/frontend/app/components/shared/SessionsTabOverview/components/SessionList/SessionList.tsx @@ -215,7 +215,7 @@ function SessionList(props: Props) {
-
+
{NO_CONTENT.message}
diff --git a/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx b/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx index e408d683d..e0cd8a82b 100644 --- a/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx +++ b/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx @@ -1,5 +1,7 @@ import React from 'react'; -import { Button, Icon } from 'UI'; +import { Button } from 'antd'; +import { LinkOutlined } from '@ant-design/icons'; + import copy from 'copy-to-clipboard'; function SessionCopyLink({ time }: { time: number }) { @@ -20,11 +22,8 @@ function SessionCopyLink({ time }: { time: number }) { return (
- {copied &&
Copied
}
diff --git a/frontend/app/components/shared/SharePopup/SharePopup.tsx b/frontend/app/components/shared/SharePopup/SharePopup.tsx index 896168c49..ce7955924 100644 --- a/frontend/app/components/shared/SharePopup/SharePopup.tsx +++ b/frontend/app/components/shared/SharePopup/SharePopup.tsx @@ -175,7 +175,7 @@ function ShareModalComp({
-
+
Share via
{hasBoth ? ( @@ -214,7 +214,7 @@ function ShareModalComp({
-
Select a channel or individual
+
Select a channel or individual
{shareTo === 'slack' ? (