From b822b1c0677dd268914e3c0b0148a493d846d6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=91=D0=B0=D0=B1?= =?UTF-8?q?=D1=83=D1=88=D0=BA=D0=B8=D0=BD?= Date: Wed, 26 Feb 2025 20:31:01 +0100 Subject: [PATCH] applied eslint --- frontend/app/AdditionalRoutes.tsx | 8 +- frontend/app/IFrameRoutes.tsx | 37 +- frontend/app/PrivateRoutes.tsx | 33 +- frontend/app/PublicRoutes.tsx | 8 +- frontend/app/Router.tsx | 59 +- frontend/app/api_client.ts | 43 +- frontend/app/assets/prism/prism-bash.min.js | 168 +- .../app/assets/prism/prism-javascript.min.js | 127 +- frontend/app/assets/prism/prism-jsx.min.js | 96 +- frontend/app/assets/prism/prism-kotlin.min.js | 67 +- frontend/app/assets/prism/prism-swift.min.js | 97 +- .../app/assets/prism/prism-typescript.min.js | 43 +- frontend/app/assets/prism/prism.min.js | 913 +++- frontend/app/components/Alerts/AlertForm.js | 704 +-- .../Alerts/AlertFormModal/AlertFormModal.tsx | 141 +- .../components/Alerts/AlertFormModal/index.ts | 2 +- .../Alerts/DropdownChips/DropdownChips.js | 108 +- .../components/Alerts/DropdownChips/index.js | 2 +- .../Alerts/Notifications/Notifications.tsx | 12 +- .../components/Alerts/Notifications/index.ts | 2 +- frontend/app/components/Assist/Assist.tsx | 3 +- .../app/components/Assist/AssistRouter.tsx | 2 +- .../AssistSearchActions.tsx | 27 +- .../Assist/AssistSearchActions/index.ts | 2 +- frontend/app/components/Assist/AssistView.tsx | 6 +- .../Assist/ChatControls/ChatControls.tsx | 42 +- .../components/Assist/ChatControls/index.js | 2 +- .../Assist/ChatWindow/ChatWindow.tsx | 22 +- .../app/components/Assist/ChatWindow/index.ts | 2 +- .../RecordingsList/EditRecordingModal.tsx | 118 +- .../Assist/RecordingsList/Recordings.tsx | 22 +- .../Assist/RecordingsList/RecordingsList.tsx | 33 +- .../RecordingsList/RecordingsSearch.tsx | 46 +- .../Assist/RecordingsList/RecordsListItem.tsx | 2 +- .../RequestingWindow/RequestingWindow.tsx | 23 +- .../Assist/RequestingWindow/index.ts | 2 +- .../AssistActions/AssistActions.tsx | 67 +- .../Assist/components/AssistActions/index.ts | 2 +- .../components/SessionList/SessionList.tsx | 111 +- .../Assist/components/SessionList/index.ts | 2 +- .../VideoContainer/VideoContainer.tsx | 16 +- .../Assist/components/VideoContainer/index.ts | 2 +- frontend/app/components/Assist/index.ts | 2 +- .../components/AssistStats/AssistStats.tsx | 144 +- .../AssistStats/components/Charts.tsx | 4 +- .../AssistStats/components/Table.tsx | 87 +- .../AssistStats/components/TeamMembers.tsx | 29 +- .../AssistStats/components/UserSearch.tsx | 16 +- frontend/app/components/AssistStats/index.ts | 2 +- .../components/AssistStats/pdfGenerator.ts | 15 +- frontend/app/components/Charts/BarChart.tsx | 17 +- .../app/components/Charts/ColumnChart.tsx | 12 +- frontend/app/components/Charts/LineChart.tsx | 20 +- frontend/app/components/Charts/PieChart.tsx | 54 +- .../app/components/Charts/SankeyChart.tsx | 89 +- frontend/app/components/Charts/barUtils.ts | 3 +- frontend/app/components/Charts/init.ts | 16 +- frontend/app/components/Charts/pieUtils.ts | 11 +- frontend/app/components/Charts/sankeyUtils.ts | 21 +- frontend/app/components/Charts/utils.ts | 21 +- .../AuditDetailModal/AuditDetailModal.tsx | 80 +- .../Client/Audit/AuditDetailModal/index.ts | 2 +- .../Client/Audit/AuditList/AuditList.tsx | 118 +- .../Client/Audit/AuditList/index.ts | 2 +- .../Audit/AuditListItem/AuditListItem.tsx | 18 +- .../Client/Audit/AuditListItem/index.ts | 2 +- .../AuditSearchField/AuditSearchField.tsx | 42 +- .../Client/Audit/AuditSearchField/index.ts | 2 +- .../Client/Audit/AuditView/AuditView.tsx | 120 +- .../Client/Audit/AuditView/index.ts | 2 +- frontend/app/components/Client/Client.tsx | 10 +- .../Client/CustomFields/CustomFieldForm.js | 20 +- .../Client/CustomFields/CustomFieldForm.tsx | 20 +- .../Client/CustomFields/CustomFields.tsx | 38 +- .../Client/CustomFields/ListItem.js | 10 +- .../components/Client/CustomFields/index.js | 2 +- frontend/app/components/Client/DebugLog.tsx | 31 +- .../Backend/DatadogForm/DatadogFormModal.tsx | 20 +- .../DynatraceForm/DynatraceFormModal.tsx | 20 +- .../Backend/ElasticForm/ElasticFormModal.tsx | 14 +- .../Backend/SentryForm/SentryFormModal.tsx | 14 +- .../Client/Integrations/FormField.tsx | 6 +- .../Client/Integrations/GithubForm.js | 51 +- .../Integrations/IntegrationFilters.tsx | 16 +- .../Client/Integrations/IntegrationForm.tsx | 27 +- .../Client/Integrations/IntegrationItem.tsx | 28 +- .../Integrations/IntegrationModalCard.tsx | 14 +- .../Client/Integrations/Integrations.tsx | 42 +- .../Client/Integrations/JiraForm/JiraForm.js | 46 +- .../Client/Integrations/JiraForm/index.js | 2 +- .../Integrations/ProfilerDoc/ProfilerDoc.js | 18 +- .../Client/Integrations/ProfilerDoc/index.js | 2 +- .../Integrations/SlackAddForm/SlackAddForm.js | 33 +- .../Client/Integrations/SlackAddForm/index.js | 2 +- .../SlackChannelList/SlackChannelList.js | 76 +- .../Integrations/SlackChannelList/index.js | 2 +- .../Client/Integrations/SlackForm.tsx | 72 +- .../Integrations/Teams/TeamsAddForm.tsx | 30 +- .../Integrations/Teams/TeamsChannelList.tsx | 8 +- .../Client/Integrations/Teams/index.tsx | 64 +- .../Tracker/AssistDoc/AssistDoc.js | 87 +- .../Tracker/AssistDoc/AssistNpm.tsx | 2 +- .../Tracker/AssistDoc/AssistScript.tsx | 8 +- .../Integrations/Tracker/AssistDoc/index.js | 2 +- .../Tracker/GraphQLDoc/GraphQLDoc.js | 82 +- .../Integrations/Tracker/GraphQLDoc/index.js | 2 +- .../Integrations/Tracker/MobxDoc/MobxDoc.js | 82 +- .../Integrations/Tracker/MobxDoc/index.js | 2 +- .../Integrations/Tracker/NgRxDoc/NgRxDoc.js | 80 +- .../Integrations/Tracker/NgRxDoc/index.js | 2 +- .../Tracker/PiniaDoc/PiniaDoc.tsx | 8 +- .../Integrations/Tracker/PiniaDoc/index.js | 2 +- .../Integrations/Tracker/ReduxDoc/ReduxDoc.js | 76 +- .../Integrations/Tracker/ReduxDoc/index.js | 2 +- .../Integrations/Tracker/VueDoc/VueDoc.js | 22 +- .../Integrations/Tracker/VueDoc/index.js | 2 +- .../Tracker/ZustandDoc/ZustandDoc.js | 86 +- .../Integrations/Tracker/ZustandDoc/index.js | 2 +- .../Client/Integrations/apiMethods.ts | 19 +- .../components/Client/Integrations/index.js | 2 +- .../components/Client/Modules/ModuleCard.tsx | 27 +- .../app/components/Client/Modules/Modules.tsx | 18 +- .../app/components/Client/Modules/index.ts | 14 +- .../Client/Notifications/Notifications.tsx | 29 +- .../components/Client/Notifications/index.js | 2 +- .../components/Client/ProfileSettings/Api.js | 12 +- .../Client/ProfileSettings/ChangePassword.tsx | 30 +- .../Client/ProfileSettings/Licenses.js | 19 +- .../Client/ProfileSettings/OptOut.js | 2 +- .../Client/ProfileSettings/ProfileSettings.js | 34 +- .../Client/ProfileSettings/Settings.js | 20 +- .../Client/ProfileSettings/TenantKey.js | 45 +- .../Client/Projects/ProjectCaptureRate.tsx | 20 +- .../Client/Projects/ProjectCodeSnippet.tsx | 65 +- .../Client/Projects/ProjectForm.tsx | 14 +- .../Client/Projects/ProjectList.tsx | 66 +- .../Client/Projects/ProjectTabContent.tsx | 6 +- .../Client/Projects/ProjectTabTracking.tsx | 58 +- .../Client/Projects/ProjectTabs.tsx | 2 +- .../Client/Projects/ProjectTags.tsx | 18 +- .../components/Client/Projects/Projects.tsx | 37 +- .../components/Client/Projects/TagForm.tsx | 16 +- .../app/components/Client/Roles/Roles.tsx | 116 +- .../Roles/components/RoleForm/RoleForm.tsx | 106 +- .../Client/Roles/components/RoleForm/index.ts | 2 +- .../Roles/components/RoleItem/RoleItem.tsx | 74 +- .../Client/Roles/components/RoleItem/index.ts | 2 +- frontend/app/components/Client/Roles/index.ts | 2 +- .../Client/SessionsListingSettings.tsx | 6 +- .../AddProjectButton/AddProjectButton.tsx | 6 +- .../Client/Sites/AddProjectButton/index.ts | 2 +- .../app/components/Client/Sites/GDPRForm.js | 97 +- .../Sites/InstallButton/InstallButton.tsx | 24 +- .../Client/Sites/InstallButton/index.ts | 2 +- .../components/Client/Sites/NewSiteForm.tsx | 31 +- .../components/Client/Sites/ProjectKey.tsx | 14 +- .../Client/Sites/SiteSearch/SiteSearch.tsx | 42 +- .../Client/Sites/SiteSearch/index.ts | 2 +- .../app/components/Client/Sites/Sites.tsx | 136 +- frontend/app/components/Client/TabItem.js | 10 +- .../app/components/Client/Users/UsersView.tsx | 23 +- .../AddUserButton/AddUserButton.tsx | 4 +- .../Users/components/AddUserButton/index.ts | 2 +- .../Users/components/UserForm/UserForm.tsx | 53 +- .../Client/Users/components/UserForm/index.ts | 2 +- .../Users/components/UserList/UserList.tsx | 155 +- .../Client/Users/components/UserList/index.ts | 2 +- .../components/UserListItem/UserListItem.tsx | 22 +- .../Users/components/UserListItem/index.ts | 2 +- .../components/UserSearch/UserSearch.tsx | 48 +- .../Users/components/UserSearch/index.ts | 2 +- .../Client/Webhooks/WebhookForm.tsx | 14 +- .../components/Client/Webhooks/Webhooks.tsx | 28 +- .../app/components/Client/Webhooks/index.js | 2 +- .../app/components/Dashboard/NewDashboard.tsx | 12 +- .../Dashboard/Widgets/CardSessionsByList.tsx | 23 +- .../CustomMetricsWidgets/AreaChart.tsx | 28 +- .../CustomMetricsWidgets/BigNumChart.tsx | 49 +- .../ClickMapCard/ClickMapCard.tsx | 32 +- .../ClickMapCard/index.ts | 2 +- .../CohortCard/CohortCard.tsx | 284 +- .../CustomMetricsWidgets/CohortCard/index.ts | 2 +- .../CustomChartTooltip.tsx | 33 +- .../CustomMetricsWidgets/CustomLegend.tsx | 11 +- .../CustomMetricOverviewChart.tsx | 117 +- .../CustomMetricOverviewChart/index.ts | 2 +- .../CustomMetricPercentage.tsx | 18 +- .../CustomMetricPercentage/index.ts | 2 +- .../CustomMetricPieChart.tsx | 44 +- .../CustomMetricPieChart/index.ts | 2 +- .../CustomMetricTable/CustomMetricTable.tsx | 128 +- .../CustomMetricTable/index.ts | 2 +- .../CustomMetricTableErrors.tsx | 167 +- .../CustomMetricTableErrors/index.ts | 2 +- .../CustomMetricTableSessions.tsx | 23 +- .../CustomMetricTableSessions/index.ts | 2 +- .../InsightsCard/InsightItem.tsx | 19 +- .../InsightsCard/InsightsCard.tsx | 12 +- .../InsightsCard/index.ts | 2 +- .../CustomMetricsWidgets/SessionsBy.tsx | 67 +- .../Widgets/CustomMetricsWidgets/index.ts | 2 +- .../Dashboard/Widgets/ListWithIcons.tsx | 13 +- .../PredefinedWidgets/CPULoad/CPULoad.tsx | 98 +- .../PredefinedWidgets/CPULoad/index.ts | 2 +- .../CallWithErrors/CallWithErrors.tsx | 78 +- .../PredefinedWidgets/CallWithErrors/Chart.js | 6 +- .../CallWithErrors/ImageInfo.js | 12 +- .../CallWithErrors/MethodType.js | 4 +- .../PredefinedWidgets/CallWithErrors/index.ts | 2 +- .../CallsErrors4xx/CallsErrors4xx.tsx | 83 +- .../PredefinedWidgets/CallsErrors4xx/index.ts | 2 +- .../CallsErrors5xx/CallsErrors5xx.tsx | 84 +- .../PredefinedWidgets/CallsErrors5xx/index.ts | 2 +- .../PredefinedWidgets/Crashes/Crashes.tsx | 98 +- .../PredefinedWidgets/Crashes/index.ts | 2 +- .../DomBuildingTime/DomBuildingTime.tsx | 123 +- .../DomBuildingTime/index.ts | 2 +- .../ErrorsByOrigin/ErrorsByOrigin.tsx | 113 +- .../PredefinedWidgets/ErrorsByOrigin/index.ts | 2 +- .../ErrorsByType/ErrorsByType.tsx | 88 +- .../PredefinedWidgets/ErrorsByType/index.ts | 2 +- .../PredefinedWidgets/ErrorsPerDomain/Bar.tsx | 14 +- .../ErrorsPerDomain/ErrorsPerDomain.tsx | 14 +- .../ErrorsPerDomain/index.ts | 2 +- .../Widgets/PredefinedWidgets/FPS/FPS.tsx | 106 +- .../Widgets/PredefinedWidgets/FPS/index.ts | 2 +- .../MemoryConsumption/MemoryConsumption.tsx | 112 +- .../MemoryConsumption/index.ts | 2 +- .../ResponseTime/ResponseTime.tsx | 124 +- .../PredefinedWidgets/ResponseTime/index.ts | 2 +- .../ResponseTimeDistribution.tsx | 175 +- .../ResponseTimeDistribution/index.ts | 2 +- .../SessionsAffectedByJSErrors.tsx | 82 +- .../SessionsAffectedByJSErrors/index.ts | 2 +- .../SessionsImpactedBySlowRequests.tsx | 96 +- .../SessionsImpactedBySlowRequests/index.ts | 2 +- .../SessionsPerBrowser/Bar.js | 47 +- .../SessionsPerBrowser/SessionsPerBrowser.tsx | 28 +- .../SessionsPerBrowser/index.ts | 2 +- .../PredefinedWidgets/SlowestDomains/Bar.tsx | 14 +- .../SlowestDomains/SlowestDomains.tsx | 16 +- .../PredefinedWidgets/SlowestDomains/index.ts | 2 +- .../SpeedIndexByLocation/Scale.js | 6 +- .../SpeedIndexByLocation.tsx | 36 +- .../SpeedIndexByLocation/index.ts | 2 +- .../TimeToRender/TimeToRender.tsx | 133 +- .../PredefinedWidgets/TimeToRender/index.ts | 2 +- .../Dashboard/Widgets/common/AvgLabel.js | 11 +- .../Dashboard/Widgets/common/CountBadge.js | 40 +- .../Dashboard/Widgets/common/CustomTooltip.js | 12 +- .../Dashboard/Widgets/common/Divider.js | 23 +- .../Dashboard/Widgets/common/SessionLine.js | 57 +- .../Dashboard/Widgets/common/Styles.js | 162 +- .../Dashboard/Widgets/common/Table.js | 43 +- .../Dashboard/Widgets/common/Title.js | 14 +- .../Dashboard/Widgets/common/domain.js | 13 +- .../Dashboard/Widgets/common/index.js | 2 +- .../components/AddCardModal/AddCardModal.tsx | 2 +- .../AddCardSection/AddCardSection.tsx | 74 +- .../components/AddCardSelectionModal.tsx | 8 +- .../components/AddToDashboardButton.tsx | 6 +- .../Alerts/AlertForm/BottomButtons.tsx | 46 +- .../components/Alerts/AlertForm/Condition.tsx | 22 +- .../Alerts/AlertForm/NotifyHooks.tsx | 2 +- .../components/Alerts/AlertListItem.tsx | 78 +- .../components/Alerts/AlertsList.tsx | 50 +- .../components/Alerts/AlertsSearch.tsx | 6 +- .../components/Alerts/AlertsView.tsx | 70 +- .../Alerts/DropdownChips/DropdownChips.js | 108 +- .../components/Alerts/DropdownChips/index.js | 2 +- .../Dashboard/components/Alerts/NewAlert.tsx | 134 +- .../Dashboard/components/Alerts/index.tsx | 2 +- .../components/CardIssues/CardIssueItem.tsx | 2 +- .../components/CardIssues/CardIssues.tsx | 67 +- .../Dashboard/components/CardIssues/index.ts | 2 +- .../components/CardUserList/CardUserItem.tsx | 41 +- .../components/CardUserList/CardUserList.tsx | 125 +- .../SessionsModal/SessionsModal.tsx | 171 +- .../CardUserList/SessionsModal/index.ts | 2 +- .../ClickMapRagePicker/ClickMapRagePicker.tsx | 71 +- .../components/ClickMapRagePicker/index.ts | 2 +- .../Dashboard/components/CreateCardButton.tsx | 51 +- .../components/CreateDashboardButton.tsx | 22 +- .../DashbaordListModal/DashbaordListModal.tsx | 64 +- .../components/DashbaordListModal/index.ts | 2 +- .../DashboardEditModal/DashboardEditModal.tsx | 150 +- .../components/DashboardEditModal/index.ts | 2 +- .../DashboardForm/DashboardForm.tsx | 80 +- .../components/DashboardForm/index.ts | 2 +- .../DashboardHeader/DashboardHeader.tsx | 41 +- .../DashboardList/DashboardList.tsx | 93 +- .../DashboardList/DashboardSearch.tsx | 5 +- .../DashboardList/DashboardsView.tsx | 14 +- .../components/DashboardList/Header.tsx | 30 +- .../NewDashModal/CardsLibrary.tsx | 14 +- .../DashboardList/NewDashModal/CreateCard.tsx | 174 +- .../NewDashModal/ExampleCards.tsx | 177 +- .../NewDashModal/Examples/AreaChartCard.tsx | 126 +- .../NewDashModal/Examples/BarChart.tsx | 10 +- .../NewDashModal/Examples/Bars.tsx | 88 +- .../Examples/CallsWithErrorsExample.tsx | 18 +- .../NewDashModal/Examples/Count.tsx | 60 +- .../NewDashModal/Examples/ExCard.tsx | 44 +- .../NewDashModal/Examples/Funnel.tsx | 6 +- .../NewDashModal/Examples/HeatmapsExample.tsx | 11 +- .../NewDashModal/Examples/InsightsExample.tsx | 87 +- .../PageResponseTimeDistributionExample.tsx | 5 +- .../NewDashModal/Examples/Path.tsx | 88 +- .../NewDashModal/Examples/PerfBreakdown.tsx | 42 +- .../Examples/SessionsBy/ByBrowser.tsx | 10 +- .../Examples/SessionsBy/ByCountry.tsx | 10 +- .../Examples/SessionsBy/ByFecth.tsx | 10 +- .../Examples/SessionsBy/ByIssues.tsx | 70 +- .../Examples/SessionsBy/ByRferrer.tsx | 10 +- .../Examples/SessionsBy/BySystem.tsx | 12 +- .../Examples/SessionsBy/ByUrl.tsx | 16 +- .../Examples/SessionsBy/ByUser.tsx | 84 +- .../Examples/SessionsBy/Component.tsx | 12 +- .../Examples/SessionsBy/SlowestDomains.tsx | 14 +- .../Examples/SessionsByErrors.tsx | 10 +- .../Examples/SessionsByIssues.tsx | 10 +- .../Examples/SessionsPerBrowserExample.tsx | 16 +- .../NewDashModal/Examples/SlowestDomain.tsx | 14 +- .../Examples/SpeedIndexByLocationExample.tsx | 70 +- .../NewDashModal/Examples/TableOfErrors.tsx | 413 +- .../Examples/Tabs/CoreWebVitals.tsx | 14 +- .../Examples/Tabs/PerformanceMonitoring.tsx | 14 +- .../Examples/Tabs/ProductAnalytics.tsx | 12 +- .../Examples/Tabs/WebAnalytics.tsx | 14 +- .../NewDashModal/Examples/Trend.tsx | 52 +- .../NewDashModal/Examples/WebVital.tsx | 86 +- .../NewDashModal/NewDashboardModal.tsx | 83 +- .../DashboardList/NewDashModal/Option.tsx | 12 +- .../DashboardList/NewDashModal/SelectCard.tsx | 66 +- .../DashboardList/NewDashModal/index.ts | 2 +- .../DashboardMetricSelection.tsx | 252 +- .../DashboardMetricSelection/index.ts | 2 +- .../DashboardModal/DashboardModal.tsx | 130 +- .../components/DashboardModal/index.ts | 2 +- .../DashboardOptions/DashboardOptions.tsx | 12 +- .../components/DashboardOptions/index.ts | 2 +- .../DashboardRouter/DashboardRouter.tsx | 2 +- .../components/DashboardRouter/index.ts | 2 +- .../DashboardSideMenu/DashboardSideMenu.tsx | 4 +- .../components/DashboardSideMenu/index.ts | 2 +- .../components/DashboardView/AiQuery.tsx | 32 +- .../DashboardView/DashboardView.tsx | 176 +- .../components/DashboardView/index.ts | 2 +- .../DashboardWidgetGrid/AddMetric.tsx | 8 +- .../AddMetricContainer.tsx | 160 +- .../AddPredefinedMetric.tsx | 16 +- .../DashboardWidgetGrid.tsx | 29 +- .../components/DashboardWidgetGrid/index.ts | 2 +- .../ErrorDetailsModal/ErrorDetailsModal.tsx | 16 +- .../Errors/ErrorDetailsModal/index.ts | 2 +- .../Errors/ErrorLabel/ErrorLabel.tsx | 20 +- .../components/Errors/ErrorLabel/index.ts | 2 +- .../Errors/ErrorListItem/ErrorListItem.tsx | 132 +- .../components/Errors/ErrorListItem/index.ts | 2 +- .../components/Errors/ErrorName/ErrorName.tsx | 20 +- .../components/Errors/ErrorName/index.ts | 2 +- .../components/FilterSeries/AddStepButton.tsx | 44 +- .../FilterSeries/ExcludeFilters.tsx | 4 +- .../components/FilterSeries/FilterSeries.tsx | 75 +- .../FilterSeries/SeriesName/SeriesName.tsx | 8 +- .../FilterSeries/SeriesName/index.ts | 2 +- .../components/FilterSeries/index.ts | 2 +- .../FunnelIssueDetails/FunnelIssueDetails.tsx | 93 +- .../Funnels/FunnelIssueDetails/index.ts | 2 +- .../FunnelIssueGraph/FunnelIssueGraph.tsx | 12 +- .../Funnels/FunnelIssueGraph/index.ts | 2 +- .../FunnelIssueModal/FunnelIssueModal.tsx | 20 +- .../Funnels/FunnelIssueModal/index.ts | 2 +- .../Funnels/FunnelIssues/FunnelIssues.tsx | 123 +- .../FunnelIssuesDropdown.tsx | 193 +- .../Funnels/FunnelIssuesDropdown/index.ts | 2 +- .../FunnelIssuesList/FunnelIssuesList.tsx | 70 +- .../Funnels/FunnelIssuesList/index.ts | 2 +- .../FunnelIssuesListItem.tsx | 143 +- .../Funnels/FunnelIssuesListItem/index.ts | 2 +- .../FunnelIssuesSelectedFilters.tsx | 42 +- .../FunnelIssuesSelectedFilters/index.ts | 2 +- .../FunnelIssuesSort/FunnelIssuesSort.tsx | 54 +- .../Funnels/FunnelIssuesSort/index.ts | 2 +- .../MetricListItem/MetricListItem.tsx | 23 +- .../components/MetricListItem/index.ts | 2 +- .../MetricTypeItem/MetricTypeItem.tsx | 18 +- .../MetricTypeList/MetricTypeList.tsx | 38 +- .../components/MetricTypeSelector.tsx | 27 +- .../MetricViewHeader/MetricViewHeader.tsx | 12 +- .../components/MetricsGrid/MetricsGrid.tsx | 12 +- .../Dashboard/components/MetricsGrid/index.ts | 2 +- .../MetricsLibraryModal/FooterContent.tsx | 72 +- .../MetricsLibraryModal.tsx | 14 +- .../components/MetricsList/GridView.tsx | 11 +- .../components/MetricsList/ListView.tsx | 98 +- .../components/MetricsList/MetricsList.tsx | 80 +- .../Dashboard/components/MetricsList/index.ts | 2 +- .../MetricsSearch/MetricsSearch.tsx | 4 +- .../components/MetricsSearch/index.ts | 2 +- .../components/MetricsView/MetricsView.tsx | 6 +- .../Dashboard/components/MetricsView/index.ts | 2 +- .../SessionsModal/SessionsModal.tsx | 40 +- .../components/SessionsModal/index.ts | 2 +- .../components/WidgetChart/LongLoader.tsx | 14 +- .../components/WidgetChart/WidgetChart.tsx | 117 +- .../Dashboard/components/WidgetChart/index.ts | 2 +- .../WidgetDatatable/WidgetDatatable.tsx | 37 +- .../WidgetDateRange/RangeGranularity.tsx | 30 +- .../WidgetDateRange/WidgetDateRange.tsx | 66 +- .../components/WidgetForm/CardBuilder.tsx | 561 ++- .../components/WidgetForm/WidgetForm.tsx | 483 +- .../components/WidgetForm/WidgetFormNew.tsx | 266 +- .../MetricSubtypeDropdown.tsx | 20 +- .../MetricTypeDropdown/MetricTypeDropdown.tsx | 30 +- .../Dashboard/components/WidgetForm/index.ts | 2 +- .../components/WidgetForm/renderMap.ts | 56 +- .../components/WidgetName/WidgetName.tsx | 8 +- .../Dashboard/components/WidgetName/index.ts | 2 +- .../Dashboard/components/WidgetOptions.tsx | 32 +- .../WidgetPredefinedChart.tsx | 60 +- .../components/WidgetPredefinedChart/index.ts | 2 +- .../WidgetPreview/WidgetPreview.tsx | 52 +- .../components/WidgetPreview/index.ts | 2 +- .../WidgetSessions/WidgetSessions.tsx | 123 +- .../components/WidgetSessions/index.ts | 2 +- .../WidgetSubDetailsView.tsx | 60 +- .../components/WidgetSubDetailsView/index.ts | 2 +- .../components/WidgetView/CardViewMenu.tsx | 16 +- .../components/WidgetView/WidgetView.tsx | 58 +- .../WidgetView/WidgetViewHeader.tsx | 48 +- .../Dashboard/components/WidgetView/index.ts | 2 +- .../components/WidgetWrapper/AlertButton.tsx | 42 +- .../components/WidgetWrapper/CardMenu.tsx | 84 +- .../WidgetWrapper/TemplateOverlay.tsx | 6 +- .../WidgetWrapper/WidgetWrapper.tsx | 31 +- .../WidgetWrapper/WidgetWrapperNew.tsx | 72 +- .../components/WidgetWrapper/index.ts | 2 +- .../app/components/Errors/Error/DateAgo.js | 20 +- .../Errors/Error/DistributionBar.js | 6 +- .../app/components/Errors/Error/ErrorInfo.js | 6 +- .../app/components/Errors/Error/IconCard.js | 35 +- .../components/Errors/Error/MainSection.js | 15 +- .../app/components/Errors/Error/SessionBar.js | 104 +- .../components/Errors/Error/SideSection.js | 17 +- frontend/app/components/Errors/Error/Trend.js | 104 +- frontend/app/components/Errors/ui/Divider.js | 10 +- .../app/components/Errors/ui/ErrorName.js | 20 +- frontend/app/components/Errors/ui/Label.js | 18 +- .../components/FFlags/FFlagItem/FFlagItem.tsx | 25 +- .../app/components/FFlags/FFlagItem/index.ts | 2 +- frontend/app/components/FFlags/FFlagsList.tsx | 41 +- .../components/FFlags/FFlagsListHeader.tsx | 16 +- .../app/components/FFlags/FFlagsSearch.tsx | 8 +- .../components/FFlags/FlagView/FlagView.tsx | 60 +- .../FFlags/NewFFlag/Description.tsx | 10 +- .../app/components/FFlags/NewFFlag/Header.tsx | 8 +- .../components/FFlags/NewFFlag/Helpers.tsx | 24 +- .../app/components/FFlags/NewFFlag/HowTo.tsx | 12 +- .../FFlags/NewFFlag/Multivariant.tsx | 198 +- .../components/FFlags/NewFFlag/NewFFlag.tsx | 141 +- .../app/components/FFlags/NewFFlag/index.ts | 2 +- frontend/app/components/FFlags/index.ts | 2 +- .../ForgotPassword/CreatePassword.tsx | 91 +- .../ForgotPassword/ForgotPassword.tsx | 4 +- .../components/ForgotPassword/ReCaptcha.js | 6 +- .../ForgotPassword/ResetPasswordRequest.tsx | 40 +- .../FunnelGraphSmall/FunnelGraphSmall.js | 16 +- .../Funnels/FunnelGraphSmall/index.js | 2 +- .../Funnels/FunnelItem/FunnelItem.tsx | 26 +- .../components/Funnels/FunnelItem/index.js | 2 +- .../Funnels/FunnelMenuItem/FunnelMenuItem.js | 8 +- .../Funnels/FunnelMenuItem/index.js | 2 +- .../Funnels/FunnelOverview/FunnelOverview.js | 39 +- .../Funnels/FunnelOverview/index.js | 2 +- .../Funnels/FunnelSearch/FunnelSearch.tsx | 48 +- .../components/Funnels/FunnelSearch/index.ts | 2 +- .../FunnelSessionsHeader.js | 14 +- .../Funnels/FunnelSessionsHeader/index.js | 2 +- .../Funnels/FunnelWidget/FunnelBar.tsx | 48 +- .../Funnels/FunnelWidget/FunnelStepText.tsx | 34 +- .../Funnels/FunnelWidget/FunnelTable.tsx | 76 +- .../Funnels/FunnelWidget/FunnelWidget.tsx | 113 +- .../components/Funnels/FunnelWidget/index.ts | 2 +- .../Funnels/IssueItem/IssueGraph.js | 12 +- .../components/Funnels/IssueItem/IssueItem.js | 41 +- .../app/components/Funnels/IssueItem/index.js | 2 +- frontend/app/components/Header/AlertItem.js | 20 +- .../DefaultMenuView/DefaultMenuView.tsx | 27 +- .../Header/DefaultMenuView/index.ts | 2 +- .../components/Header/Discover/FeatureItem.js | 21 +- .../app/components/Header/Discover/index.js | 2 +- .../HealthStatus/HealthModal/Footer.tsx | 25 +- .../HealthStatus/HealthModal/HealthModal.tsx | 66 +- .../Header/HealthStatus/HealthStatus.tsx | 15 +- .../Header/HealthStatus/HealthWidget.tsx | 64 +- .../Header/HealthStatus/ServiceCategory.tsx | 9 +- .../SubserviceHealth/SubserviceHealth.tsx | 4 +- .../components/Header/HealthStatus/const.ts | 4 +- .../Header/HealthStatus/getHealth.ts | 23 +- .../components/Header/HealthStatus/index.ts | 2 +- .../Header/NewProjectButton/index.ts | 2 +- .../app/components/Header/NotificationItem.js | 18 +- .../Header/OnboardingExplore/FeatureItem.js | 12 +- .../Header/OnboardingExplore/index.js | 2 +- .../Header/PreferencesView/index.ts | 2 +- .../Header/SettingsMenu/SettingsMenu.tsx | 31 +- .../components/Header/SettingsMenu/index.ts | 2 +- .../components/Header/UserMenu/UserMenu.tsx | 20 +- .../app/components/Header/UserMenu/index.ts | 2 +- .../app/components/Highlights/EditHlModal.tsx | 15 +- .../components/Highlights/HighlightClip.tsx | 44 +- .../components/Highlights/HighlightPlayer.tsx | 16 +- .../components/Highlights/HighlightsList.tsx | 53 +- .../Highlights/HighlightsListHeader.tsx | 32 +- .../LanguageSwitcher/LanguageSwitcher.tsx | 68 + .../app/components/LanguageSwitcher/index.ts | 1 + frontend/app/components/Login/Login.tsx | 68 +- frontend/app/components/Modal/Modal.tsx | 30 +- .../app/components/Modal/ModalOverlay.tsx | 18 +- frontend/app/components/Modal/index.tsx | 5 +- frontend/app/components/Modal/withModal.tsx | 9 +- frontend/app/components/ModalContext.tsx | 84 +- .../app/components/Onboarding/Onboarding.tsx | 27 +- .../components/CircleNumber/CircleNumber.js | 8 +- .../components/CircleNumber/index.js | 2 +- .../IdentifyUsersTab/IdentifyUsersTab.tsx | 65 +- .../components/IdentifyUsersTab/index.ts | 2 +- .../InstallOpenReplayTab.tsx | 37 +- .../components/InstallOpenReplayTab/index.ts | 2 +- .../IntegrationsTab/IntegrationsTab.tsx | 13 +- .../components/IntegrationsTab/index.ts | 2 +- .../ManageUsersTab/ManageUsersTab.tsx | 15 +- .../components/ManageUsersTab/index.ts | 2 +- .../components/MetadataList/MetadataList.js | 13 +- .../components/MetadataList/MetadataList.tsx | 12 +- .../components/MetadataList/index.js | 2 +- .../OnboardingMenu/OnboardingMenu.js | 122 +- .../components/OnboardingMenu/index.js | 2 +- .../OnboardingNavButton.js | 39 +- .../components/OnboardingNavButton/index.js | 2 +- .../OnboardingTabs/CopyButton/CopyButton.js | 13 +- .../OnboardingTabs/CopyButton/index.js | 2 +- .../InstallDocs/AndroidInstallDocs.tsx | 46 +- .../OnboardingTabs/InstallDocs/InstallDocs.js | 56 +- .../InstallDocs/MobileInstallDocs.tsx | 37 +- .../OnboardingTabs/InstallDocs/index.js | 2 +- .../OnboardingTabs/OnboardingMobileTabs.tsx | 12 +- .../OnboardingTabs/OnboardingTabs.tsx | 11 +- .../ProjectCodeSnippet/ProjectCodeSnippet.js | 40 +- .../ProjectCodeSnippet/index.js | 2 +- .../OnboardingTabs/SegmentTab/SegmentTab.js | 17 +- .../OnboardingTabs/SegmentTab/index.js | 2 +- .../components/OnboardingTabs/index.js | 2 +- .../ProjectFormButton/ProjectFormButton.js | 24 +- .../components/ProjectFormButton/index.js | 2 +- .../Onboarding/components/SideMenu.tsx | 32 +- .../Onboarding/components/withOnboarding.tsx | 7 +- frontend/app/components/Onboarding/index.js | 2 +- frontend/app/components/Overview/Overview.tsx | 18 +- frontend/app/components/Overview/index.ts | 2 +- .../app/components/ScopeForm/ScopeForm.tsx | 51 +- frontend/app/components/ScopeForm/index.ts | 2 +- .../app/components/Session/ClipsPlayer.tsx | 31 +- .../app/components/Session/LivePlayer.tsx | 25 +- .../app/components/Session/LiveSession.js | 87 +- .../components/Session/MobileClipsPlayer.tsx | 24 +- .../app/components/Session/MobilePlayer.tsx | 27 +- .../Player/ClickMapRenderer/Renderer.tsx | 4 +- .../Player/ClickMapRenderer/ThinPlayer.tsx | 48 +- .../ClickMapRenderer/ThinPlayerContent.tsx | 24 +- .../Session/Player/ClickMapRenderer/index.ts | 2 +- .../Player/ClipPlayer/AutoPlayTimer.tsx | 98 +- .../Player/ClipPlayer/AutoplayToggle.tsx | 50 +- .../Player/ClipPlayer/ClipFeedback.tsx | 146 +- .../Player/ClipPlayer/ClipPlayerContent.tsx | 6 +- .../Player/ClipPlayer/ClipPlayerControls.tsx | 12 +- .../Player/ClipPlayer/ClipPlayerHeader.tsx | 20 +- .../Player/ClipPlayer/ClipPlayerOverlay.tsx | 46 +- .../ClipPlayer/MobileClipPlayerContent.tsx | 20 +- .../Player/ClipPlayer/QueueControls.tsx | 128 +- .../Session/Player/ClipPlayer/TimeTracker.tsx | 30 +- .../Session/Player/ClipPlayer/Timeline.tsx | 278 +- .../Player/ClipPlayer/TimelineTracker.tsx | 28 +- .../Session/Player/ClipPlayer/UserCard.tsx | 117 +- .../Player/LivePlayer/AssistDuration.tsx | 24 +- .../AssistSessionsTabs/AssistSessionsTabs.tsx | 28 +- .../LivePlayer/AssistSessionsTabs/index.tsx | 2 +- .../Player/LivePlayer/LiveControls.tsx | 58 +- .../Player/LivePlayer/LivePlayerBlock.tsx | 7 +- .../LivePlayer/LivePlayerBlockHeader.tsx | 22 +- .../Player/LivePlayer/LivePlayerInst.tsx | 15 +- .../Player/LivePlayer/LivePlayerSubHeader.tsx | 13 +- .../Player/LivePlayer/LiveTag/LiveTag.tsx | 12 +- .../Player/LivePlayer/LiveTag/index.js | 2 +- .../Player/LivePlayer/Overlay/LiveOverlay.tsx | 31 +- .../LivePlayer/Overlay/LiveStatusText.tsx | 37 +- .../Player/LivePlayer/Overlay/index.ts | 2 +- .../Session/Player/LivePlayer/Timeline.tsx | 31 +- .../Player/MobilePlayer/MobileControls.tsx | 80 +- .../Player/MobilePlayer/MobileOverlay.tsx | 24 +- .../MobilePlayer/MobilePlayerHeader.tsx | 10 +- .../MobilePlayer/MobilePlayerSubheader.tsx | 69 +- .../Player/MobilePlayer/PerfWarnings.tsx | 37 +- .../Player/MobilePlayer/PlayerBlock.tsx | 16 +- .../Player/MobilePlayer/PlayerContent.tsx | 16 +- .../Player/MobilePlayer/PlayerInst.tsx | 46 +- .../Player/MobilePlayer/ReplayWindow.tsx | 46 +- .../Session/Player/PlayerErrorBoundary.tsx | 7 +- .../Player/ReplayPlayer/AudioPlayer.tsx | 88 +- .../EventsBlock/EventSearch/EventSearch.js | 46 +- .../EventsBlock/EventSearch/index.js | 2 +- .../EventsBlock/Metadata/Metadata.js | 25 +- .../EventsBlock/Metadata/MetadataItem.js | 128 +- .../EventsBlock/Metadata/SessionLine.js | 58 +- .../EventsBlock/Metadata/SessionList.js | 17 +- .../EventsBlock/Metadata/index.js | 2 +- .../EventsBlock/UserCard/UserCard.js | 272 +- .../EventsBlock/UserCard/index.js | 2 +- .../Player/ReplayPlayer/PlayerBlock.tsx | 4 +- .../Player/ReplayPlayer/PlayerBlockHeader.tsx | 65 +- .../Player/ReplayPlayer/PlayerContent.tsx | 16 +- .../Player/ReplayPlayer/PlayerInst.tsx | 51 +- .../ReplayPlayer/SummaryBlock/index.tsx | 78 +- .../Player/ReplayPlayer/useShortcuts.ts | 117 +- .../BackendLogs/BackendLogsPanel.tsx | 43 +- .../BackendLogs/LogsButton.tsx | 10 +- .../BackendLogs/StatusMessages.tsx | 39 +- .../SharedComponents/BackendLogs/Table.tsx | 46 +- .../SharedComponents/BackendLogs/utils.ts | 44 +- .../Player/SharedComponents/SessionTabs.tsx | 70 +- .../Session/Player/SharedComponents/Tab.tsx | 14 +- .../Session/Player/TagWatch/SaveModal.tsx | 32 +- .../Session/Player/TagWatch/TagWatch.tsx | 15 +- .../Session/Player/TagWatch/index.ts | 2 +- .../app/components/Session/RightBlock.tsx | 10 +- frontend/app/components/Session/Session.tsx | 17 +- frontend/app/components/Session/Tabs/Tabs.tsx | 28 +- frontend/app/components/Session/Tabs/index.ts | 2 +- frontend/app/components/Session/WebPlayer.tsx | 38 +- .../app/components/Session_/Autoscroll.tsx | 43 +- .../Session_/BottomBlock/BottomBlock.tsx | 14 +- .../Session_/BottomBlock/Content.js | 14 +- .../components/Session_/BottomBlock/Header.js | 18 +- .../Session_/BottomBlock/InfoLine.js | 32 +- .../components/Session_/BottomBlock/index.ts | 2 +- .../Console/ConsoleRow/ConsoleRow.tsx | 6 +- .../components/Session_/EventsBlock/Event.tsx | 85 +- .../Session_/EventsBlock/EventGroupWrapper.js | 35 +- .../EventsBlock/EventSearch/EventSearch.js | 28 +- .../Session_/EventsBlock/EventSearch/index.js | 2 +- .../Session_/EventsBlock/EventsBlock.tsx | 67 +- .../Session_/EventsBlock/LoadInfo.js | 91 +- .../Session_/EventsBlock/Metadata/Metadata.js | 25 +- .../EventsBlock/Metadata/MetadataItem.js | 128 +- .../EventsBlock/Metadata/SessionLine.js | 58 +- .../EventsBlock/Metadata/SessionList.js | 16 +- .../Session_/EventsBlock/Metadata/index.js | 2 +- .../Session_/EventsBlock/NoteEvent.tsx | 18 +- .../Session_/EventsBlock/UserCard/UserCard.js | 184 +- .../Session_/EventsBlock/UserCard/index.js | 2 +- .../Session_/EventsBlock/UxtEvent.tsx | 27 +- .../components/Session_/EventsBlock/index.js | 2 +- .../Session_/Exceptions/Exceptions.tsx | 84 +- .../components/Session_/Fetch/FetchDetails.js | 267 +- .../Fetch/components/Headers/Headers.tsx | 30 +- .../Fetch/components/Headers/index.ts | 2 +- .../components/Session_/GraphQL/GQLDetails.js | 22 +- .../components/Session_/GraphQL/GraphQL.tsx | 43 +- .../app/components/Session_/GraphQL/index.js | 2 +- .../Session_/Highlight/HighlightButton.tsx | 15 +- .../Session_/Highlight/HighlightPanel.tsx | 116 +- .../Session_/Inspector/AttrView.tsx | 122 +- .../Session_/Inspector/ElementView.tsx | 283 +- .../Session_/Inspector/InlineInput.tsx | 64 +- .../Session_/Inspector/TextView.tsx | 16 +- .../components/Session_/Inspector/index.js | 4 +- .../components/Session_/Issues/IssueForm.tsx | 26 +- .../app/components/Session_/Issues/Issues.js | 4 +- .../Session_/Issues/IssuesModal.tsx | 12 +- .../app/components/Session_/Issues/index.js | 2 +- .../Session_/Multiview/EmptyTile.tsx | 2 +- .../Session_/Multiview/Multiview.tsx | 14 +- .../Session_/Multiview/SessionTileFooter.tsx | 4 +- .../Session_/OverviewPanel/OverviewPanel.tsx | 372 +- .../components/EventRow/EventRow.tsx | 68 +- .../components/EventRow/index.ts | 2 +- .../FeatureSelection/FeatureSelection.tsx | 66 +- .../OverviewPanelContainer.tsx | 5 +- .../OverviewPanelContainer/index.ts | 2 +- .../PerformanceGraph/PerformanceGraph.tsx | 48 +- .../components/PerformanceGraph/index.ts | 2 +- .../StackEventModal/StackEventModal.tsx | 42 +- .../components/JsonViewer/JsonViewer.js | 25 +- .../components/JsonViewer/index.ts | 2 +- .../components/Sentry/Sentry.js | 131 +- .../components/Sentry/index.ts | 2 +- .../components/TimelinePointer/Dots.tsx | 72 +- .../TimelinePointer/TimelinePointer.tsx | 55 +- .../components/TimelinePointer/index.ts | 2 +- .../TimelineScale/TimelineScale.tsx | 59 +- .../components/TimelineScale/index.ts | 2 +- .../components/VerticalLine/VerticalLine.tsx | 6 +- .../components/VerticalLine/index.ts | 2 +- .../VerticalPointerLine.tsx | 14 +- .../components/VerticalPointerLine/index.ts | 2 +- .../Session_/OverviewPanel/fakeData.ts | 8 +- .../Session_/OverviewPanel/index.ts | 2 +- .../PageInsightsPanel/PageInsightsPanel.tsx | 147 +- .../components/SelectorCard/SelectorCard.tsx | 53 +- .../components/SelectorCard/index.js | 2 +- .../SelectorsList/SelectorsList.tsx | 18 +- .../components/SelectorsList/index.js | 2 +- .../Session_/PageInsightsPanel/index.js | 2 +- .../Session_/Performance/Performance.tsx | 433 +- .../AssistSessionsModal.tsx | 25 +- .../Controls/AssistSessionsModal/index.tsx | 2 +- .../AssistSessionsTabs/AssistSessionsTabs.tsx | 24 +- .../Controls/AssistSessionsTabs/index.tsx | 2 +- .../Player/Controls/ControlButton.tsx | 38 +- .../Session_/Player/Controls/Controls.tsx | 91 +- .../Session_/Player/Controls/EventsList.tsx | 26 +- .../Session_/Player/Controls/NotesList.tsx | 23 +- .../Player/Controls/SkipIntervalsList.tsx | 2 +- .../Session_/Player/Controls/Time.tsx | 34 +- .../Session_/Player/Controls/TimeTracker.js | 23 +- .../Session_/Player/Controls/Timeline.tsx | 48 +- .../Player/Controls/components/Circle.tsx | 16 +- .../components/ControlsComponents.tsx | 57 +- .../Controls/components/CustomDragLayer.tsx | 67 +- .../Controls/components/DraggableCircle.tsx | 114 +- .../Controls/components/KeyboardHelp.tsx | 86 +- .../Controls/components/PlayerControls.tsx | 10 +- .../Controls/components/PlayingTime.tsx | 38 +- .../Player/Controls/components/ReadNote.tsx | 39 +- .../Controls/components/TimeTooltip.tsx | 18 +- .../components/TimelineZoomButton.tsx | 22 +- .../Controls/components/TooltipContainer.tsx | 6 +- .../Controls/components/ZoomDragLayer.tsx | 79 +- .../Player/Controls/getTimelinePosition.ts | 1 - .../Session_/Player/Controls/index.js | 2 +- .../components/Session_/Player/Overlay.tsx | 34 +- .../Session_/Player/Overlay/AutoplayTimer.tsx | 18 +- .../Player/Overlay/ElementsMarker.tsx | 26 +- .../Player/Overlay/ElementsMarker/Marker.tsx | 18 +- .../Player/Overlay/LiveStatusText.tsx | 39 +- .../Session_/Player/Overlay/Loader.tsx | 4 +- .../Session_/Player/Overlay/PlayIconLayer.tsx | 4 +- .../Session_/QueueControls/QueueControls.tsx | 22 +- .../Session_/QueueControls/index.ts | 2 +- .../ScreenRecorder/ScreenRecorder.tsx | 33 +- .../SessionInfoItem/SessionInfoItem.tsx | 36 +- .../Session_/SessionInfoItem/index.ts | 2 +- .../StackEvents/UserEvent/JsonViewer.js | 5 +- .../Session_/StackEvents/UserEvent/Sentry.js | 131 +- .../StackEvents/UserEvent/UserEvent.js | 2 +- .../Session_/StackEvents/UserEvent/index.js | 2 +- .../components/Session_/Storage/DiffRow.tsx | 21 +- .../Session_/Storage/ReduxViewer.tsx | 44 +- .../components/Session_/Storage/Storage.tsx | 46 +- .../app/components/Session_/Storage/index.js | 2 +- .../app/components/Session_/Subheader.tsx | 81 +- .../Session_/UnitStepsModal/index.tsx | 56 +- .../app/components/Session_/WarnBadge.tsx | 49 +- frontend/app/components/Signup/Signup.tsx | 18 +- .../Signup/SignupForm/SignupForm.tsx | 50 +- .../app/components/Signup/SignupForm/index.ts | 2 +- frontend/app/components/Signup/index.ts | 2 +- .../Spots/SpotPlayer/SpotPlayer.tsx | 43 +- .../SpotPlayer/components/AccessError.tsx | 58 +- .../SpotPlayer/components/AccessModal.tsx | 94 +- .../SpotPlayer/components/CommentsSection.tsx | 48 +- .../components/Panels/SpotConsole.tsx | 20 +- .../components/Panels/SpotNetwork.tsx | 32 +- .../SpotPlayer/components/SpotActivity.tsx | 12 +- .../SpotPlayer/components/SpotLocation.tsx | 14 +- .../components/SpotPlayerControls.tsx | 20 +- .../components/SpotPlayerHeader.tsx | 72 +- .../SpotPlayer/components/SpotSideBar.tsx | 12 +- .../SpotPlayer/components/SpotTimeTracker.tsx | 10 +- .../SpotPlayer/components/SpotTimeline.tsx | 10 +- .../components/SpotVideoContainer.tsx | 53 +- .../Spots/SpotPlayer/components/Vjs.tsx | 4 +- .../app/components/Spots/SpotPlayer/consts.ts | 2 +- .../app/components/Spots/SpotPlayer/index.tsx | 2 +- .../Spots/SpotPlayer/spotPlayerStore.ts | 52 +- .../Spots/SpotsList/EditItemModal.tsx | 16 +- .../components/Spots/SpotsList/EmptyPage.tsx | 10 +- .../components/Spots/SpotsList/InstallCTA.tsx | 26 +- .../Spots/SpotsList/SpotListItem.tsx | 58 +- .../Spots/SpotsList/SpotsListHeader.tsx | 18 +- .../app/components/Spots/SpotsList/index.tsx | 56 +- .../UsabilityTesting/LiveTestsModal.tsx | 24 +- .../UsabilityTesting/ParticipantOverview.tsx | 6 +- .../UsabilityTesting/ResponsesOverview.tsx | 76 +- .../components/UsabilityTesting/SidePanel.tsx | 29 +- .../UsabilityTesting/StepsModal.tsx | 39 +- .../components/UsabilityTesting/TestEdit.tsx | 202 +- .../UsabilityTesting/TestOverview.tsx | 368 +- .../UsabilityTesting/UsabilityTesting.tsx | 75 +- frontend/app/components/hocs/index.js | 2 +- frontend/app/components/hocs/withCopy.tsx | 4 +- .../components/hocs/withLocationHandlers.js | 12 +- frontend/app/components/hocs/withOverlay.js | 114 +- frontend/app/components/hocs/withPageTitle.js | 18 +- .../app/components/hocs/withPermissions.js | 16 +- frontend/app/components/hocs/withReport.tsx | 33 +- frontend/app/components/hocs/withRequest.js | 117 +- .../app/components/hocs/withSiteIdRouter.js | 16 +- .../app/components/hocs/withSiteIdUpdater.js | 18 +- frontend/app/components/hocs/withToggle.js | 32 +- .../AlertTriggersModal/AlertTriggersModal.tsx | 120 +- .../AlertTypeLabel/AlertTypeLabel.tsx | 12 +- .../AlertTypeLabel/index.ts | 2 +- .../AlertTriggersModal/ListItem/ListItem.tsx | 20 +- .../shared/AlertTriggersModal/index.ts | 2 +- .../shared/AnimatedSVG/AnimatedSVG.tsx | 74 +- .../components/shared/AnimatedSVG/index.ts | 3 +- .../shared/AutoplayToggle/AutoplayToggle.tsx | 1 - .../shared/BannerMessage/BannerMessage.js | 36 +- .../components/shared/BannerMessage/index.js | 2 +- .../components/shared/Bookmark/Bookmark.tsx | 10 +- .../app/components/shared/Bookmark/index.js | 2 +- .../shared/Breadcrumb/BackButton.tsx | 4 +- .../app/components/shared/Breadcrumb/index.ts | 2 +- .../ChromePluginMessage.js | 16 +- .../shared/ChromePluginMessage/index.js | 2 +- .../shared/CodeSnippet/CodeSnippet.tsx | 36 +- .../components/shared/CodeSnippet/index.ts | 2 +- .../shared/ConditionSet/ConditionSet.tsx | 28 +- .../shared/ConditionSet/Conditions.tsx | 6 +- .../components/shared/ConditionSet/index.ts | 2 +- .../components/shared/CopyText/CopyText.tsx | 6 +- frontend/app/components/shared/Copyright.tsx | 17 +- .../app/components/shared/CountryFlagIcon.tsx | 2 +- .../CustomDropdownOption.tsx | 6 +- .../components/shared/DatePicker/config.ts | 38 +- frontend/app/components/shared/DateRange.js | 22 +- .../DateRangeDropdown/DateOptionLabel.js | 16 +- .../DateRangeDropdown/DateRangePopup.tsx | 36 +- .../DevTools/BottomBlock/BottomBlock.tsx | 6 +- .../shared/DevTools/BottomBlock/Content.tsx | 14 +- .../shared/DevTools/BottomBlock/Header.tsx | 12 +- .../shared/DevTools/BottomBlock/InfoLine.js | 32 +- .../shared/DevTools/BottomBlock/index.ts | 2 +- .../DevTools/ConsolePanel/ConsolePanel.tsx | 68 +- .../ConsolePanel/MobileConsolePanel.tsx | 27 +- .../shared/DevTools/ConsoleRow/ConsoleRow.tsx | 38 +- .../shared/DevTools/JumpButton/JumpButton.tsx | 2 +- .../DevTools/NetworkPanel/NetworkPanel.tsx | 166 +- .../shared/DevTools/NetworkPanel/WSModal.tsx | 32 +- .../shared/DevTools/NetworkPanel/WSPanel.tsx | 88 +- .../DevTools/ProfilerModal/ProfilerModal.tsx | 10 +- .../DevTools/ProfilerPanel/ProfilerPanel.tsx | 16 +- .../StackEventPanel/StackEventPanel.tsx | 56 +- .../DevTools/StackEventRow/StackEventRow.tsx | 14 +- .../shared/DevTools/TabSelector.tsx | 18 +- .../app/components/shared/DevTools/TabTag.tsx | 4 +- .../shared/DevTools/TimeTable/BarRow.tsx | 18 +- .../shared/DevTools/TimeTable/TimeTable.tsx | 71 +- .../shared/DevTools/TimeTable/index.js | 2 +- .../shared/DevTools/useAutoscroll.ts | 42 +- .../shared/DevTools/useListFilter.ts | 48 +- .../app/components/shared/DocCard/DocCard.tsx | 2 +- .../app/components/shared/DocCard/index.ts | 2 +- .../app/components/shared/DocLink/DocLink.js | 20 +- .../app/components/shared/DocLink/index.js | 2 +- .../app/components/shared/Dropdown/index.tsx | 14 +- .../shared/DropdownPlain/DropdownPlain.tsx | 40 +- .../components/shared/DropdownPlain/index.ts | 2 +- .../EmailVerificationMessage.js | 3 +- .../shared/EmailVerificationMessage/index.js | 2 +- .../shared/ErrorsBadge/ErrorsBadge.js | 2 +- .../components/shared/ErrorsBadge/index.js | 2 +- .../EventSearchInput/EventSearchInput.tsx | 7 +- .../shared/EventSearchInput/index.ts | 2 +- .../FetchDetailsModal/FetchDetailsModal.tsx | 17 +- .../FetchBasicDetails/FetchBasicDetails.tsx | 44 +- .../components/FetchTabs/FetchTabs.tsx | 54 +- .../components/Headers/Headers.tsx | 20 +- .../components/Headers/index.ts | 2 +- .../shared/FetchDetailsModal/index.js | 2 +- .../shared/FilterDropdown/FilterDropdown.js | 132 +- .../components/shared/FilterDropdown/index.js | 2 +- .../FilterAutoComplete/AutocompleteModal.tsx | 64 +- .../FilterAutoComplete/FilterAutoComplete.tsx | 49 +- .../Filters/FilterAutoComplete/index.ts | 2 +- .../FilterAutoCompleteLocal.tsx | 34 +- .../Filters/FilterAutoCompleteLocal/index.ts | 2 +- .../Filters/FilterDuration/FilterDuration.js | 27 +- .../shared/Filters/FilterDuration/index.js | 2 +- .../shared/Filters/FilterItem/FilterItem.tsx | 71 +- .../shared/Filters/FilterItem/index.ts | 2 +- .../shared/Filters/FilterList/EventsOrder.tsx | 11 +- .../shared/Filters/FilterList/FilterList.tsx | 211 +- .../shared/Filters/FilterList/index.ts | 2 +- .../Filters/FilterModal/FilterModal.tsx | 167 +- .../Filters/FilterOperator/FilterOperator.tsx | 38 +- .../shared/Filters/FilterOperator/index.ts | 2 +- .../FilterSelection/FilterSelection.tsx | 24 +- .../shared/Filters/FilterSelection/index.ts | 2 +- .../Filters/FilterSource/FilterSource.tsx | 46 +- .../shared/Filters/FilterSource/index.ts | 2 +- .../Filters/FilterValue/FilterValue.tsx | 86 +- .../shared/Filters/FilterValue/index.ts | 2 +- .../FilterValueDropdown.tsx | 26 +- .../Filters/FilterValueDropdown/index.ts | 2 +- .../LiveFilterModal/LiveFilterModal.tsx | 59 +- .../shared/Filters/LiveFilterModal/index.ts | 2 +- .../Filters/SubFilterItem/SubFilterItem.tsx | 36 +- .../shared/Filters/SubFilterItem/index.ts | 2 +- .../shared/GettingStarted/CircleProgress.tsx | 8 +- .../GettingStarted/GettingStartedModal.tsx | 6 +- .../GettingStarted/GettingStartedProgress.tsx | 19 +- .../shared/GettingStarted/StepList.tsx | 14 +- .../components/shared/GettingStarted/index.ts | 2 +- .../GraphQLDetailsModal.tsx | 20 +- .../shared/GuidePopup/GuidePopup.tsx | 16 +- .../app/components/shared/GuidePopup/index.ts | 2 +- .../Insights/SankeyChart/CustomLink.tsx | 43 +- .../Insights/SankeyChart/CustomNode.tsx | 80 +- .../Insights/SankeyChart/NodeButton.tsx | 27 +- .../Insights/SankeyChart/NodeDropdown.tsx | 14 +- .../Insights/SankeyChart/SankeyChart.tsx | 202 +- .../shared/Insights/SankeyChart/utils.ts | 13 +- .../Insights/ScatterChart/ScatterChart.tsx | 4 +- .../IntegrateSlackButton.js | 13 +- .../shared/IntegrateSlackButton/index.js | 2 +- .../shared/LiveSearchBar/LiveSearchBar.tsx | 8 +- .../components/shared/LiveSearchBar/index.ts | 2 +- .../LiveSessionList/LiveSessionList.tsx | 48 +- .../shared/LiveSessionList/index.js | 2 +- .../LiveSessionReloadButton.tsx | 4 +- .../shared/LiveSessionReloadButton/index.ts | 2 +- .../LiveSessionSearch/LiveSessionSearch.tsx | 4 +- .../shared/LiveSessionSearch/index.ts | 2 +- .../LiveSessionSearchField.tsx | 9 +- .../shared/LiveSessionSearchField/index.ts | 2 +- .../shared/MainSearchBar/MainSearchBar.tsx | 6 +- .../MainSearchBar/components/TagList.tsx | 41 +- .../components/shared/MainSearchBar/index.ts | 2 +- .../components/shared/NewBadge/NewBadge.js | 10 +- .../app/components/shared/NewBadge/index.js | 2 +- .../NoSessionsMessage/NoSessionsMessage.js | 18 +- .../shared/NoSessionsMessage/index.js | 2 +- .../app/components/shared/NotFoundPage.tsx | 12 +- .../OutsideClickDetectingDiv.js | 12 +- .../shared/OutsideClickDetectingDiv/index.js | 2 +- .../ProjectDropdown/ProjectDropdown.tsx | 39 +- .../shared/ProjectDropdown/index.ts | 2 +- .../shared/ReloadButton/ReloadButton.tsx | 4 +- .../components/shared/ReloadButton/index.ts | 2 +- .../components/shared/ResultTimings/Bar.js | 8 +- .../shared/ResultTimings/Barwrapper.js | 10 +- .../shared/ResultTimings/ResultTimings.js | 28 +- .../shared/ResultTimings/SectionWrapper.js | 6 +- .../SaveFilterButton/SaveFilterButton.tsx | 2 +- .../shared/SaveFilterButton/index.ts | 2 +- .../SaveSearchModal/SaveSearchModal.tsx | 34 +- .../shared/SaveSearchModal/index.ts | 2 +- .../shared/SavedSearch/SavedSearch.tsx | 20 +- .../SavedSearchModal/SavedSearchModal.tsx | 20 +- .../components/SavedSearchModal/index.ts | 2 +- .../components/shared/SavedSearch/index.ts | 2 +- .../shared/SearchActions/SearchActions.tsx | 34 +- .../components/shared/SearchActions/index.ts | 2 +- .../app/components/shared/Select/Select.tsx | 75 +- .../app/components/shared/Select/index.ts | 2 +- .../SelectDateRange/SelectDateRange.tsx | 69 +- .../shared/SelectDateRange/index.ts | 2 +- .../SessionFilters/AiSessionSearchField.tsx | 95 +- .../shared/SessionFilters/SessionFilters.tsx | 16 +- .../components/shared/SessionFilters/index.ts | 2 +- .../components/shared/SessionItem/Counter.tsx | 14 +- .../SessionItem/ErrorBars/ErrorBars.tsx | 69 +- .../shared/SessionItem/ErrorBars/index.ts | 2 +- .../shared/SessionItem/MetaItem/MetaItem.tsx | 28 +- .../shared/SessionItem/MetaItem/index.ts | 2 +- .../MetaMoreButton/MetaMoreButton.tsx | 9 +- .../SessionItem/MetaMoreButton/index.ts | 2 +- .../shared/SessionItem/PlayLink/PlayLink.tsx | 28 +- .../shared/SessionItem/PlayLink/index.ts | 2 +- .../shared/SessionItem/SessionItem.tsx | 84 +- .../SessionMetaList/SessionMetaList.tsx | 2 +- .../SessionItem/SessionMetaList/index.ts | 2 +- .../components/shared/SessionItem/index.ts | 2 +- .../SessionSettings/SessionSettings.tsx | 22 +- .../components/CaptureRate.tsx | 34 +- .../ConditionalRecordingSettings.tsx | 20 +- .../components/DefaultPlaying.tsx | 7 +- .../components/DefaultTimezone.tsx | 26 +- .../components/ListingVisibility.tsx | 120 +- .../components/MouseTrailSettings.tsx | 10 +- .../shared/SessionSettings/index.ts | 2 +- .../SessionsTabOverview.tsx | 16 +- .../components/Bookmarks/Bookmarks.tsx | 32 +- .../LatestSessionsMessage.tsx | 9 +- .../components/NoContentMessage.tsx | 6 +- .../components/Notes/NoteItem.tsx | 40 +- .../components/Notes/NoteList.tsx | 110 +- .../components/Notes/NoteTags.tsx | 8 +- .../components/Notes/NotesRoute.tsx | 12 +- .../components/Notes/TeamBadge.tsx | 8 +- .../components/Notes/index.ts | 4 +- .../components/RecordingStatus.tsx | 30 +- .../SessionHeader/SessionHeader.tsx | 6 +- .../components/SessionHeader/index.ts | 2 +- .../SessionList/SessionDateRange.tsx | 10 +- .../components/SessionList/SessionList.tsx | 72 +- .../components/SessionList/index.ts | 2 +- .../SessionSettingButton.tsx | 24 +- .../components/SessionSettingButton/index.ts | 2 +- .../components/SessionSort/SessionSort.tsx | 12 +- .../components/SessionSort/index.ts | 2 +- .../components/SessionTags/SessionTags.tsx | 21 +- .../SessionCopyLink/SessionCopyLink.tsx | 6 +- .../SharePopup/SessionCopyLink/index.ts | 2 +- .../shared/SharePopup/SharePopup.tsx | 42 +- .../app/components/shared/SharePopup/index.js | 2 +- .../shared/SiteDropdown/SiteDropdown.js | 16 +- .../components/shared/SiteDropdown/index.js | 2 +- .../SortOrderButton/SortOrderButton.tsx | 4 +- .../shared/SortOrderButton/index.ts | 2 +- .../components/SupportList/SupportList.tsx | 6 +- .../components/SupportList/index.ts | 2 +- .../components/shared/SupportCallout/index.ts | 2 +- .../shared/ToggleContent/ToggleContent.js | 14 +- .../components/shared/ToggleContent/index.js | 2 +- .../CopyButton/CopyButton.js | 13 +- .../TrackingCodeModal/CopyButton/index.js | 2 +- .../InstallDocs/InstallDocs.js | 37 +- .../TrackingCodeModal/InstallDocs/index.js | 2 +- .../TrackingCodeModal/InstallIosDocs.tsx | 41 +- .../ProjectCodeSnippet/ProjectCodeSnippet.js | 98 +- .../ProjectCodeSnippet/index.js | 2 +- .../TrackingCodeModal/TrackingCodeModal.js | 9 +- .../shared/TrackingCodeModal/index.js | 2 +- .../UserSessionsModal/UserSessionsModal.tsx | 171 +- .../shared/UserSessionsModal/index.ts | 2 +- .../WidgetAutoComplete/WidgetAutoComplete.js | 50 +- .../shared/XRayButton/XRayButton.tsx | 12 +- .../app/components/shared/XRayButton/index.ts | 2 +- frontend/app/components/ui/Avatar/Avatar.js | 32 +- frontend/app/components/ui/Avatar/index.js | 2 +- .../app/components/ui/BackLink/BackLink.js | 45 +- frontend/app/components/ui/Button/Button.tsx | 11 +- .../app/components/ui/Checkbox/Checkbox.tsx | 18 +- frontend/app/components/ui/Checkbox/index.ts | 2 +- .../ui/CircularLoader/CircularLoader.js | 17 +- .../app/components/ui/CircularLoader/index.js | 2 +- .../components/ui/CloseButton/CloseButton.tsx | 14 +- .../app/components/ui/CodeBlock/CodeBlock.tsx | 4 +- frontend/app/components/ui/CodeBlock/index.ts | 2 +- .../ui/Confirmation/Confirmation.js | 26 +- .../app/components/ui/Confirmation/index.ts | 2 +- .../components/ui/CopyButton/CopyButton.js | 13 +- .../app/components/ui/CopyButton/index.js | 2 +- .../components/ui/CountryFlag/CountryFlag.tsx | 26 +- .../app/components/ui/CountryFlag/index.js | 2 +- frontend/app/components/ui/Divider.tsx | 6 +- .../ui/ErrorDetails/ErrorDetails.tsx | 110 +- .../components/ui/ErrorFrame/ErrorFrame.js | 90 +- .../app/components/ui/ErrorFrame/index.js | 2 +- .../app/components/ui/ErrorItem/ErrorItem.tsx | 6 +- frontend/app/components/ui/ErrorItem/index.ts | 2 +- .../ui/EscapeButton/EscapeButton.js | 12 +- .../app/components/ui/EscapeButton/index.js | 2 +- frontend/app/components/ui/Form/Form.tsx | 40 +- frontend/app/components/ui/Form/index.ts | 2 +- .../ui/HighlightCode/HighlightCode.js | 12 +- .../app/components/ui/HighlightCode/index.js | 2 +- frontend/app/components/ui/Icon/Browser.js | 10 +- frontend/app/components/ui/Icon/Icon.tsx | 26 +- frontend/app/components/ui/Icon/Os.js | 10 +- .../components/ui/IconButton/IconButton.js | 6 +- frontend/app/components/ui/Icons/activity.tsx | 9 +- .../app/components/ui/Icons/alarm_clock.tsx | 12 +- .../app/components/ui/Icons/alarm_plus.tsx | 9 +- .../app/components/ui/Icons/all_sessions.tsx | 9 +- .../app/components/ui/Icons/analytics.tsx | 9 +- frontend/app/components/ui/Icons/anchor.tsx | 9 +- .../ui/Icons/arrow_alt_square_right.tsx | 9 +- .../components/ui/Icons/arrow_bar_left.tsx | 9 +- .../components/ui/Icons/arrow_clockwise.tsx | 12 +- .../ui/Icons/arrow_counterclockwise.tsx | 12 +- .../app/components/ui/Icons/arrow_down.tsx | 9 +- .../components/ui/Icons/arrow_down_short.tsx | 9 +- .../app/components/ui/Icons/arrow_down_up.tsx | 9 +- .../app/components/ui/Icons/arrow_repeat.tsx | 12 +- .../components/ui/Icons/arrow_right_short.tsx | 9 +- .../components/ui/Icons/arrow_square_left.tsx | 9 +- .../ui/Icons/arrow_square_right.tsx | 9 +- frontend/app/components/ui/Icons/arrow_up.tsx | 9 +- .../components/ui/Icons/arrow_up_short.tsx | 9 +- .../ui/Icons/arrows_angle_extend.tsx | 9 +- .../ui/Icons/avatar_icn_avatar1.tsx | 14 +- .../ui/Icons/avatar_icn_avatar10.tsx | 14 +- .../ui/Icons/avatar_icn_avatar11.tsx | 16 +- .../ui/Icons/avatar_icn_avatar12.tsx | 19 +- .../ui/Icons/avatar_icn_avatar13.tsx | 13 +- .../ui/Icons/avatar_icn_avatar14.tsx | 16 +- .../ui/Icons/avatar_icn_avatar15.tsx | 14 +- .../ui/Icons/avatar_icn_avatar16.tsx | 15 +- .../ui/Icons/avatar_icn_avatar17.tsx | 13 +- .../ui/Icons/avatar_icn_avatar18.tsx | 16 +- .../ui/Icons/avatar_icn_avatar19.tsx | 12 +- .../ui/Icons/avatar_icn_avatar2.tsx | 14 +- .../ui/Icons/avatar_icn_avatar20.tsx | 16 +- .../ui/Icons/avatar_icn_avatar21.tsx | 15 +- .../ui/Icons/avatar_icn_avatar22.tsx | 13 +- .../ui/Icons/avatar_icn_avatar23.tsx | 14 +- .../ui/Icons/avatar_icn_avatar3.tsx | 13 +- .../ui/Icons/avatar_icn_avatar4.tsx | 15 +- .../ui/Icons/avatar_icn_avatar5.tsx | 15 +- .../ui/Icons/avatar_icn_avatar6.tsx | 13 +- .../ui/Icons/avatar_icn_avatar7.tsx | 21 +- .../ui/Icons/avatar_icn_avatar8.tsx | 15 +- .../ui/Icons/avatar_icn_avatar9.tsx | 13 +- frontend/app/components/ui/Icons/ban.tsx | 9 +- .../components/ui/Icons/bar_chart_line.tsx | 9 +- .../app/components/ui/Icons/bar_pencil.tsx | 16 +- frontend/app/components/ui/Icons/battery.tsx | 9 +- .../components/ui/Icons/battery_charging.tsx | 14 +- frontend/app/components/ui/Icons/bell.tsx | 9 +- .../app/components/ui/Icons/bell_fill.tsx | 9 +- .../app/components/ui/Icons/bell_plus.tsx | 9 +- .../app/components/ui/Icons/bell_slash.tsx | 9 +- .../app/components/ui/Icons/binoculars.tsx | 9 +- frontend/app/components/ui/Icons/book.tsx | 12 +- frontend/app/components/ui/Icons/book_doc.tsx | 12 +- frontend/app/components/ui/Icons/bookmark.tsx | 9 +- .../app/components/ui/Icons/broadcast.tsx | 9 +- .../components/ui/Icons/browser_browser.tsx | 9 +- .../components/ui/Icons/browser_chrome.tsx | 9 +- .../app/components/ui/Icons/browser_edge.tsx | 9 +- .../components/ui/Icons/browser_electron.tsx | 14 +- .../components/ui/Icons/browser_facebook.tsx | 9 +- .../components/ui/Icons/browser_firefox.tsx | 9 +- .../app/components/ui/Icons/browser_ie.tsx | 9 +- .../app/components/ui/Icons/browser_opera.tsx | 9 +- .../components/ui/Icons/browser_safari.tsx | 9 +- .../app/components/ui/Icons/buildings.tsx | 12 +- frontend/app/components/ui/Icons/bullhorn.tsx | 9 +- .../app/components/ui/Icons/business_time.tsx | 9 +- frontend/app/components/ui/Icons/calendar.tsx | 9 +- .../app/components/ui/Icons/calendar_alt.tsx | 12 +- .../components/ui/Icons/calendar_check.tsx | 9 +- .../app/components/ui/Icons/calendar_day.tsx | 9 +- frontend/app/components/ui/Icons/call.tsx | 9 +- frontend/app/components/ui/Icons/camera.tsx | 9 +- .../app/components/ui/Icons/camera_alt.tsx | 9 +- .../app/components/ui/Icons/camera_video.tsx | 9 +- .../components/ui/Icons/camera_video_off.tsx | 9 +- .../components/ui/Icons/card_checklist.tsx | 12 +- .../app/components/ui/Icons/card_list.tsx | 12 +- .../app/components/ui/Icons/card_text.tsx | 12 +- .../components/ui/Icons/caret_down_fill.tsx | 9 +- .../components/ui/Icons/caret_left_fill.tsx | 9 +- .../components/ui/Icons/caret_right_fill.tsx | 9 +- .../app/components/ui/Icons/caret_up_fill.tsx | 9 +- .../app/components/ui/Icons/chat_dots.tsx | 12 +- .../components/ui/Icons/chat_left_text.tsx | 12 +- .../components/ui/Icons/chat_right_text.tsx | 12 +- .../components/ui/Icons/chat_square_quote.tsx | 12 +- frontend/app/components/ui/Icons/check.tsx | 9 +- .../app/components/ui/Icons/check_circle.tsx | 9 +- .../components/ui/Icons/check_circle_fill.tsx | 9 +- .../ui/Icons/chevron_double_left.tsx | 12 +- .../ui/Icons/chevron_double_right.tsx | 12 +- .../app/components/ui/Icons/chevron_down.tsx | 9 +- .../app/components/ui/Icons/chevron_left.tsx | 9 +- .../app/components/ui/Icons/chevron_right.tsx | 9 +- .../app/components/ui/Icons/chevron_up.tsx | 9 +- frontend/app/components/ui/Icons/circle.tsx | 9 +- .../app/components/ui/Icons/circle_fill.tsx | 9 +- .../components/ui/Icons/click_hesitation.tsx | 15 +- .../app/components/ui/Icons/click_rage.tsx | 13 +- .../components/ui/Icons/clipboard_check.tsx | 13 +- .../ui/Icons/clipboard_list_check.tsx | 12 +- frontend/app/components/ui/Icons/clock.tsx | 9 +- .../app/components/ui/Icons/clock_history.tsx | 13 +- frontend/app/components/ui/Icons/close.tsx | 12 +- .../components/ui/Icons/cloud_fog2_fill.tsx | 9 +- frontend/app/components/ui/Icons/code.tsx | 9 +- frontend/app/components/ui/Icons/cog.tsx | 12 +- frontend/app/components/ui/Icons/cogs.tsx | 9 +- .../app/components/ui/Icons/collection.tsx | 9 +- .../components/ui/Icons/collection_play.tsx | 12 +- .../app/components/ui/Icons/color_apple.tsx | 15 +- .../components/ui/Icons/color_browser_Tor.tsx | 33 +- .../ui/Icons/color_browser_applebot.tsx | 29 +- .../color_browser_browser_icons_color_Tor.tsx | 33 +- ...r_browser_browser_icons_color_applebot.tsx | 29 +- ...lor_browser_browser_icons_color_chrome.tsx | 39 +- ...wser_browser_icons_color_chrome_mobile.tsx | 39 +- ..._browser_icons_color_chrome_mobile_ios.tsx | 39 +- ...owser_browser_icons_color_duck_duck_go.tsx | 89 +- ..._browser_icons_color_duckduckgo_mobile.tsx | 89 +- ...color_browser_browser_icons_color_edge.tsx | 65 +- ...rowser_browser_icons_color_edge_mobile.tsx | 65 +- ...r_browser_browser_icons_color_facebook.tsx | 27 +- ...or_browser_browser_icons_color_firefox.tsx | 219 +- ...rowser_browser_icons_color_firefox_ios.tsx | 219 +- ...ser_browser_icons_color_firefox_mobile.tsx | 219 +- ...lor_browser_browser_icons_color_google.tsx | 19 +- ..._browser_browser_icons_color_googlebot.tsx | 19 +- ...ser_browser_icons_color_huawei_browser.tsx | 15 +- ..._browser_icons_color_internet_explorer.tsx | 13 +- ...owser_browser_icons_color_miui_browser.tsx | 27 +- ...wser_browser_icons_color_mobile_safari.tsx | 313 +- ...r_browser_icons_color_mobile_safari_ui.tsx | 313 +- ...olor_browser_browser_icons_color_opera.tsx | 43 +- ...lor_browser_browser_icons_color_safari.tsx | 313 +- ...r_browser_icons_color_samsung_internet.tsx | 15 +- ...browser_browser_icons_color_uc_browser.tsx | 75 +- ...or_browser_browser_icons_color_unknown.tsx | 17 +- ...olor_browser_browser_icons_color_whale.tsx | 57 +- ...ser_browser_icons_color_yandex_browser.tsx | 15 +- .../ui/Icons/color_browser_chrome.tsx | 39 +- .../ui/Icons/color_browser_chrome_mobile.tsx | 39 +- .../Icons/color_browser_chrome_mobile_ios.tsx | 39 +- .../ui/Icons/color_browser_duck_duck_go.tsx | 89 +- .../Icons/color_browser_duckduckgo_mobile.tsx | 89 +- .../ui/Icons/color_browser_edge.tsx | 65 +- .../ui/Icons/color_browser_edge_mobile.tsx | 65 +- .../ui/Icons/color_browser_facebook.tsx | 27 +- .../ui/Icons/color_browser_firefox.tsx | 219 +- .../ui/Icons/color_browser_firefox_ios.tsx | 219 +- .../ui/Icons/color_browser_firefox_mobile.tsx | 219 +- .../ui/Icons/color_browser_google.tsx | 19 +- .../ui/Icons/color_browser_googlebot.tsx | 19 +- .../ui/Icons/color_browser_huawei_browser.tsx | 15 +- .../Icons/color_browser_internet_explorer.tsx | 13 +- .../ui/Icons/color_browser_miui_browser.tsx | 27 +- .../ui/Icons/color_browser_mobile_safari.tsx | 313 +- .../Icons/color_browser_mobile_safari_ui.tsx | 313 +- .../ui/Icons/color_browser_opera.tsx | 43 +- .../ui/Icons/color_browser_safari.tsx | 313 +- .../Icons/color_browser_samsung_internet.tsx | 15 +- .../ui/Icons/color_browser_uc_browser.tsx | 75 +- .../ui/Icons/color_browser_unknown.tsx | 17 +- .../ui/Icons/color_browser_whale.tsx | 57 +- .../ui/Icons/color_browser_yandex_browser.tsx | 15 +- .../app/components/ui/Icons/color_chrome.tsx | 39 +- .../components/ui/Icons/color_country_de.tsx | 33 +- .../components/ui/Icons/color_country_fr.tsx | 33 +- .../components/ui/Icons/color_country_gb.tsx | 57 +- .../components/ui/Icons/color_country_in.tsx | 47 +- .../components/ui/Icons/color_country_us.tsx | 47 +- frontend/app/components/ui/Icons/color_de.tsx | 33 +- .../ui/Icons/color_device_desktop.tsx | 17 +- .../ui/Icons/color_device_mobile.tsx | 41 +- .../ui/Icons/color_device_other_phone.tsx | 31 +- .../ui/Icons/color_device_tablet.tsx | 17 +- .../ui/Icons/color_device_unkown.tsx | 21 +- .../app/components/ui/Icons/color_edge.tsx | 65 +- .../app/components/ui/Icons/color_fedora.tsx | 17 +- .../app/components/ui/Icons/color_firefox.tsx | 219 +- frontend/app/components/ui/Icons/color_fr.tsx | 33 +- frontend/app/components/ui/Icons/color_gb.tsx | 57 +- frontend/app/components/ui/Icons/color_in.tsx | 47 +- .../ui/Icons/color_issues_bad_request.tsx | 27 +- .../ui/Icons/color_issues_click_rage.tsx | 21 +- .../components/ui/Icons/color_issues_cpu.tsx | 33 +- .../ui/Icons/color_issues_crash.tsx | 23 +- .../ui/Icons/color_issues_custom.tsx | 21 +- .../ui/Icons/color_issues_dead_click.tsx | 33 +- .../ui/Icons/color_issues_errors.tsx | 19 +- .../color_issues_excessive_scrolling.tsx | 19 +- .../ui/Icons/color_issues_js_exception.tsx | 19 +- .../ui/Icons/color_issues_memory.tsx | 31 +- .../Icons/color_issues_missing_resource.tsx | 25 +- .../ui/Icons/color_issues_mouse_thrashing.tsx | 17 +- .../ui/Icons/color_issues_mouse_trashing.tsx | 17 +- .../ui/Icons/color_issues_slow_page_load.tsx | 47 +- .../components/ui/Icons/color_microsoft.tsx | 19 +- .../app/components/ui/Icons/color_opera.tsx | 43 +- .../components/ui/Icons/color_os_android.tsx | 19 +- .../components/ui/Icons/color_os_apple.tsx | 15 +- .../ui/Icons/color_os_blackberry.tsx | 27 +- .../ui/Icons/color_os_chrome_os.tsx | 39 +- .../ui/Icons/color_os_elementary.tsx | 13 +- .../components/ui/Icons/color_os_fedora.tsx | 17 +- .../components/ui/Icons/color_os_freebsd.tsx | 19 +- .../components/ui/Icons/color_os_gnome.tsx | 13 +- .../app/components/ui/Icons/color_os_ios.tsx | 19 +- .../components/ui/Icons/color_os_linux.tsx | 189 +- .../ui/Icons/color_os_linux_mint.tsx | 43 +- .../components/ui/Icons/color_os_macos.tsx | 31 +- .../ui/Icons/color_os_microsoft.tsx | 19 +- .../components/ui/Icons/color_os_ubuntu.tsx | 15 +- .../components/ui/Icons/color_os_unkown.tsx | 21 +- .../app/components/ui/Icons/color_safari.tsx | 313 +- .../app/components/ui/Icons/color_ubuntu.tsx | 15 +- frontend/app/components/ui/Icons/color_us.tsx | 47 +- .../app/components/ui/Icons/columns_gap.tsx | 9 +- .../ui/Icons/columns_gap_filled.tsx | 9 +- frontend/app/components/ui/Icons/console.tsx | 12 +- .../app/components/ui/Icons/console_error.tsx | 12 +- .../components/ui/Icons/console_exception.tsx | 9 +- .../app/components/ui/Icons/console_info.tsx | 12 +- .../components/ui/Icons/console_warning.tsx | 9 +- .../app/components/ui/Icons/controller.tsx | 12 +- frontend/app/components/ui/Icons/cookies.tsx | 17 +- frontend/app/components/ui/Icons/copy.tsx | 9 +- .../ui/Icons/credit_card_2_back.tsx | 12 +- .../components/ui/Icons/credit_card_front.tsx | 12 +- frontend/app/components/ui/Icons/cross.tsx | 9 +- frontend/app/components/ui/Icons/cubes.tsx | 12 +- .../app/components/ui/Icons/cursor_trash.tsx | 17 +- frontend/app/components/ui/Icons/dash.tsx | 9 +- .../app/components/ui/Icons/dashboard_icn.tsx | 54 +- .../ui/Icons/dashboards_circle_alert.tsx | 21 +- .../ui/Icons/dashboards_cohort_chart.tsx | 16 +- .../ui/Icons/dashboards_heatmap_2.tsx | 15 +- .../ui/Icons/dashboards_user_journey.tsx | 15 +- .../ui/Icons/db_icons_icn_card_clickMap.tsx | 32 +- .../ui/Icons/db_icons_icn_card_errors.tsx | 20 +- .../ui/Icons/db_icons_icn_card_funnel.tsx | 48 +- .../ui/Icons/db_icons_icn_card_funnels.tsx | 53 +- .../ui/Icons/db_icons_icn_card_insights.tsx | 31 +- .../ui/Icons/db_icons_icn_card_library.tsx | 24 +- .../ui/Icons/db_icons_icn_card_mapchart.tsx | 25 +- .../Icons/db_icons_icn_card_pathAnalysis.tsx | 29 +- .../Icons/db_icons_icn_card_performance.tsx | 22 +- .../ui/Icons/db_icons_icn_card_resources.tsx | 60 +- .../ui/Icons/db_icons_icn_card_table.tsx | 40 +- .../ui/Icons/db_icons_icn_card_timeseries.tsx | 19 +- .../ui/Icons/db_icons_icn_card_webVitals.tsx | 49 +- frontend/app/components/ui/Icons/desktop.tsx | 9 +- frontend/app/components/ui/Icons/device.tsx | 12 +- .../app/components/ui/Icons/diagram_3.tsx | 9 +- frontend/app/components/ui/Icons/dice_3.tsx | 12 +- frontend/app/components/ui/Icons/dizzy.tsx | 9 +- .../app/components/ui/Icons/door_closed.tsx | 12 +- .../app/components/ui/Icons/doublecheck.tsx | 9 +- frontend/app/components/ui/Icons/download.tsx | 12 +- frontend/app/components/ui/Icons/drag.tsx | 9 +- frontend/app/components/ui/Icons/edit.tsx | 9 +- .../app/components/ui/Icons/ellipsis_v.tsx | 9 +- .../app/components/ui/Icons/emoji_dizzy.tsx | 12 +- frontend/app/components/ui/Icons/enter.tsx | 9 +- frontend/app/components/ui/Icons/envelope.tsx | 9 +- .../components/ui/Icons/envelope_check.tsx | 12 +- .../components/ui/Icons/envelope_paper.tsx | 9 +- .../app/components/ui/Icons/envelope_x.tsx | 12 +- .../app/components/ui/Icons/errors_icon.tsx | 12 +- .../app/components/ui/Icons/event_click.tsx | 9 +- .../ui/Icons/event_click_hesitation.tsx | 15 +- .../components/ui/Icons/event_clickrage.tsx | 12 +- .../app/components/ui/Icons/event_code.tsx | 9 +- .../components/ui/Icons/event_i_cursor.tsx | 9 +- .../app/components/ui/Icons/event_input.tsx | 12 +- .../ui/Icons/event_input_hesitation.tsx | 16 +- .../app/components/ui/Icons/event_link.tsx | 12 +- .../components/ui/Icons/event_location.tsx | 9 +- .../ui/Icons/event_mouse_thrashing.tsx | 17 +- .../app/components/ui/Icons/event_resize.tsx | 9 +- .../app/components/ui/Icons/event_view.tsx | 12 +- .../ui/Icons/exclamation_circle.tsx | 12 +- .../ui/Icons/exclamation_circle_fill.tsx | 12 +- .../ui/Icons/exclamation_triangle.tsx | 9 +- .../app/components/ui/Icons/expand_wide.tsx | 12 +- .../app/components/ui/Icons/explosion.tsx | 9 +- .../components/ui/Icons/external_link_alt.tsx | 12 +- frontend/app/components/ui/Icons/eye.tsx | 9 +- .../app/components/ui/Icons/eye_slash.tsx | 9 +- .../components/ui/Icons/eye_slash_fill.tsx | 12 +- frontend/app/components/ui/Icons/fetch.tsx | 9 +- .../app/components/ui/Icons/fetch_request.tsx | 12 +- .../app/components/ui/Icons/fflag_multi.tsx | 17 +- .../app/components/ui/Icons/fflag_single.tsx | 12 +- frontend/app/components/ui/Icons/file.tsx | 9 +- .../components/ui/Icons/file_bar_graph.tsx | 15 +- .../app/components/ui/Icons/file_code.tsx | 12 +- .../components/ui/Icons/file_medical_alt.tsx | 12 +- frontend/app/components/ui/Icons/file_pdf.tsx | 15 +- frontend/app/components/ui/Icons/files.tsx | 9 +- .../app/components/ui/Icons/filetype_js.tsx | 9 +- .../app/components/ui/Icons/filetype_pdf.tsx | 9 +- frontend/app/components/ui/Icons/filter.tsx | 9 +- .../ui/Icons/filters_arrow_return_right.tsx | 9 +- .../components/ui/Icons/filters_browser.tsx | 9 +- .../ui/Icons/filters_chevrons_up_down.tsx | 9 +- .../app/components/ui/Icons/filters_click.tsx | 9 +- .../components/ui/Icons/filters_clickrage.tsx | 12 +- .../app/components/ui/Icons/filters_code.tsx | 9 +- .../components/ui/Icons/filters_console.tsx | 9 +- .../components/ui/Icons/filters_country.tsx | 12 +- .../components/ui/Icons/filters_cpu_load.tsx | 17 +- .../components/ui/Icons/filters_custom.tsx | 9 +- .../components/ui/Icons/filters_device.tsx | 12 +- .../ui/Icons/filters_dom_complete.tsx | 13 +- .../components/ui/Icons/filters_duration.tsx | 9 +- .../app/components/ui/Icons/filters_error.tsx | 12 +- .../app/components/ui/Icons/filters_fetch.tsx | 9 +- .../ui/Icons/filters_fetch_failed.tsx | 14 +- .../components/ui/Icons/filters_file_code.tsx | 9 +- .../components/ui/Icons/filters_graphql.tsx | 9 +- .../components/ui/Icons/filters_i_cursor.tsx | 9 +- .../app/components/ui/Icons/filters_input.tsx | 12 +- .../app/components/ui/Icons/filters_lcpt.tsx | 13 +- .../app/components/ui/Icons/filters_link.tsx | 12 +- .../components/ui/Icons/filters_location.tsx | 9 +- .../ui/Icons/filters_memory_load.tsx | 13 +- .../components/ui/Icons/filters_metadata.tsx | 9 +- .../app/components/ui/Icons/filters_os.tsx | 9 +- .../filters_perfromance_network_request.tsx | 13 +- .../components/ui/Icons/filters_platform.tsx | 9 +- .../components/ui/Icons/filters_referrer.tsx | 12 +- .../components/ui/Icons/filters_resize.tsx | 9 +- .../components/ui/Icons/filters_rev_id.tsx | 9 +- .../components/ui/Icons/filters_screen.tsx | 13 +- .../ui/Icons/filters_state_action.tsx | 9 +- .../ui/Icons/filters_tag_element.tsx | 12 +- .../app/components/ui/Icons/filters_ttfb.tsx | 17 +- .../components/ui/Icons/filters_user_alt.tsx | 12 +- .../components/ui/Icons/filters_userid.tsx | 9 +- .../app/components/ui/Icons/filters_view.tsx | 12 +- frontend/app/components/ui/Icons/flag_na.tsx | 9 +- frontend/app/components/ui/Icons/folder2.tsx | 9 +- .../app/components/ui/Icons/folder_plus.tsx | 12 +- .../app/components/ui/Icons/fullscreen.tsx | 9 +- frontend/app/components/ui/Icons/funnel.tsx | 9 +- .../app/components/ui/Icons/funnel_cpu.tsx | 9 +- .../components/ui/Icons/funnel_cpu_fill.tsx | 12 +- .../app/components/ui/Icons/funnel_dizzy.tsx | 9 +- .../ui/Icons/funnel_emoji_angry.tsx | 12 +- .../ui/Icons/funnel_emoji_angry_fill.tsx | 9 +- .../ui/Icons/funnel_emoji_dizzy_fill.tsx | 9 +- .../ui/Icons/funnel_exclamation_circle.tsx | 12 +- .../Icons/funnel_exclamation_circle_fill.tsx | 9 +- .../ui/Icons/funnel_file_earmark_break.tsx | 9 +- .../Icons/funnel_file_earmark_break_fill.tsx | 9 +- .../ui/Icons/funnel_file_earmark_minus.tsx | 12 +- .../Icons/funnel_file_earmark_minus_fill.tsx | 9 +- .../ui/Icons/funnel_file_medical_alt.tsx | 12 +- .../app/components/ui/Icons/funnel_file_x.tsx | 12 +- .../app/components/ui/Icons/funnel_fill.tsx | 9 +- .../components/ui/Icons/funnel_hdd_fill.tsx | 9 +- .../ui/Icons/funnel_hourglass_top.tsx | 9 +- .../app/components/ui/Icons/funnel_image.tsx | 12 +- .../components/ui/Icons/funnel_image_fill.tsx | 9 +- .../components/ui/Icons/funnel_microchip.tsx | 12 +- .../app/components/ui/Icons/funnel_mouse.tsx | 9 +- .../app/components/ui/Icons/funnel_new.tsx | 9 +- .../Icons/funnel_patch_exclamation_fill.tsx | 9 +- .../components/ui/Icons/funnel_sd_card.tsx | 12 +- frontend/app/components/ui/Icons/gear.tsx | 12 +- .../app/components/ui/Icons/gear_fill.tsx | 9 +- .../ui/Icons/geo_alt_fill_custom.tsx | 9 +- frontend/app/components/ui/Icons/github.tsx | 9 +- frontend/app/components/ui/Icons/graph_up.tsx | 12 +- .../components/ui/Icons/graph_up_arrow.tsx | 9 +- frontend/app/components/ui/Icons/grid.tsx | 9 +- frontend/app/components/ui/Icons/grid_1x2.tsx | 9 +- frontend/app/components/ui/Icons/grid_3x3.tsx | 9 +- .../app/components/ui/Icons/grid_check.tsx | 9 +- .../components/ui/Icons/grid_horizontal.tsx | 9 +- .../components/ui/Icons/grip_horizontal.tsx | 9 +- frontend/app/components/ui/Icons/hash.tsx | 9 +- .../app/components/ui/Icons/hdd_stack.tsx | 13 +- frontend/app/components/ui/Icons/headset.tsx | 9 +- .../app/components/ui/Icons/heart_rate.tsx | 9 +- .../components/ui/Icons/high_engagement.tsx | 9 +- frontend/app/components/ui/Icons/history.tsx | 9 +- .../components/ui/Icons/hourglass_start.tsx | 9 +- .../app/components/ui/Icons/ic_errors.tsx | 12 +- .../app/components/ui/Icons/ic_network.tsx | 12 +- frontend/app/components/ui/Icons/ic_rage.tsx | 12 +- .../app/components/ui/Icons/ic_resources.tsx | 12 +- .../components/ui/Icons/icn_fetch_request.tsx | 15 +- .../app/components/ui/Icons/icn_referrer.tsx | 15 +- frontend/app/components/ui/Icons/icn_url.tsx | 15 +- frontend/app/components/ui/Icons/id_card.tsx | 12 +- frontend/app/components/ui/Icons/image.tsx | 12 +- frontend/app/components/ui/Icons/index.ts | 1 - frontend/app/components/ui/Icons/info.tsx | 12 +- .../app/components/ui/Icons/info_circle.tsx | 12 +- .../components/ui/Icons/info_circle_fill.tsx | 9 +- .../app/components/ui/Icons/info_square.tsx | 12 +- .../components/ui/Icons/input_hesitation.tsx | 16 +- frontend/app/components/ui/Icons/inspect.tsx | 9 +- .../ui/Icons/integrations_apple.tsx | 12 +- .../ui/Icons/integrations_assist.tsx | 20 +- .../ui/Icons/integrations_bugsnag.tsx | 12 +- .../ui/Icons/integrations_bugsnag_text.tsx | 9 +- .../ui/Icons/integrations_chrome.tsx | 24 +- .../ui/Icons/integrations_cloudwatch.tsx | 20 +- .../ui/Icons/integrations_cloudwatch_text.tsx | 21 +- .../ui/Icons/integrations_datadog.tsx | 9 +- .../ui/Icons/integrations_dynatrace.tsx | 19 +- .../components/ui/Icons/integrations_edge.tsx | 37 +- .../ui/Icons/integrations_elasticsearch.tsx | 17 +- .../Icons/integrations_elasticsearch_text.tsx | 18 +- .../ui/Icons/integrations_fedora.tsx | 13 +- .../ui/Icons/integrations_firefox.tsx | 114 +- .../ui/Icons/integrations_github.tsx | 9 +- .../ui/Icons/integrations_graphql.tsx | 12 +- .../components/ui/Icons/integrations_jira.tsx | 25 +- .../ui/Icons/integrations_jira_text.tsx | 21 +- .../ui/Icons/integrations_microsoft.tsx | 14 +- .../components/ui/Icons/integrations_mobx.tsx | 15 +- .../ui/Icons/integrations_newrelic.tsx | 16 +- .../ui/Icons/integrations_newrelic_text.tsx | 13 +- .../components/ui/Icons/integrations_ngrx.tsx | 16 +- .../ui/Icons/integrations_openreplay.tsx | 14 +- .../ui/Icons/integrations_openreplay_text.tsx | 15 +- .../ui/Icons/integrations_opera.tsx | 26 +- .../ui/Icons/integrations_redux.tsx | 16 +- .../ui/Icons/integrations_rollbar.tsx | 12 +- .../ui/Icons/integrations_rollbar_text.tsx | 14 +- .../ui/Icons/integrations_safari.tsx | 161 +- .../ui/Icons/integrations_segment.tsx | 12 +- .../ui/Icons/integrations_sentry.tsx | 9 +- .../ui/Icons/integrations_sentry_text.tsx | 9 +- .../ui/Icons/integrations_slack.tsx | 16 +- .../ui/Icons/integrations_slack_bw.tsx | 9 +- .../ui/Icons/integrations_stackdriver.tsx | 19 +- .../ui/Icons/integrations_sumologic.tsx | 12 +- .../ui/Icons/integrations_sumologic_text.tsx | 9 +- .../ui/Icons/integrations_teams.tsx | 29 +- .../ui/Icons/integrations_teams_white.tsx | 12 +- .../ui/Icons/integrations_ubuntu.tsx | 12 +- .../ui/Icons/integrations_vuejs.tsx | 14 +- .../ui/Icons/integrations_zustand.tsx | 24 +- .../app/components/ui/Icons/journal_code.tsx | 13 +- frontend/app/components/ui/Icons/key.tsx | 12 +- frontend/app/components/ui/Icons/keyboard.tsx | 12 +- .../app/components/ui/Icons/layer_group.tsx | 9 +- .../app/components/ui/Icons/layers_half.tsx | 9 +- .../app/components/ui/Icons/lightbulb.tsx | 9 +- .../app/components/ui/Icons/lightbulb_on.tsx | 12 +- .../app/components/ui/Icons/link_45deg.tsx | 12 +- frontend/app/components/ui/Icons/list.tsx | 9 +- frontend/app/components/ui/Icons/list_alt.tsx | 9 +- .../app/components/ui/Icons/list_arrow.tsx | 9 +- frontend/app/components/ui/Icons/list_ul.tsx | 9 +- frontend/app/components/ui/Icons/lock_alt.tsx | 9 +- .../components/ui/Icons/low_disc_space.tsx | 12 +- frontend/app/components/ui/Icons/magic.tsx | 9 +- .../components/ui/Icons/map_marker_alt.tsx | 12 +- frontend/app/components/ui/Icons/memory.tsx | 9 +- .../app/components/ui/Icons/memory_ios.tsx | 9 +- frontend/app/components/ui/Icons/mic.tsx | 12 +- frontend/app/components/ui/Icons/mic_mute.tsx | 12 +- frontend/app/components/ui/Icons/minus.tsx | 9 +- frontend/app/components/ui/Icons/mobile.tsx | 12 +- .../app/components/ui/Icons/mouse_alt.tsx | 9 +- .../ui/Icons/mouse_pointer_click.tsx | 14 +- frontend/app/components/ui/Icons/network.tsx | 15 +- frontend/app/components/ui/Icons/next1.tsx | 9 +- .../app/components/ui/Icons/no_dashboard.tsx | 16 +- .../app/components/ui/Icons/no_metrics.tsx | 16 +- .../components/ui/Icons/no_metrics_chart.tsx | 15 +- .../app/components/ui/Icons/no_recordings.tsx | 22 +- frontend/app/components/ui/Icons/orIcn.tsx | 16 +- frontend/app/components/ui/Icons/orSpot.tsx | 16 +- .../app/components/ui/Icons/orspotOutline.tsx | 12 +- frontend/app/components/ui/Icons/os.tsx | 9 +- .../app/components/ui/Icons/os_android.tsx | 9 +- .../app/components/ui/Icons/os_chrome_os.tsx | 9 +- .../app/components/ui/Icons/os_fedora.tsx | 9 +- frontend/app/components/ui/Icons/os_ios.tsx | 9 +- frontend/app/components/ui/Icons/os_linux.tsx | 9 +- .../app/components/ui/Icons/os_mac_os_x.tsx | 9 +- frontend/app/components/ui/Icons/os_other.tsx | 9 +- .../app/components/ui/Icons/os_ubuntu.tsx | 9 +- .../app/components/ui/Icons/os_windows.tsx | 9 +- frontend/app/components/ui/Icons/pause.tsx | 9 +- .../components/ui/Icons/pause_circle_fill.tsx | 9 +- .../app/components/ui/Icons/pause_fill.tsx | 9 +- .../app/components/ui/Icons/pdf_download.tsx | 13 +- frontend/app/components/ui/Icons/pencil.tsx | 9 +- .../app/components/ui/Icons/pencil_stop.tsx | 15 +- frontend/app/components/ui/Icons/people.tsx | 9 +- frontend/app/components/ui/Icons/percent.tsx | 9 +- .../components/ui/Icons/performance_icon.tsx | 12 +- frontend/app/components/ui/Icons/person.tsx | 9 +- .../app/components/ui/Icons/person_border.tsx | 12 +- .../app/components/ui/Icons/person_fill.tsx | 9 +- .../components/ui/Icons/pie_chart_fill.tsx | 9 +- frontend/app/components/ui/Icons/pin_fill.tsx | 9 +- frontend/app/components/ui/Icons/play.tsx | 9 +- .../app/components/ui/Icons/play_circle.tsx | 9 +- .../components/ui/Icons/play_circle_bold.tsx | 12 +- .../components/ui/Icons/play_circle_light.tsx | 9 +- .../app/components/ui/Icons/play_fill.tsx | 9 +- .../app/components/ui/Icons/play_fill_new.tsx | 9 +- .../app/components/ui/Icons/play_hover.tsx | 9 +- frontend/app/components/ui/Icons/plug.tsx | 9 +- frontend/app/components/ui/Icons/plus.tsx | 9 +- .../app/components/ui/Icons/plus_circle.tsx | 12 +- frontend/app/components/ui/Icons/plus_lg.tsx | 9 +- .../ui/Icons/pointer_sessions_search.tsx | 9 +- frontend/app/components/ui/Icons/prev1.tsx | 9 +- frontend/app/components/ui/Icons/pulse.tsx | 9 +- frontend/app/components/ui/Icons/puzzle.tsx | 9 +- .../app/components/ui/Icons/puzzle_piece.tsx | 9 +- .../components/ui/Icons/question_circle.tsx | 12 +- .../app/components/ui/Icons/question_lg.tsx | 9 +- .../app/components/ui/Icons/quote_left.tsx | 9 +- .../app/components/ui/Icons/quote_right.tsx | 9 +- frontend/app/components/ui/Icons/quotes.tsx | 9 +- frontend/app/components/ui/Icons/record2.tsx | 12 +- .../app/components/ui/Icons/record_btn.tsx | 12 +- .../app/components/ui/Icons/record_circle.tsx | 12 +- .../ui/Icons/record_circle_fill.tsx | 9 +- frontend/app/components/ui/Icons/redo.tsx | 9 +- .../app/components/ui/Icons/redo_back.tsx | 9 +- frontend/app/components/ui/Icons/redux.tsx | 9 +- frontend/app/components/ui/Icons/referrer.tsx | 14 +- .../components/ui/Icons/remote_control.tsx | 9 +- .../app/components/ui/Icons/replay_10.tsx | 9 +- .../components/ui/Icons/resources_icon.tsx | 9 +- frontend/app/components/ui/Icons/safe.tsx | 12 +- .../app/components/ui/Icons/safe_fill.tsx | 12 +- .../app/components/ui/Icons/sandglass.tsx | 9 +- frontend/app/components/ui/Icons/search.tsx | 9 +- .../ui/Icons/search_notification.tsx | 9 +- frontend/app/components/ui/Icons/server.tsx | 9 +- .../app/components/ui/Icons/share_alt.tsx | 9 +- .../app/components/ui/Icons/shield_lock.tsx | 12 +- .../components/ui/Icons/side_menu_closed.tsx | 9 +- .../components/ui/Icons/side_menu_open.tsx | 12 +- .../components/ui/Icons/signpost_split.tsx | 9 +- frontend/app/components/ui/Icons/signup.tsx | 9 +- .../app/components/ui/Icons/skip_forward.tsx | 9 +- .../components/ui/Icons/skip_forward_fill.tsx | 9 +- frontend/app/components/ui/Icons/slack.tsx | 9 +- .../app/components/ui/Icons/slash_circle.tsx | 12 +- frontend/app/components/ui/Icons/sleep.tsx | 12 +- frontend/app/components/ui/Icons/sliders.tsx | 9 +- .../app/components/ui/Icons/social_slack.tsx | 12 +- .../app/components/ui/Icons/social_trello.tsx | 9 +- frontend/app/components/ui/Icons/sparkles.tsx | 12 +- .../app/components/ui/Icons/speedometer2.tsx | 12 +- frontend/app/components/ui/Icons/spinner.tsx | 9 +- .../ui/Icons/square_mouse_pointer.tsx | 12 +- frontend/app/components/ui/Icons/star.tsx | 9 +- .../app/components/ui/Icons/star_solid.tsx | 9 +- .../app/components/ui/Icons/step_forward.tsx | 9 +- frontend/app/components/ui/Icons/stickies.tsx | 12 +- .../ui/Icons/stop_record_circle.tsx | 9 +- .../app/components/ui/Icons/stopwatch.tsx | 12 +- frontend/app/components/ui/Icons/store.tsx | 9 +- frontend/app/components/ui/Icons/sync_alt.tsx | 12 +- frontend/app/components/ui/Icons/table.tsx | 9 +- .../app/components/ui/Icons/table_new.tsx | 9 +- .../components/ui/Icons/tablet_android.tsx | 12 +- .../components/ui/Icons/tachometer_slow.tsx | 12 +- .../ui/Icons/tachometer_slowest.tsx | 9 +- frontend/app/components/ui/Icons/tags.tsx | 12 +- .../app/components/ui/Icons/team_funnel.tsx | 15 +- .../app/components/ui/Icons/telephone.tsx | 9 +- .../components/ui/Icons/telephone_fill.tsx | 9 +- frontend/app/components/ui/Icons/terminal.tsx | 12 +- .../components/ui/Icons/text_paragraph.tsx | 9 +- .../components/ui/Icons/thermometer_sun.tsx | 12 +- frontend/app/components/ui/Icons/toggles.tsx | 12 +- frontend/app/components/ui/Icons/tools.tsx | 9 +- frontend/app/components/ui/Icons/trash.tsx | 9 +- frontend/app/components/ui/Icons/turtle.tsx | 9 +- frontend/app/components/ui/Icons/user_alt.tsx | 9 +- .../app/components/ui/Icons/user_circle.tsx | 9 +- .../app/components/ui/Icons/user_friends.tsx | 9 +- .../app/components/ui/Icons/user_journey.tsx | 9 +- .../app/components/ui/Icons/user_switch.tsx | 9 +- frontend/app/components/ui/Icons/users.tsx | 9 +- .../components/ui/Icons/vendors_graphql.tsx | 9 +- .../app/components/ui/Icons/vendors_mobx.tsx | 9 +- .../app/components/ui/Icons/vendors_ngrx.tsx | 12 +- .../app/components/ui/Icons/vendors_redux.tsx | 13 +- .../app/components/ui/Icons/vendors_vuex.tsx | 12 +- .../app/components/ui/Icons/web_vitals.tsx | 9 +- frontend/app/components/ui/Icons/wifi.tsx | 12 +- frontend/app/components/ui/Icons/window.tsx | 9 +- .../app/components/ui/Icons/window_alt.tsx | 9 +- .../components/ui/Icons/window_restore.tsx | 9 +- frontend/app/components/ui/Icons/window_x.tsx | 13 +- frontend/app/components/ui/Icons/zoom_in.tsx | 13 +- .../components/ui/Information/Information.js | 10 +- .../app/components/ui/Information/index.js | 2 +- frontend/app/components/ui/Input/Input.tsx | 6 +- frontend/app/components/ui/Input/index.ts | 2 +- .../app/components/ui/ItemMenu/ItemMenu.tsx | 57 +- .../app/components/ui/JSONTree/JSONTree.tsx | 4 +- frontend/app/components/ui/JSONTree/index.js | 2 +- frontend/app/components/ui/Label/Label.js | 20 +- frontend/app/components/ui/Link/Link.js | 20 +- frontend/app/components/ui/Loader/Loader.tsx | 23 +- frontend/app/components/ui/Message/Message.js | 11 +- frontend/app/components/ui/Modal/Modal.tsx | 127 +- frontend/app/components/ui/Modal/index.ts | 2 +- .../app/components/ui/NoContent/NoContent.tsx | 33 +- .../ui/NoPermission/NoPermission.tsx | 8 +- .../app/components/ui/NoPermission/index.ts | 2 +- .../NoSessionPermission.tsx | 16 +- .../ui/NoSessionPermission/index.ts | 2 +- .../ui/Notification/Notification.js | 34 +- .../app/components/ui/Notification/index.js | 2 +- .../app/components/ui/PageTitle/PageTitle.tsx | 26 +- frontend/app/components/ui/PageTitle/index.ts | 2 +- .../components/ui/Pagination/Pagination.tsx | 24 +- .../app/components/ui/Pagination/index.ts | 2 +- .../app/components/ui/Popover/Popover.tsx | 19 +- .../components/ui/QuestionMarkHint/index.js | 2 +- frontend/app/components/ui/SVG.tsx | 2042 ++++---- .../ui/SegmentSelection/SegmentSelection.tsx | 6 +- .../ui/SideMenuHeader/SideMenuHeader.tsx | 6 +- .../app/components/ui/SideMenuHeader/index.ts | 2 +- .../ui/SideMenuItem/SideMenuItem.tsx | 46 +- .../app/components/ui/SideMenuItem/index.js | 2 +- .../components/ui/SlideModal/SlideModal.js | 32 +- .../ui/SlideModal/SlideModalProvider.js | 4 +- frontend/app/components/ui/Switch.tsx | 4 +- frontend/app/components/ui/Tabs/Tabs.js | 40 +- .../app/components/ui/TagBadge/TagBadge.js | 50 +- .../app/components/ui/TagInput/TagInput.js | 38 +- frontend/app/components/ui/TagList/TagList.js | 43 +- .../ui/TextEllipsis/TextEllipsis.js | 22 +- .../app/components/ui/TextLink/TextLink.js | 16 +- frontend/app/components/ui/TextLink/index.js | 2 +- .../ui/TimelinePointer/TimelinePointer.js | 4 +- .../components/ui/TimelinePointer/index.js | 2 +- .../ui/ToggleButton/ToggleButton.tsx | 129 +- .../app/components/ui/ToggleButton/index.ts | 2 +- frontend/app/components/ui/Tooltip.tsx | 2 +- frontend/app/components/ui/index.js | 4 +- frontend/app/constants/browserIcon.js | 2 +- frontend/app/constants/card.ts | 9 +- frontend/app/constants/countries.js | 267 +- frontend/app/constants/countryShortName.js | 4 +- frontend/app/constants/filterOptions.js | 125 +- frontend/app/constants/index.js | 12 +- frontend/app/constants/links.js | 7 +- frontend/app/constants/platformOptions.js | 2 +- frontend/app/constants/regions.js | 40 +- frontend/app/constants/schedule.js | 25 +- frontend/app/constants/storageKeys.ts | 30 +- frontend/app/date.ts | 87 +- frontend/app/dateRange.js | 87 +- frontend/app/declaration.d.ts | 2 +- .../app/dev/components/CrashReactAppButton.js | 16 +- frontend/app/dev/components/ErrorGenPanel.tsx | 16 +- frontend/app/dev/components/EvalErrorBtn.js | 16 +- .../app/dev/components/EventErrorButton.js | 14 +- .../app/dev/components/InternalErrorButton.js | 18 +- .../app/dev/components/MemoryCrushButton.js | 22 +- .../app/dev/components/PromiseErrorButton.js | 16 +- frontend/app/dev/console.js | 30 +- frontend/app/hooks/useCancelableTimeout.ts | 33 +- frontend/app/hooks/useForceUpdate.ts | 6 +- frontend/app/hooks/useForm.ts | 18 +- frontend/app/hooks/useInputState.ts | 14 +- frontend/app/hooks/useIsMounted.ts | 18 +- frontend/app/hooks/useLatestRef.ts | 11 +- frontend/app/hooks/usePageTitle.js | 8 +- frontend/app/hooks/useToggle.ts | 14 +- frontend/app/i18n.js | 28 + frontend/app/iconNames.js | 76 +- frontend/app/init/immutable.js | 2 +- frontend/app/init/index.js | 2 +- frontend/app/init/sentry.js | 2 +- frontend/app/initialize.js | 18 +- frontend/app/initialize.tsx | 31 +- frontend/app/layout/InitORCard.tsx | 10 +- frontend/app/layout/Layout.tsx | 4 +- frontend/app/layout/SideMenu.tsx | 87 +- .../app/layout/SpotToOpenReplayPrompt.tsx | 52 +- frontend/app/layout/SupportModal.tsx | 8 +- frontend/app/layout/TopHeader.tsx | 11 +- frontend/app/layout/TopRight.tsx | 6 +- frontend/app/layout/data.ts | 60 +- frontend/app/local_storage.js | 16 +- frontend/app/locales/en.json | 4 + frontend/app/locales/fr.json | 4 + frontend/app/logger/index.js | 28 +- frontend/app/mstore/aiFiltersStore.ts | 53 +- frontend/app/mstore/aiSummaryStore.ts | 6 +- frontend/app/mstore/alertsStore.ts | 59 +- frontend/app/mstore/assistMultiviewStore.ts | 16 +- frontend/app/mstore/auditStore.ts | 153 +- frontend/app/mstore/customFieldStore.ts | 25 +- frontend/app/mstore/dashboardStore.ts | 108 +- frontend/app/mstore/errorStore.ts | 5 + frontend/app/mstore/featureFlagsStore.ts | 55 +- frontend/app/mstore/filterStore.ts | 4 +- frontend/app/mstore/funnelStore.ts | 296 +- frontend/app/mstore/index.tsx | 43 +- frontend/app/mstore/integrationsStore.ts | 75 +- frontend/app/mstore/issueReportingStore.ts | 14 +- frontend/app/mstore/loginStore.ts | 28 +- frontend/app/mstore/metricStore.ts | 110 +- frontend/app/mstore/notesStore.ts | 160 +- frontend/app/mstore/notificationStore.ts | 163 +- frontend/app/mstore/projectsStore.ts | 49 +- frontend/app/mstore/recordingsStore.ts | 12 +- frontend/app/mstore/roleStore.ts | 58 +- frontend/app/mstore/searchStore.ts | 59 +- frontend/app/mstore/searchStoreLive.ts | 76 +- frontend/app/mstore/sessionStore.ts | 222 +- frontend/app/mstore/settingsStore.ts | 58 +- frontend/app/mstore/spotStore.ts | 48 +- frontend/app/mstore/tagWatchStore.ts | 3 +- frontend/app/mstore/types/FeatureFlag.ts | 154 +- frontend/app/mstore/types/IconProvider.tsx | 28 +- frontend/app/mstore/types/audit.ts | 77 +- frontend/app/mstore/types/customField.ts | 5 +- frontend/app/mstore/types/dashboard.ts | 338 +- frontend/app/mstore/types/error.ts | 36 +- frontend/app/mstore/types/filter.ts | 50 +- frontend/app/mstore/types/filterItem.ts | 49 +- frontend/app/mstore/types/filterSeries.ts | 75 +- frontend/app/mstore/types/funnel.ts | 81 +- frontend/app/mstore/types/funnelIssue.ts | 144 +- frontend/app/mstore/types/funnelStage.ts | 96 +- frontend/app/mstore/types/funnelnsights.ts | 19 +- frontend/app/mstore/types/gdpr.ts | 24 +- frontend/app/mstore/types/gettingStarted.ts | 14 +- .../app/mstore/types/integrations/consts.ts | 3 +- .../mstore/types/integrations/messengers.ts | 20 +- .../app/mstore/types/integrations/services.ts | 63 +- frontend/app/mstore/types/issue.ts | 5 + frontend/app/mstore/types/moduleSettings.ts | 24 +- frontend/app/mstore/types/notification.ts | 73 +- frontend/app/mstore/types/project.ts | 51 +- frontend/app/mstore/types/role.ts | 17 +- frontend/app/mstore/types/savedSearch.ts | 35 +- frontend/app/mstore/types/search.ts | 47 +- frontend/app/mstore/types/session.ts | 125 +- frontend/app/mstore/types/sessionSettings.ts | 104 +- frontend/app/mstore/types/sessionsCardData.ts | 16 +- frontend/app/mstore/types/spot.ts | 45 +- frontend/app/mstore/types/user.ts | 158 +- frontend/app/mstore/types/widget.ts | 944 ++-- frontend/app/mstore/uiPlayerStore.ts | 42 +- frontend/app/mstore/userStore.ts | 138 +- frontend/app/mstore/uxtestingStore.ts | 45 +- .../app/mstore/weeklyReportConfigStore.ts | 24 +- frontend/app/player-ui/FullScreenButton.tsx | 12 +- frontend/app/player-ui/PlayButton.tsx | 6 +- frontend/app/player-ui/PlayTime.tsx | 38 +- frontend/app/player-ui/ProgressBar.tsx | 16 +- frontend/app/player-ui/ProgressCircle.tsx | 13 +- frontend/app/player-ui/SkipButton.tsx | 11 +- frontend/app/player-ui/index.tsx | 12 +- frontend/app/player/common/ListWalker.ts | 323 +- .../app/player/common/ListWalkerWithMarks.ts | 70 +- frontend/app/player/common/SimpleStore.ts | 19 +- frontend/app/player/common/common.d.ts | 5 +- frontend/app/player/common/tarball.ts | 21 +- frontend/app/player/common/types.ts | 7 +- frontend/app/player/common/unpack.ts | 8 +- frontend/app/player/create.ts | 64 +- frontend/app/player/guards.ts | 4 +- frontend/app/player/index.ts | 11 +- frontend/app/player/mobile/IOSLists.ts | 72 +- .../app/player/mobile/IOSMessageManager.ts | 41 +- frontend/app/player/mobile/IOSPlayer.ts | 34 +- .../managers/IOSPerformanceTrackManager.ts | 12 +- .../player/mobile/managers/SnapshotManager.ts | 33 +- .../player/mobile/managers/TouchManager.ts | 22 +- frontend/app/player/mobile/types/log.ts | 10 +- frontend/app/player/mobile/utils.ts | 25 +- frontend/app/player/player/Animator.ts | 159 +- frontend/app/player/player/Player.ts | 77 +- frontend/app/player/player/_LSCache.ts | 9 +- frontend/app/player/player/localStorage.ts | 25 +- frontend/app/player/web/Lists.ts | 8 +- frontend/app/player/web/MessageLoader.ts | 142 +- frontend/app/player/web/MessageManager.ts | 41 +- frontend/app/player/web/Screen/Cursor.ts | 74 +- frontend/app/player/web/Screen/Inspector.ts | 33 +- frontend/app/player/web/Screen/Marker.ts | 32 +- frontend/app/player/web/Screen/Screen.ts | 25 +- frontend/app/player/web/TabManager.ts | 111 +- frontend/app/player/web/WebLivePlayer.ts | 9 +- frontend/app/player/web/WebPlayer.ts | 208 +- .../player/web/addons/InspectorController.ts | 7 +- frontend/app/player/web/addons/MouseTrail.ts | 34 +- .../app/player/web/addons/TargetMarker.ts | 46 +- .../app/player/web/addons/clickmapStyles.ts | 8 +- .../app/player/web/addons/simpleHeatmap.ts | 14 +- .../app/player/web/assist/AnnotationCanvas.ts | 117 +- .../app/player/web/assist/AssistManager.ts | 99 +- frontend/app/player/web/assist/Call.ts | 40 +- .../app/player/web/assist/CanvasReceiver.ts | 43 +- frontend/app/player/web/assist/LocalStream.ts | 6 +- .../app/player/web/assist/RemoteControl.ts | 17 +- .../app/player/web/assist/ScreenRecording.ts | 93 +- frontend/app/player/web/assist/types.ts | 1 - .../player/web/managers/ActiveTabManager.ts | 16 +- .../player/web/managers/ActivityManager.ts | 45 +- .../app/player/web/managers/CanvasManager.ts | 28 +- .../app/player/web/managers/DOM/DOMManager.ts | 82 +- .../player/web/managers/DOM/FocusManager.ts | 35 +- .../web/managers/DOM/SelectionManager.ts | 26 +- .../player/web/managers/DOM/StylesManager.ts | 31 +- .../app/player/web/managers/DOM/VirtualDOM.ts | 551 ++- .../player/web/managers/DOM/safeCSSRules.ts | 18 +- .../player/web/managers/MouseMoveManager.ts | 90 +- .../app/player/web/managers/PagesManager.ts | 18 +- .../web/managers/PerformanceTrackManager.ts | 192 +- .../player/web/managers/TabClosingManager.ts | 22 +- .../player/web/managers/WindowNodeCounter.ts | 156 +- .../web/messages/JSONRawMessageReader.ts | 49 +- .../app/player/web/messages/MFileReader.ts | 87 +- .../app/player/web/messages/MStreamReader.ts | 34 +- .../player/web/messages/PrimitiveReader.ts | 53 +- frontend/app/player/web/messages/index.ts | 4 +- .../player/web/messages/rewriter/constants.ts | 4 +- .../web/messages/rewriter/rewriteMessage.ts | 52 +- .../web/messages/rewriter/urlResolve.ts | 16 +- frontend/app/player/web/messages/timed.ts | 2 +- .../player/web/messages/tracker-legacy.gen.ts | 4 +- frontend/app/player/web/network/crypto.ts | 32 +- frontend/app/player/web/network/loadFiles.ts | 45 +- frontend/app/player/web/storageSelectors.ts | 58 +- frontend/app/player/web/types/index.ts | 4 +- frontend/app/player/web/types/log.ts | 9 +- frontend/app/player/web/types/resource.ts | 113 +- frontend/app/routes.ts | 60 +- frontend/app/services/AiService.ts | 2 +- frontend/app/services/AlertsService.ts | 38 +- frontend/app/services/AssistStatsService.ts | 18 +- frontend/app/services/AuditService.ts | 36 +- frontend/app/services/BaseService.ts | 16 +- frontend/app/services/ConfigService.ts | 8 +- frontend/app/services/CustomFieldService.ts | 10 +- frontend/app/services/DashboardService.ts | 138 +- frontend/app/services/ErrorService.ts | 6 +- frontend/app/services/FilterService.ts | 2 +- frontend/app/services/FunnelService.ts | 80 +- frontend/app/services/IntegrationsService.ts | 4 +- frontend/app/services/IssueReportsService.ts | 18 +- frontend/app/services/MetricService.ts | 21 +- frontend/app/services/NotesService.ts | 47 +- frontend/app/services/RecordingsService.ts | 30 +- frontend/app/services/SessionService.ts | 19 +- frontend/app/services/TagWatchService.ts | 2 +- frontend/app/services/UserService.ts | 21 +- frontend/app/services/UxtestingService.ts | 13 +- frontend/app/services/WebhookService.ts | 20 +- frontend/app/services/index.ts | 2 +- frontend/app/services/loginService.ts | 2 +- frontend/app/services/spotService.ts | 44 +- frontend/app/theme/colors.js | 88 +- frontend/app/types/Record.js | 32 +- frontend/app/types/account/account.ts | 142 +- frontend/app/types/account/index.js | 2 +- frontend/app/types/account/limit.ts | 1 + frontend/app/types/alert.ts | 158 +- frontend/app/types/app/period.js | 271 +- frontend/app/types/client/client.ts | 5 + frontend/app/types/customField.js | 39 +- frontend/app/types/customMetric.js | 143 +- frontend/app/types/dashboard/helper.ts | 22 +- frontend/app/types/errorInfo.js | 72 +- frontend/app/types/filter/customFilter.js | 74 +- frontend/app/types/filter/event.js | 67 +- frontend/app/types/filter/filter.js | 180 +- frontend/app/types/filter/filterType.ts | 4 +- frontend/app/types/filter/index.js | 157 +- frontend/app/types/filter/newFilter.js | 544 +- frontend/app/types/filter/savedFilter.js | 60 +- frontend/app/types/funnel.js | 160 +- frontend/app/types/funnelIssue.js | 97 +- .../app/types/integrations/bugsnagConfig.js | 41 +- .../types/integrations/cloudwatchConfig.js | 87 +- .../app/types/integrations/datadogConfig.js | 39 +- .../types/integrations/elasticsearchConfig.js | 68 +- .../app/types/integrations/githubConfig.js | 76 +- .../app/types/integrations/issueTracker.js | 49 +- frontend/app/types/integrations/jiraConfig.js | 88 +- .../app/types/integrations/newrelicConfig.js | 41 +- .../app/types/integrations/rollbarConfig.js | 37 +- .../app/types/integrations/sentryConfig.js | 45 +- .../app/types/integrations/slackConfig.js | 51 +- .../types/integrations/stackdriverConfig.js | 39 +- .../app/types/integrations/sumoLogicConfig.js | 61 +- frontend/app/types/member.ts | 63 +- frontend/app/types/notification.js | 38 +- frontend/app/types/resource.js | 10 +- frontend/app/types/session/activity.ts | 27 +- frontend/app/types/session/assignment.ts | 27 +- frontend/app/types/session/error.ts | 35 +- frontend/app/types/session/errorStack.ts | 24 +- frontend/app/types/session/event.ts | 88 +- frontend/app/types/session/index.js | 2 +- frontend/app/types/session/issue.ts | 82 +- frontend/app/types/session/session.ts | 168 +- frontend/app/types/session/stackEvent.ts | 23 +- frontend/app/types/site/gdpr.ts | 6 +- frontend/app/types/site/index.js | 2 +- frontend/app/types/site/site.ts | 7 +- frontend/app/types/template.js | 29 +- frontend/app/types/variable.js | 23 +- frontend/app/types/watchdog.js | 146 +- frontend/app/types/webhook.ts | 24 +- frontend/app/utils/index.ts | 161 +- frontend/app/utils/screenRecorder.ts | 13 +- frontend/app/utils/search.ts | 38 +- frontend/app/validate.js | 27 +- frontend/eslint.config.js | 82 + frontend/package.json | 31 +- frontend/tsconfig.json | 2 +- frontend/yarn.lock | 4370 ++++++++++------- 2008 files changed, 40866 insertions(+), 33681 deletions(-) create mode 100644 frontend/app/components/LanguageSwitcher/LanguageSwitcher.tsx create mode 100644 frontend/app/components/LanguageSwitcher/index.ts create mode 100644 frontend/app/i18n.js create mode 100644 frontend/app/locales/en.json create mode 100644 frontend/app/locales/fr.json create mode 100644 frontend/eslint.config.js diff --git a/frontend/app/AdditionalRoutes.tsx b/frontend/app/AdditionalRoutes.tsx index db93ff9c5..e6f992916 100644 --- a/frontend/app/AdditionalRoutes.tsx +++ b/frontend/app/AdditionalRoutes.tsx @@ -5,13 +5,11 @@ interface Props { redirect: string; } -const AdditionalRoutes = (props: Props) => { +function AdditionalRoutes(props: Props) { const { redirect } = props; return ( - <> - - + ); -}; +} export default AdditionalRoutes; diff --git a/frontend/app/IFrameRoutes.tsx b/frontend/app/IFrameRoutes.tsx index 8bfe3522b..434a6af56 100644 --- a/frontend/app/IFrameRoutes.tsx +++ b/frontend/app/IFrameRoutes.tsx @@ -3,31 +3,29 @@ import { Switch, Route } from 'react-router-dom'; import { Loader } from 'UI'; import withSiteIdUpdater from 'HOCs/withSiteIdUpdater'; -import * as routes from './routes'; import NotFoundPage from 'Shared/NotFoundPage'; import { ModalProvider } from 'Components/Modal'; import Layout from 'App/layout/Layout'; import PublicRoutes from 'App/PublicRoutes'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; +import * as routes from './routes'; const components: any = { SessionPure: lazy(() => import('Components/Session/Session')), - LiveSessionPure: lazy(() => import('Components/Session/LiveSession')) + LiveSessionPure: lazy(() => import('Components/Session/LiveSession')), }; - const enhancedComponents: any = { Session: withSiteIdUpdater(components.SessionPure), - LiveSession: withSiteIdUpdater(components.LiveSessionPure) + LiveSession: withSiteIdUpdater(components.LiveSessionPure), }; -const withSiteId = routes.withSiteId; +const { withSiteId } = routes; const SESSION_PATH = routes.session(); const LIVE_SESSION_PATH = routes.liveSession(); - interface Props { isJwt?: boolean; isLoggedIn?: boolean; @@ -43,15 +41,23 @@ function IFrameRoutes(props: Props) { if (isLoggedIn) { return ( - - - }> - - - - + + + }> + + + + @@ -67,5 +73,4 @@ function IFrameRoutes(props: Props) { return ; } - export default observer(IFrameRoutes); diff --git a/frontend/app/PrivateRoutes.tsx b/frontend/app/PrivateRoutes.tsx index b9d2cb247..7ae942e07 100644 --- a/frontend/app/PrivateRoutes.tsx +++ b/frontend/app/PrivateRoutes.tsx @@ -1,11 +1,11 @@ import withSiteIdUpdater from 'HOCs/withSiteIdUpdater'; import React, { Suspense, lazy } from 'react'; import { Redirect, Route, Switch } from 'react-router-dom'; -import { observer } from 'mobx-react-lite' -import { useStore } from "./mstore"; +import { observer } from 'mobx-react-lite'; import { GLOBAL_HAS_NO_RECORDINGS } from 'App/constants/storageKeys'; import { OB_DEFAULT_TAB } from 'App/routes'; import { Loader } from 'UI'; +import { useStore } from './mstore'; import APIClient from './api_client'; import * as routes from './routes'; @@ -20,13 +20,13 @@ const components: any = { DashboardPure: lazy(() => import('Components/Dashboard/NewDashboard')), MultiviewPure: lazy(() => import('Components/Session_/Multiview/Multiview')), UsabilityTestingPure: lazy( - () => import('Components/UsabilityTesting/UsabilityTesting') + () => import('Components/UsabilityTesting/UsabilityTesting'), ), UsabilityTestEditPure: lazy( - () => import('Components/UsabilityTesting/TestEdit') + () => import('Components/UsabilityTesting/TestEdit'), ), UsabilityTestOverviewPure: lazy( - () => import('Components/UsabilityTesting/TestOverview') + () => import('Components/UsabilityTesting/TestOverview'), ), SpotsListPure: lazy(() => import('Components/Spots/SpotsList')), SpotPure: lazy(() => import('Components/Spots/SpotPlayer')), @@ -46,7 +46,7 @@ const enhancedComponents: any = { UsabilityTesting: withSiteIdUpdater(components.UsabilityTestingPure), UsabilityTestEdit: withSiteIdUpdater(components.UsabilityTestEditPure), UsabilityTestOverview: withSiteIdUpdater( - components.UsabilityTestOverviewPure + components.UsabilityTestOverviewPure, ), SpotsList: withSiteIdUpdater(components.SpotsListPure), Spot: components.SpotPure, @@ -54,7 +54,7 @@ const enhancedComponents: any = { Highlights: withSiteIdUpdater(components.HighlightsPure), }; -const withSiteId = routes.withSiteId; +const { withSiteId } = routes; const METRICS_PATH = routes.metrics(); const METRICS_DETAILS = routes.metricDetails(); @@ -100,25 +100,24 @@ const HIGHLIGHTS_PATH = routes.highlights(); function PrivateRoutes() { const { projectsStore, userStore, integrationsStore } = useStore(); - const onboarding = userStore.onboarding; + const { onboarding } = userStore; const scope = userStore.scopeState; - const tenantId = userStore.account.tenantId; + const { tenantId } = userStore.account; const sites = projectsStore.list; - const siteId = projectsStore.siteId; - const hasRecordings = sites.some(s => s.recorded); + const { siteId } = projectsStore; + const hasRecordings = sites.some((s) => s.recorded); const redirectToSetup = scope === 0; - const redirectToOnboarding = - !onboarding && (localStorage.getItem(GLOBAL_HAS_NO_RECORDINGS) === 'true' || (sites.length > 0 && !hasRecordings)) && scope > 0; + const redirectToOnboarding = !onboarding && (localStorage.getItem(GLOBAL_HAS_NO_RECORDINGS) === 'true' || (sites.length > 0 && !hasRecordings)) && scope > 0; const siteIdList: any = sites.map(({ id }) => id); React.useEffect(() => { if (siteId && integrationsStore.integrations.siteId !== siteId) { - integrationsStore.integrations.setSiteId(siteId) + integrationsStore.integrations.setSiteId(siteId); void integrationsStore.integrations.fetchIntegrations(siteId); } - }, [siteId]) + }, [siteId]); return ( - }> + }> ( ))} - + diff --git a/frontend/app/PublicRoutes.tsx b/frontend/app/PublicRoutes.tsx index 1e1cee516..94af9fcea 100644 --- a/frontend/app/PublicRoutes.tsx +++ b/frontend/app/PublicRoutes.tsx @@ -7,7 +7,6 @@ import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import * as routes from 'App/routes'; - const LOGIN_PATH = routes.login(); const SIGNUP_PATH = routes.signup(); const FORGOT_PASSWORD = routes.forgotPassword(); @@ -19,8 +18,8 @@ const Spot = lazy(() => import('Components/Spots/SpotPlayer/SpotPlayer')); function PublicRoutes() { const { userStore } = useStore(); - const authDetails = userStore.authStore.authDetails; - const isEnterprise = userStore.isEnterprise; + const { authDetails } = userStore.authStore; + const { isEnterprise } = userStore; const hideSupport = isEnterprise || location.pathname.includes('spots') || location.pathname.includes('view-spot'); const [loading, setLoading] = React.useState(true); @@ -34,7 +33,7 @@ function PublicRoutes() { return ( - }> + }> @@ -48,5 +47,4 @@ function PublicRoutes() { ); } - export default observer(PublicRoutes); diff --git a/frontend/app/Router.tsx b/frontend/app/Router.tsx index 000a6d6d5..76eb55ae9 100644 --- a/frontend/app/Router.tsx +++ b/frontend/app/Router.tsx @@ -8,7 +8,7 @@ import { GLOBAL_DESTINATION_PATH, IFRAME, JWT_PARAM, - SPOT_ONBOARDING + SPOT_ONBOARDING, } from 'App/constants/storageKeys'; import Layout from 'App/layout/Layout'; import { useStore } from 'App/mstore'; @@ -16,8 +16,8 @@ import { checkParam, handleSpotJWT, isTokenExpired } from 'App/utils'; import { ModalProvider } from 'Components/Modal'; import { ModalProvider as NewModalProvider } from 'Components/ModalContext'; import { Loader } from 'UI'; +import { observer } from 'mobx-react-lite'; import * as routes from './routes'; -import { observer } from 'mobx-react-lite' interface RouterProps extends RouteComponentProps { match: { @@ -33,20 +33,22 @@ const Router: React.FC = (props) => { history, } = props; const mstore = useStore(); - const { customFieldStore, projectsStore, sessionStore, searchStore, userStore } = mstore; - const jwt = userStore.jwt; - const changePassword = userStore.account.changePassword; + const { + customFieldStore, projectsStore, sessionStore, searchStore, userStore, + } = mstore; + const { jwt } = userStore; + const { changePassword } = userStore.account; const userInfoLoading = userStore.fetchInfoRequest.loading; const scopeSetup = userStore.scopeState === 0; const localSpotJwt = userStore.spotJwt; const isLoggedIn = Boolean(jwt && !changePassword); - const fetchUserInfo = userStore.fetchUserInfo; + const { fetchUserInfo } = userStore; const setJwt = userStore.updateJwt; - const logout = userStore.logout; + const { logout } = userStore; - const setSessionPath = sessionStore.setSessionPath; - const siteId = projectsStore.siteId; - const sitesLoading = projectsStore.sitesLoading; + const { setSessionPath } = sessionStore; + const { siteId } = projectsStore; + const { sitesLoading } = projectsStore; const sites = projectsStore.list; const loading = Boolean(userInfoLoading || (!scopeSetup && !siteId) || sitesLoading); const initSite = projectsStore.initProject; @@ -75,10 +77,10 @@ const Router: React.FC = (props) => { const handleSpotLogin = (jwt: string) => { if (spotReqSent.current) { return; - } else { - spotReqSent.current = true; - setIsSpotCb(false); } + spotReqSent.current = true; + setIsSpotCb(false); + handleSpotJWT(jwt); }; @@ -86,7 +88,7 @@ const Router: React.FC = (props) => { if (!isLoggedIn && location.pathname !== routes.login()) { localStorage.setItem( GLOBAL_DESTINATION_PATH, - location.pathname + location.search + location.pathname + location.search, ); } }; @@ -106,10 +108,10 @@ const Router: React.FC = (props) => { const destinationPath = localStorage.getItem(GLOBAL_DESTINATION_PATH); if ( - destinationPath && - !destinationPath.includes(routes.login()) && - !destinationPath.includes(routes.signup()) && - destinationPath !== '/' + destinationPath + && !destinationPath.includes(routes.login()) + && !destinationPath.includes(routes.signup()) + && destinationPath !== '/' ) { const url = new URL(destinationPath, window.location.origin); checkParams(url.search); @@ -143,7 +145,7 @@ const Router: React.FC = (props) => { useEffect(() => { handleDestinationPath(); - setSessionPath(previousLocation ? previousLocation : location); + setSessionPath(previousLocation || location); }, [location]); useEffect(() => { @@ -163,14 +165,14 @@ const Router: React.FC = (props) => { }, [isSpotCb, isLoggedIn, localSpotJwt, isSignup]); useEffect(() => { - if (!isLoggedIn) return + if (!isLoggedIn) return; const fetchData = async () => { if (siteId && siteId !== lastFetchedSiteIdRef.current) { const activeSite = sites.find((s) => s.id == siteId); initSite(activeSite ?? {}); lastFetchedSiteIdRef.current = activeSite?.id; - await customFieldStore.fetchListActive(siteId + ''); - await searchStore.fetchSavedSearchList() + await customFieldStore.fetchListActive(`${siteId}`); + await searchStore.fetchSavedSearchList(); } }; @@ -190,13 +192,12 @@ const Router: React.FC = (props) => { const prevIsLoggedIn = usePrevious(isLoggedIn); const previousLocation = usePrevious(location); - const hideHeader = - (location.pathname && location.pathname.includes('/session/')) || - location.pathname.includes('/assist/') || - location.pathname.includes('multiview') || - location.pathname.includes('/view-spot/') || - location.pathname.includes('/spots/') || - location.pathname.includes('/scope-setup'); + const hideHeader = (location.pathname && location.pathname.includes('/session/')) + || location.pathname.includes('/assist/') + || location.pathname.includes('multiview') + || location.pathname.includes('/view-spot/') + || location.pathname.includes('/spots/') + || location.pathname.includes('/scope-setup'); if (isIframe) { return ( diff --git a/frontend/app/api_client.ts b/frontend/app/api_client.ts index f9343ed88..62c73ac83 100644 --- a/frontend/app/api_client.ts +++ b/frontend/app/api_client.ts @@ -30,7 +30,7 @@ const siteIdRequiredPaths: string[] = [ '/check-recording-status', '/usability-tests', '/tags', - '/intelligent' + '/intelligent', ]; export const clean = (obj: any, forbiddenValues: any[] = [undefined, '']): any => { @@ -38,7 +38,7 @@ export const clean = (obj: any, forbiddenValues: any[] = [undefined, '']): any = ? new Array(obj.length).fill().map((_, i) => i) : Object.keys(obj); const retObj = Array.isArray(obj) ? [] : {}; - keys.map(key => { + keys.map((key) => { const value = obj[key]; if (typeof value === 'object' && value !== null) { retObj[key] = clean(value); @@ -52,18 +52,23 @@ export const clean = (obj: any, forbiddenValues: any[] = [undefined, '']): any = export default class APIClient { private init: RequestInit; + private siteId: string | undefined; + private siteIdCheck: (() => { siteId: string | null }) | undefined; + private getJwt: () => string | null = () => null; + private onUpdateJwt: (data: { jwt?: string, spotJwt?: string }) => void; + private refreshingTokenPromise: Promise | null = null; constructor() { this.init = { headers: new Headers({ Accept: 'application/json', - 'Content-Type': 'application/json' - }) + 'Content-Type': 'application/json', + }), }; } @@ -82,14 +87,14 @@ export default class APIClient { } setSiteIdCheck(checker: () => { siteId: string | null }): void { - this.siteIdCheck = checker + this.siteIdCheck = checker; } private getInit(method: string = 'GET', params?: any, reqHeaders?: Record): RequestInit { // Always fetch the latest JWT from the store - const jwt = this.getJwt() + const jwt = this.getJwt(); const headers = new Headers({ - 'Accept': 'application/json', + Accept: 'application/json', 'Content-Type': 'application/json', }); @@ -148,7 +153,7 @@ export default class APIClient { params?: any, method: string = 'GET', options: { clean?: boolean } = { clean: true }, - headers?: Record + headers?: Record, ): Promise { let _path = path; let jwt = this.getJwt(); @@ -167,21 +172,21 @@ export default class APIClient { delete init.body; } - const noChalice = path.includes('v1/integrations') || path.includes('/spot') && !path.includes('/login') - let edp = window.env.API_EDP || window.location.origin + '/api'; + const noChalice = path.includes('v1/integrations') || path.includes('/spot') && !path.includes('/login'); + let edp = window.env.API_EDP || `${window.location.origin}/api`; if (noChalice && !edp.includes('api.openreplay.com')) { - edp = edp.replace('/api', '') + edp = edp.replace('/api', ''); } if ( - path !== '/targets_temp' && - !path.includes('/metadata/session_search') && - !path.includes('/assist/credentials') && - siteIdRequiredPaths.some((sidPath) => path.startsWith(sidPath)) + path !== '/targets_temp' + && !path.includes('/metadata/session_search') + && !path.includes('/assist/credentials') + && siteIdRequiredPaths.some((sidPath) => path.startsWith(sidPath)) ) { edp = `${edp}/${this.siteId ?? ''}`; } if (path.includes('PROJECT_ID')) { - _path = _path.replace('PROJECT_ID', this.siteId + ''); + _path = _path.replace('PROJECT_ID', `${this.siteId}`); } const fullUrl = edp + _path; @@ -193,7 +198,7 @@ export default class APIClient { if (response.ok) { return response; } - let errorMsg = `Something went wrong.`; + let errorMsg = 'Something went wrong.'; try { const errorData = await response.json(); errorMsg = errorData.errors?.[0] || errorMsg; @@ -204,7 +209,7 @@ export default class APIClient { async refreshToken(): Promise { try { const response = await this.fetch('/refresh', { - headers: this.init.headers + headers: this.init.headers, }, 'GET', { clean: false }); if (!response.ok) { @@ -249,5 +254,5 @@ export default class APIClient { forceSiteId = (siteId: string) => { this.siteId = siteId; - } + }; } diff --git a/frontend/app/assets/prism/prism-bash.min.js b/frontend/app/assets/prism/prism-bash.min.js index f1659f1e3..dba1edeee 100644 --- a/frontend/app/assets/prism/prism-bash.min.js +++ b/frontend/app/assets/prism/prism-bash.min.js @@ -1 +1,167 @@ -!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/, + punctuation: /\(\(?|\)\)?|,|;/, + }, + }, + { + pattern: /\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/, + greedy: !0, + inside: { variable: /^\$\(|^`|\)$|`$/ }, + }, + { + pattern: /\$\{[^}]+\}/, + greedy: !0, + inside: { + operator: /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/, + punctuation: /[\[\]]/, + environment: { + pattern: RegExp(`(\\{)${t}`), + lookbehind: !0, + alias: 'constant', + }, + }, + }, + /\$(?:\w+|[#?*!@$])/, + ], + entity: + /\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/, + }; + (e.languages.bash = { + shebang: { pattern: /^#!\s*\/.*/, alias: 'important' }, + comment: { pattern: /(^|[^"{\\$])#.*/, lookbehind: !0 }, + 'function-name': [ + { + pattern: /(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/, + lookbehind: !0, + alias: 'function', + }, + { pattern: /\b[\w-]+(?=\s*\(\s*\)\s*\{)/, alias: 'function' }, + ], + 'for-or-select': { + pattern: /(\b(?:for|select)\s+)\w+(?=\s+in\s)/, + alias: 'variable', + lookbehind: !0, + }, + 'assign-left': { + pattern: /(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/, + inside: { + environment: { + pattern: RegExp(`(^|[\\s;|&]|[<>]\\()${t}`), + lookbehind: !0, + alias: 'constant', + }, + }, + alias: 'variable', + lookbehind: !0, + }, + parameter: { + pattern: /(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/, + alias: 'variable', + lookbehind: !0, + }, + string: [ + { + pattern: /((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/, + lookbehind: !0, + greedy: !0, + inside: n, + }, + { + pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/, + lookbehind: !0, + greedy: !0, + inside: { bash: a }, + }, + { + pattern: + /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/, + lookbehind: !0, + greedy: !0, + inside: n, + }, + { pattern: /(^|[^$\\])'[^']*'/, lookbehind: !0, greedy: !0 }, + { + pattern: /\$'(?:[^'\\]|\\[\s\S])*'/, + greedy: !0, + inside: { entity: n.entity }, + }, + ], + environment: { pattern: RegExp(`\\$?${t}`), alias: 'constant' }, + variable: n.variable, + function: { + pattern: + /(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/, + lookbehind: !0, + }, + keyword: { + pattern: + /(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/, + lookbehind: !0, + }, + builtin: { + pattern: + /(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/, + lookbehind: !0, + alias: 'class-name', + }, + boolean: { + pattern: /(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/, + lookbehind: !0, + }, + 'file-descriptor': { pattern: /\B&\d\b/, alias: 'important' }, + operator: { + pattern: + /\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/, + inside: { 'file-descriptor': { pattern: /^\d/, alias: 'important' } }, + }, + punctuation: /\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/, + number: { pattern: /(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/, lookbehind: !0 }, + }), + (a.inside = e.languages.bash); + for ( + let s = [ + 'comment', + 'function-name', + 'for-or-select', + 'assign-left', + 'parameter', + 'string', + 'environment', + 'function', + 'keyword', + 'builtin', + 'boolean', + 'file-descriptor', + 'operator', + 'punctuation', + 'number', + ], + o = n.variable[1].inside, + i = 0; + i < s.length; + i++ + ) o[s[i]] = e.languages.bash[s[i]]; + (e.languages.sh = e.languages.bash), (e.languages.shell = e.languages.bash); +}(Prism)); diff --git a/frontend/app/assets/prism/prism-javascript.min.js b/frontend/app/assets/prism/prism-javascript.min.js index 22292c41f..cef56244b 100644 --- a/frontend/app/assets/prism/prism-javascript.min.js +++ b/frontend/app/assets/prism/prism-javascript.min.js @@ -1 +1,126 @@ -Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; \ No newline at end of file +(Prism.languages.javascript = Prism.languages.extend('clike', { + 'class-name': [ + Prism.languages.clike['class-name'], + { + pattern: + /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/, + lookbehind: !0, + }, + ], + keyword: [ + { pattern: /((?:^|\})\s*)catch\b/, lookbehind: !0 }, + { + pattern: + /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/, + lookbehind: !0, + }, + ], + function: + /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/, + number: { + pattern: RegExp( + '(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])', + ), + lookbehind: !0, + }, + operator: + /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/, +})), +(Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/), +Prism.languages.insertBefore('javascript', 'keyword', { + regex: { + pattern: RegExp( + '((?:^|[^$\\w\\xA0-\\uFFFF."\'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))', + ), + lookbehind: !0, + greedy: !0, + inside: { + 'regex-source': { + pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/, + lookbehind: !0, + alias: 'language-regex', + inside: Prism.languages.regex, + }, + 'regex-delimiter': /^\/|\/$/, + 'regex-flags': /^[a-z]+$/, + }, + }, + 'function-variable': { + pattern: + /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/, + alias: 'function', + }, + parameter: [ + { + pattern: + /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + { + pattern: + /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + { + pattern: + /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + { + pattern: + /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + ], + constant: /\b[A-Z](?:[A-Z_]|\dx?)*\b/, +}), +Prism.languages.insertBefore('javascript', 'string', { + hashbang: { pattern: /^#!.*/, greedy: !0, alias: 'comment' }, + 'template-string': { + pattern: + /`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/, + greedy: !0, + inside: { + 'template-punctuation': { pattern: /^`|`$/, alias: 'string' }, + interpolation: { + pattern: + /((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/, + lookbehind: !0, + inside: { + 'interpolation-punctuation': { + pattern: /^\$\{|\}$/, + alias: 'punctuation', + }, + rest: Prism.languages.javascript, + }, + }, + string: /[\s\S]+/, + }, + }, + 'string-property': { + pattern: + /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m, + lookbehind: !0, + greedy: !0, + alias: 'property', + }, +}), +Prism.languages.insertBefore('javascript', 'operator', { + 'literal-property': { + pattern: + /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m, + lookbehind: !0, + alias: 'property', + }, +}), +Prism.languages.markup + && (Prism.languages.markup.tag.addInlined('script', 'javascript'), + Prism.languages.markup.tag.addAttribute( + 'on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)', + 'javascript', + )), +(Prism.languages.js = Prism.languages.javascript); diff --git a/frontend/app/assets/prism/prism-jsx.min.js b/frontend/app/assets/prism/prism-jsx.min.js index 8aa6362fa..a1e99d3d9 100644 --- a/frontend/app/assets/prism/prism-jsx.min.js +++ b/frontend/app/assets/prism/prism-jsx.min.js @@ -1 +1,95 @@ -!function(t){var n=t.util.clone(t.languages.javascript),e="(?:\\{*\\.{3}(?:[^{}]|)*\\})";function a(t,n){return t=t.replace(//g,(function(){return"(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)"})).replace(//g,(function(){return"(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})"})).replace(//g,(function(){return e})),RegExp(t,n)}e=a(e).source,t.languages.jsx=t.languages.extend("markup",n),t.languages.jsx.tag.pattern=a("+(?:[\\w.:$-]+(?:=(?:\"(?:\\\\[^]|[^\\\\\"])*\"|'(?:\\\\[^]|[^\\\\'])*'|[^\\s{'\"/>=]+|))?|))**/?)?>"),t.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,t.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,t.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,t.languages.jsx.tag.inside.comment=n.comment,t.languages.insertBefore("inside","attr-name",{spread:{pattern:a(""),inside:t.languages.jsx}},t.languages.jsx.tag),t.languages.insertBefore("inside","special-attr",{script:{pattern:a("="),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:t.languages.jsx}}},t.languages.jsx.tag);var s=function(t){return t?"string"==typeof t?t:"string"==typeof t.content?t.content:t.content.map(s).join(""):""},g=function(n){for(var e=[],a=0;a0&&e[e.length-1].tagName===s(o.content[0].content[1])&&e.pop():"/>"===o.content[o.content.length-1].content||e.push({tagName:s(o.content[0].content[1]),openedBraces:0}):e.length>0&&"punctuation"===o.type&&"{"===o.content?e[e.length-1].openedBraces++:e.length>0&&e[e.length-1].openedBraces>0&&"punctuation"===o.type&&"}"===o.content?e[e.length-1].openedBraces--:i=!0),(i||"string"==typeof o)&&e.length>0&&0===e[e.length-1].openedBraces){var r=s(o);a0&&("string"==typeof n[a-1]||"plain-text"===n[a-1].type)&&(r=s(n[a-1])+r,n.splice(a-1,1),a--),n[a]=new t.Token("plain-text",r,null,r)}o.content&&"string"!=typeof o.content&&g(o.content)}};t.hooks.add("after-tokenize",(function(t){"jsx"!==t.language&&"tsx"!==t.language||g(t.tokens)}))}(Prism); \ No newline at end of file +!(function (t) { + const n = t.util.clone(t.languages.javascript); + let e = '(?:\\{*\\.{3}(?:[^{}]|)*\\})'; + function a(t, n) { + return ( + (t = t + .replace(//g, () => '(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)') + .replace(//g, () => '(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})') + .replace(//g, () => e)), + RegExp(t, n) + ); + } + (e = a(e).source), + (t.languages.jsx = t.languages.extend('markup', n)), + (t.languages.jsx.tag.pattern = a( + '+(?:[\\w.:$-]+(?:=(?:"(?:\\\\[^]|[^\\\\"])*"|\'(?:\\\\[^]|[^\\\\\'])*\'|[^\\s{\'"/>=]+|))?|))**/?)?>', + )), + (t.languages.jsx.tag.inside.tag.pattern = /^<\/?[^\s>\/]*/), + (t.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/), + (t.languages.jsx.tag.inside.tag.inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/), + (t.languages.jsx.tag.inside.comment = n.comment), + t.languages.insertBefore( + 'inside', + 'attr-name', + { spread: { pattern: a(''), inside: t.languages.jsx } }, + t.languages.jsx.tag, + ), + t.languages.insertBefore( + 'inside', + 'special-attr', + { + script: { + pattern: a('='), + alias: 'language-javascript', + inside: { + 'script-punctuation': { pattern: /^=(?=\{)/, alias: 'punctuation' }, + rest: t.languages.jsx, + }, + }, + }, + t.languages.jsx.tag, + ); + const s = function (t) { + return t + ? typeof t === 'string' + ? t + : typeof t.content === 'string' + ? t.content + : t.content.map(s).join('') + : ''; + }; + const g = function (n) { + for (let e = [], a = 0; a < n.length; a++) { + const o = n[a]; + let i = !1; + if ( + (typeof o !== 'string' + && (o.type === 'tag' && o.content[0] && o.content[0].type === 'tag' + ? o.content[0].content[0].content === ' 0 + && e[e.length - 1].tagName === s(o.content[0].content[1]) + && e.pop() + : o.content[o.content.length - 1].content === '/>' + || e.push({ + tagName: s(o.content[0].content[1]), + openedBraces: 0, + }) + : e.length > 0 && o.type === 'punctuation' && o.content === '{' + ? e[e.length - 1].openedBraces++ + : e.length > 0 + && e[e.length - 1].openedBraces > 0 + && o.type === 'punctuation' + && o.content === '}' + ? e[e.length - 1].openedBraces-- + : (i = !0)), + (i || typeof o === 'string') + && e.length > 0 + && e[e.length - 1].openedBraces === 0) + ) { + let r = s(o); + a < n.length - 1 + && (typeof n[a + 1] === 'string' || n[a + 1].type === 'plain-text') + && ((r += s(n[a + 1])), n.splice(a + 1, 1)), + a > 0 + && (typeof n[a - 1] === 'string' || n[a - 1].type === 'plain-text') + && ((r = s(n[a - 1]) + r), n.splice(a - 1, 1), a--), + (n[a] = new t.Token('plain-text', r, null, r)); + } + o.content && typeof o.content !== 'string' && g(o.content); + } + }; + t.hooks.add('after-tokenize', (t) => { + (t.language !== 'jsx' && t.language !== 'tsx') || g(t.tokens); + }); +}(Prism)); diff --git a/frontend/app/assets/prism/prism-kotlin.min.js b/frontend/app/assets/prism/prism-kotlin.min.js index 78a905718..b32bbd969 100644 --- a/frontend/app/assets/prism/prism-kotlin.min.js +++ b/frontend/app/assets/prism/prism-kotlin.min.js @@ -1 +1,66 @@ -!function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var e={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:e},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:e},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin}(Prism); \ No newline at end of file +!(function (n) { + (n.languages.kotlin = n.languages.extend('clike', { + keyword: { + pattern: + /(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/, + lookbehind: !0, + }, + function: [ + { pattern: /(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/, greedy: !0 }, + { + pattern: /(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/, + lookbehind: !0, + greedy: !0, + }, + ], + number: + /\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/, + operator: + /\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/, + })), + delete n.languages.kotlin['class-name']; + const e = { + 'interpolation-punctuation': { + pattern: /^\$\{?|\}$/, + alias: 'punctuation', + }, + expression: { pattern: /[\s\S]+/, inside: n.languages.kotlin }, + }; + n.languages.insertBefore('kotlin', 'string', { + 'string-literal': [ + { + pattern: /"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/, + alias: 'multiline', + inside: { + interpolation: { pattern: /\$(?:[a-z_]\w*|\{[^{}]*\})/i, inside: e }, + string: /[\s\S]+/, + }, + }, + { + pattern: /"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/, + alias: 'singleline', + inside: { + interpolation: { + pattern: /((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i, + lookbehind: !0, + inside: e, + }, + string: /[\s\S]+/, + }, + }, + ], + char: { pattern: /'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/, greedy: !0 }, + }), + delete n.languages.kotlin.string, + n.languages.insertBefore('kotlin', 'keyword', { + annotation: { + pattern: /\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/, + alias: 'builtin', + }, + }), + n.languages.insertBefore('kotlin', 'function', { + label: { pattern: /\b\w+@|@\w+\b/, alias: 'symbol' }, + }), + (n.languages.kt = n.languages.kotlin), + (n.languages.kts = n.languages.kotlin); +}(Prism)); diff --git a/frontend/app/assets/prism/prism-swift.min.js b/frontend/app/assets/prism/prism-swift.min.js index b4f87f463..058060b27 100644 --- a/frontend/app/assets/prism/prism-swift.min.js +++ b/frontend/app/assets/prism/prism-swift.min.js @@ -1 +1,96 @@ -Prism.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp('(^|[^"#])(?:"(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^(])|[^\\\\\r\n"])*"|"""(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|[^(])|[^\\\\"]|"(?!""))*""")(?!["#])'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp('(^|[^"#])(#+)(?:"(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^#])|[^\\\\\r\n])*?"|"""(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|[^#])|[^\\\\])*?""")\\2'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp("#(?:(?:elseif|if)\\b(?:[ \t]*(?:![ \t]*)?(?:\\b\\w+\\b(?:[ \t]*\\((?:[^()]|\\([^()]*\\))*\\))?|\\((?:[^()]|\\([^()]*\\))*\\))(?:[ \t]*(?:&&|\\|\\|))?)+|(?:else|endif)\\b)"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},Prism.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=Prism.languages.swift})); \ No newline at end of file +(Prism.languages.swift = { + comment: { + pattern: + /(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/, + lookbehind: !0, + greedy: !0, + }, + 'string-literal': [ + { + pattern: RegExp( + '(^|[^"#])(?:"(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^(])|[^\\\\\r\n"])*"|"""(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|[^(])|[^\\\\"]|"(?!""))*""")(?!["#])', + ), + lookbehind: !0, + greedy: !0, + inside: { + interpolation: { + pattern: /(\\\()(?:[^()]|\([^()]*\))*(?=\))/, + lookbehind: !0, + inside: null, + }, + 'interpolation-punctuation': { + pattern: /^\)|\\\($/, + alias: 'punctuation', + }, + punctuation: /\\(?=[\r\n])/, + string: /[\s\S]+/, + }, + }, + { + pattern: RegExp( + '(^|[^"#])(#+)(?:"(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^#])|[^\\\\\r\n])*?"|"""(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|[^#])|[^\\\\])*?""")\\2', + ), + lookbehind: !0, + greedy: !0, + inside: { + interpolation: { + pattern: /(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/, + lookbehind: !0, + inside: null, + }, + 'interpolation-punctuation': { + pattern: /^\)|\\#+\($/, + alias: 'punctuation', + }, + string: /[\s\S]+/, + }, + }, + ], + directive: { + pattern: RegExp( + '#(?:(?:elseif|if)\\b(?:[ \t]*(?:![ \t]*)?(?:\\b\\w+\\b(?:[ \t]*\\((?:[^()]|\\([^()]*\\))*\\))?|\\((?:[^()]|\\([^()]*\\))*\\))(?:[ \t]*(?:&&|\\|\\|))?)+|(?:else|endif)\\b)', + ), + alias: 'property', + inside: { + 'directive-name': /^#\w+/, + boolean: /\b(?:false|true)\b/, + number: /\b\d+(?:\.\d+)*\b/, + operator: /!|&&|\|\||[<>]=?/, + punctuation: /[(),]/, + }, + }, + literal: { + pattern: + /#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/, + alias: 'constant', + }, + 'other-directive': { pattern: /#\w+\b/, alias: 'property' }, + attribute: { pattern: /@\w+/, alias: 'atrule' }, + 'function-definition': { + pattern: /(\bfunc\s+)\w+/, + lookbehind: !0, + alias: 'function', + }, + label: { + pattern: + /\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/, + lookbehind: !0, + alias: 'important', + }, + keyword: + /\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/, + boolean: /\b(?:false|true)\b/, + nil: { pattern: /\bnil\b/, alias: 'constant' }, + 'short-argument': /\$\d+\b/, + omit: { pattern: /\b_\b/, alias: 'keyword' }, + number: + /\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i, + 'class-name': /\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/, + function: /\b[a-z_]\w*(?=\s*\()/i, + constant: /\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/, + operator: /[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/, + punctuation: /[{}[\]();,.:\\]/, +}), +Prism.languages.swift['string-literal'].forEach((e) => { + e.inside.interpolation.inside = Prism.languages.swift; +}); diff --git a/frontend/app/assets/prism/prism-typescript.min.js b/frontend/app/assets/prism/prism-typescript.min.js index b512c1617..0f7f7b2b8 100644 --- a/frontend/app/assets/prism/prism-typescript.min.js +++ b/frontend/app/assets/prism/prism-typescript.min.js @@ -1 +1,42 @@ -!function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism); \ No newline at end of file +!(function (e) { + (e.languages.typescript = e.languages.extend('javascript', { + 'class-name': { + pattern: + /(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/, + lookbehind: !0, + greedy: !0, + inside: null, + }, + builtin: + /\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/, + })), + e.languages.typescript.keyword.push( + /\b(?:abstract|declare|is|keyof|readonly|require)\b/, + /\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/, + /\btype\b(?=\s*(?:[\{*]|$))/, + ), + delete e.languages.typescript.parameter, + delete e.languages.typescript['literal-property']; + const s = e.languages.extend('typescript', {}); + delete s['class-name'], + (e.languages.typescript['class-name'].inside = s), + e.languages.insertBefore('typescript', 'function', { + decorator: { + pattern: /@[$\w\xA0-\uFFFF]+/, + inside: { + at: { pattern: /^@/, alias: 'operator' }, + function: /^[\s\S]+/, + }, + }, + 'generic-function': { + pattern: + /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/, + greedy: !0, + inside: { + function: /^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/, + generic: { pattern: /<[\s\S]+/, alias: 'class-name', inside: s }, + }, + }, + }), + (e.languages.ts = e.languages.typescript); +}(Prism)); diff --git a/frontend/app/assets/prism/prism.min.js b/frontend/app/assets/prism/prism.min.js index ebe7afbf1..65b6cfae0 100644 --- a/frontend/app/assets/prism/prism.min.js +++ b/frontend/app/assets/prism/prism.min.js @@ -4,7 +4,427 @@ * * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,a={},r={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof s?new s(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=c.reach);w+=k.value.length,k=k.next){var A=k.value;if(t.length>e.length)return;if(!(A instanceof s)){var P,$=1;if(b){if(!(P=i(x,w,e,v))||P.index>=e.length)break;var S=P.index,E=P.index+P[0].length,_=w;for(_+=k.value.length;S>=_;)_+=(k=k.next).value.length;if(w=_-=k.value.length,k.value instanceof s)continue;for(var j=k;j!==t.tail&&(_c.reach&&(c.reach=O);var T=k.prev;if(L&&(T=u(t,T,L),w+=L.length),g(t,T,$),k=u(t,T,new s(d,f?r.tokenize(C,f):C,y,C)),z&&u(t,k,z),$>1){var M={cause:d+","+m,reach:O};o(e,t,n,k.prev,w,M),c&&M.reach>c.reach&&(c.reach=M.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function u(e,t,n){var a=t.next,r={value:n,prev:t,next:a};return t.next=r,a.prev=r,e.length++,r}function g(e,t,n){for(var a=t.next,r=0;r"+s.content+""},!e.document)return e.addEventListener?(r.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),a=n.language,s=n.code,i=n.immediateClose;e.postMessage(r.highlight(s,r.languages[a],a)),i&&e.close()}),!1),r):r;var c=r.util.currentScript();function d(){r.manual||r.highlightAll()}if(c&&(r.filename=c.src,c.hasAttribute("data-manual")&&(r.manual=!0)),!r.manual){var p=document.readyState;"loading"===p||"interactive"===p&&c&&c.defer?document.addEventListener("DOMContentLoaded",d):window.requestAnimationFrame?window.requestAnimationFrame(d):window.setTimeout(d,16)}return r}(_self); +const _self = typeof window !== 'undefined' + ? window + : typeof WorkerGlobalScope !== 'undefined' + && self instanceof WorkerGlobalScope + ? self + : {}; +const Prism = (function (e) { + const t = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i; + let n = 0; + const a = {}; + var r = { + manual: e.Prism && e.Prism.manual, + disableWorkerMessageHandler: + e.Prism && e.Prism.disableWorkerMessageHandler, + util: { + encode: function e(t) { + return t instanceof s + ? new s(t.type, e(t.content), t.alias) + : Array.isArray(t) + ? t.map(e) + : t + .replace(/&/g, '&') + .replace(/ { + a[r] = e(t, n); + }), + a) + ); + default: + return t; + } + }, + getLanguage(e) { + for (; e;) { + const n = t.exec(e.className); + if (n) return n[1].toLowerCase(); + e = e.parentElement; + } + return 'none'; + }, + setLanguage(e, n) { + (e.className = e.className.replace(RegExp(t, 'gi'), '')), + e.classList.add(`language-${n}`); + }, + currentScript() { + if (typeof document === 'undefined') return null; + if ('currentScript' in document) return document.currentScript; + try { + throw new Error(); + } catch (a) { + const e = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(a.stack) + || [])[1]; + if (e) { + const t = document.getElementsByTagName('script'); + for (const n in t) if (t[n].src == e) return t[n]; + } + return null; + } + }, + isActive(e, t, n) { + for (let a = `no-${t}`; e;) { + const r = e.classList; + if (r.contains(t)) return !0; + if (r.contains(a)) return !1; + e = e.parentElement; + } + return !!n; + }, + }, + languages: { + plain: a, + plaintext: a, + text: a, + txt: a, + extend(e, t) { + const n = r.util.clone(r.languages[e]); + for (const a in t) n[a] = t[a]; + return n; + }, + insertBefore(e, t, n, a) { + const s = (a = a || r.languages)[e]; + const i = {}; + for (const o in s) { + if (s.hasOwnProperty(o)) { + if (o == t) for (const l in n) n.hasOwnProperty(l) && (i[l] = n[l]); + n.hasOwnProperty(o) || (i[o] = s[o]); + } + } + const u = a[e]; + return ( + (a[e] = i), + r.languages.DFS(r.languages, function (t, n) { + n === u && t != e && (this[t] = i); + }), + i + ); + }, + DFS: function e(t, n, a, s) { + s = s || {}; + const i = r.util.objId; + for (const o in t) { + if (t.hasOwnProperty(o)) { + n.call(t, o, t[o], a || o); + const l = t[o]; + const u = r.util.type(l); + u !== 'Object' || s[i(l)] + ? u !== 'Array' || s[i(l)] || ((s[i(l)] = !0), e(l, n, o, s)) + : ((s[i(l)] = !0), e(l, n, null, s)); + } + } + }, + }, + plugins: {}, + highlightAll(e, t) { + r.highlightAllUnder(document, e, t); + }, + highlightAllUnder(e, t, n) { + const a = { + callback: n, + container: e, + selector: + 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code', + }; + r.hooks.run('before-highlightall', a), + (a.elements = Array.prototype.slice.apply( + a.container.querySelectorAll(a.selector), + )), + r.hooks.run('before-all-elements-highlight', a); + for (var s, i = 0; (s = a.elements[i++]);) r.highlightElement(s, !0 === t, a.callback); + }, + highlightElement(t, n, a) { + const s = r.util.getLanguage(t); + const i = r.languages[s]; + r.util.setLanguage(t, s); + let o = t.parentElement; + o && o.nodeName.toLowerCase() === 'pre' && r.util.setLanguage(o, s); + const l = { + element: t, language: s, grammar: i, code: t.textContent, + }; + function u(e) { + (l.highlightedCode = e), + r.hooks.run('before-insert', l), + (l.element.innerHTML = l.highlightedCode), + r.hooks.run('after-highlight', l), + r.hooks.run('complete', l), + a && a.call(l.element); + } + if ( + (r.hooks.run('before-sanity-check', l), + (o = l.element.parentElement) + && o.nodeName.toLowerCase() === 'pre' + && !o.hasAttribute('tabindex') + && o.setAttribute('tabindex', '0'), + !l.code) + ) return r.hooks.run('complete', l), void (a && a.call(l.element)); + if ((r.hooks.run('before-highlight', l), l.grammar)) { + if (n && e.Worker) { + const g = new Worker(r.filename); + (g.onmessage = function (e) { + u(e.data); + }), + g.postMessage( + JSON.stringify({ + language: l.language, + code: l.code, + immediateClose: !0, + }), + ); + } else u(r.highlight(l.code, l.grammar, l.language)); + } else u(r.util.encode(l.code)); + }, + highlight(e, t, n) { + const a = { code: e, grammar: t, language: n }; + if ((r.hooks.run('before-tokenize', a), !a.grammar)) { + throw new Error( + `The language "${a.language}" has no grammar.`, + ); + } + return ( + (a.tokens = r.tokenize(a.code, a.grammar)), + r.hooks.run('after-tokenize', a), + s.stringify(r.util.encode(a.tokens), a.language) + ); + }, + tokenize(e, t) { + const n = t.rest; + if (n) { + for (const a in n) t[a] = n[a]; + delete t.rest; + } + const r = new l(); + return ( + u(r, r.head, e), + o(e, r, t, r.head, 0), + (function (e) { + const t = []; + let n = e.head.next; + for (; n !== e.tail;) t.push(n.value), (n = n.next); + return t; + }(r)) + ); + }, + hooks: { + all: {}, + add(e, t) { + const n = r.hooks.all; + (n[e] = n[e] || []), n[e].push(t); + }, + run(e, t) { + const n = r.hooks.all[e]; + if (n && n.length) for (var a, s = 0; (a = n[s++]);) a(t); + }, + }, + Token: s, + }; + function s(e, t, n, a) { + (this.type = e), + (this.content = t), + (this.alias = n), + (this.length = 0 | (a || '').length); + } + function i(e, t, n, a) { + e.lastIndex = t; + const r = e.exec(n); + if (r && a && r[1]) { + const s = r[1].length; + (r.index += s), (r[0] = r[0].slice(s)); + } + return r; + } + function o(e, t, n, a, l, c) { + for (const d in n) { + if (n.hasOwnProperty(d) && n[d]) { + let p = n[d]; + p = Array.isArray(p) ? p : [p]; + for (let m = 0; m < p.length; ++m) { + if (c && c.cause == `${d},${m}`) return; + const h = p[m]; + const f = h.inside; + const v = !!h.lookbehind; + const b = !!h.greedy; + const y = h.alias; + if (b && !h.pattern.global) { + const F = h.pattern.toString().match(/[imsuy]*$/)[0]; + h.pattern = RegExp(h.pattern.source, `${F}g`); + } + for ( + let x = h.pattern || h, k = a.next, w = l; + k !== t.tail && !(c && w >= c.reach); + w += k.value.length, k = k.next + ) { + let A = k.value; + if (t.length > e.length) return; + if (!(A instanceof s)) { + var P; + let $ = 1; + if (b) { + if (!(P = i(x, w, e, v)) || P.index >= e.length) break; + var S = P.index; + const E = P.index + P[0].length; + let _ = w; + for (_ += k.value.length; S >= _;) _ += (k = k.next).value.length; + if (((w = _ -= k.value.length), k.value instanceof s)) continue; + for ( + let j = k; + j !== t.tail && (_ < E || typeof j.value === 'string'); + j = j.next + ) $++, (_ += j.value.length); + $--, (A = e.slice(w, _)), (P.index -= w); + } else if (!(P = i(x, 0, A, v))) continue; + S = P.index; + const C = P[0]; + const L = A.slice(0, S); + const z = A.slice(S + C.length); + const O = w + A.length; + c && O > c.reach && (c.reach = O); + let T = k.prev; + if ( + (L && ((T = u(t, T, L)), (w += L.length)), + g(t, T, $), + (k = u(t, T, new s(d, f ? r.tokenize(C, f) : C, y, C))), + z && u(t, k, z), + $ > 1) + ) { + const M = { cause: `${d},${m}`, reach: O }; + o(e, t, n, k.prev, w, M), + c && M.reach > c.reach && (c.reach = M.reach); + } + } + } + } + } + } + } + function l() { + const e = { value: null, prev: null, next: null }; + const t = { value: null, prev: e, next: null }; + (e.next = t), (this.head = e), (this.tail = t), (this.length = 0); + } + function u(e, t, n) { + const a = t.next; + const r = { value: n, prev: t, next: a }; + return (t.next = r), (a.prev = r), e.length++, r; + } + function g(e, t, n) { + for (var a = t.next, r = 0; r < n && a !== e.tail; r++) a = a.next; + (t.next = a), (a.prev = t), (e.length -= r); + } + if ( + ((e.Prism = r), + (s.stringify = function e(t, n) { + if (typeof t === 'string') return t; + if (Array.isArray(t)) { + let a = ''; + return ( + t.forEach((t) => { + a += e(t, n); + }), + a + ); + } + const s = { + type: t.type, + content: e(t.content, n), + tag: 'span', + classes: ['token', t.type], + attributes: {}, + language: n, + }; + const i = t.alias; + i + && (Array.isArray(i) + ? Array.prototype.push.apply(s.classes, i) + : s.classes.push(i)), + r.hooks.run('wrap', s); + let o = ''; + for (const l in s.attributes) { + o + += ` ${ + l + }="${ + (s.attributes[l] || '').replace(/"/g, '"') + }"`; + } + return ( + `<${ + s.tag + } class="${ + s.classes.join(' ') + }"${ + o + }>${ + s.content + }` + ); + }), + !e.document) + ) { + return e.addEventListener + ? (r.disableWorkerMessageHandler + || e.addEventListener( + 'message', + (t) => { + const n = JSON.parse(t.data); + const a = n.language; + const s = n.code; + const i = n.immediateClose; + e.postMessage(r.highlight(s, r.languages[a], a)), + i && e.close(); + }, + !1, + ), + r) + : r; + } + const c = r.util.currentScript(); + function d() { + r.manual || r.highlightAll(); + } + if ( + (c + && ((r.filename = c.src), + c.hasAttribute('data-manual') && (r.manual = !0)), + !r.manual) + ) { + const p = document.readyState; + p === 'loading' || (p === 'interactive' && c && c.defer) + ? document.addEventListener('DOMContentLoaded', d) + : window.requestAnimationFrame + ? window.requestAnimationFrame(d) + : window.setTimeout(d, 16); + } + return r; +}(_self)); /** * Prism: Lightweight, robust, elegant syntax highlighting * @@ -12,5 +432,492 @@ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScop * @author Lea Verou * @namespace * @public - */"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism),Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[t]},n.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:Prism.languages[t]};var r={};r[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},Prism.languages.insertBefore("markup","cdata",r)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(e,t){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:Prism.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml,function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+t.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(Prism),Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),Prism.languages.js=Prism.languages.javascript,function(){if(void 0!==Prism&&"undefined"!=typeof document){Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector);var e={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"},t="data-src-status",n="loading",a="loaded",r="pre[data-src]:not(["+t+'="'+a+'"]):not(['+t+'="'+n+'"])';Prism.hooks.add("before-highlightall",(function(e){e.selector+=", "+r})),Prism.hooks.add("before-sanity-check",(function(s){var i=s.element;if(i.matches(r)){s.code="",i.setAttribute(t,n);var o=i.appendChild(document.createElement("CODE"));o.textContent="Loading…";var l=i.getAttribute("data-src"),u=s.language;if("none"===u){var g=(/\.(\w+)$/.exec(l)||[,"none"])[1];u=e[g]||g}Prism.util.setLanguage(o,u),Prism.util.setLanguage(i,u);var c=Prism.plugins.autoloader;c&&c.loadLanguages(u),function(e,t,n){var a=new XMLHttpRequest;a.open("GET",e,!0),a.onreadystatechange=function(){4==a.readyState&&(a.status<400&&a.responseText?t(a.responseText):a.status>=400?n("✖ Error "+a.status+" while fetching file: "+a.statusText):n("✖ Error: File does not exist or is empty"))},a.send(null)}(l,(function(e){i.setAttribute(t,a);var n=function(e){var t=/^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(e||"");if(t){var n=Number(t[1]),a=t[2],r=t[3];return a?r?[n,Number(r)]:[n,void 0]:[n,n]}}(i.getAttribute("data-range"));if(n){var r=e.split(/\r\n?|\n/g),s=n[0],l=null==n[1]?r.length:n[1];s<0&&(s+=r.length),s=Math.max(0,Math.min(s-1,r.length)),l<0&&(l+=r.length),l=Math.max(0,Math.min(l,r.length)),e=r.slice(s,l).join("\n"),i.hasAttribute("data-start")||i.setAttribute("data-start",String(s+1))}o.textContent=e,Prism.highlightElement(o)}),(function(e){i.setAttribute(t,"failed"),o.textContent=e}))}})),Prism.plugins.fileHighlight={highlight:function(e){for(var t,n=(e||document).querySelectorAll(r),a=0;t=n[a++];)Prism.highlightElement(t)}};var s=!1;Prism.fileHighlight=function(){s||(console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead."),s=!0),Prism.plugins.fileHighlight.highlight.apply(this,arguments)}}}(); -//# sourceMappingURL=/sm/1f55244a569fc0911044b5e4725a97872b6d85b0662a3429a809bb62f713c381.map \ No newline at end of file + */ typeof module !== 'undefined' && module.exports && (module.exports = Prism), +typeof global !== 'undefined' && (global.Prism = Prism), +(Prism.languages.markup = { + comment: { pattern: //, greedy: !0 }, + prolog: { pattern: /<\?[\s\S]+?\?>/, greedy: !0 }, + doctype: { + pattern: + /"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i, + greedy: !0, + inside: { + 'internal-subset': { + pattern: /(^[^\[]*\[)[\s\S]+(?=\]>$)/, + lookbehind: !0, + greedy: !0, + inside: null, + }, + string: { pattern: /"[^"]*"|'[^']*'/, greedy: !0 }, + punctuation: /^$|[[\]]/, + 'doctype-tag': /^DOCTYPE/i, + name: /[^\s<>'"]+/, + }, + }, + cdata: { pattern: //i, greedy: !0 }, + tag: { + pattern: + /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/, + greedy: !0, + inside: { + tag: { + pattern: /^<\/?[^\s>\/]+/, + inside: { punctuation: /^<\/?/, namespace: /^[^\s>\/:]+:/ }, + }, + 'special-attr': [], + 'attr-value': { + pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/, + inside: { + punctuation: [ + { pattern: /^=/, alias: 'attr-equals' }, + { pattern: /^(\s*)["']|["']$/, lookbehind: !0 }, + ], + }, + }, + punctuation: /\/?>/, + 'attr-name': { + pattern: /[^\s>\/]+/, + inside: { namespace: /^[^\s>\/:]+:/ }, + }, + }, + }, + entity: [ + { pattern: /&[\da-z]{1,8};/i, alias: 'named-entity' }, + /&#x?[\da-f]{1,8};/i, + ], +}), +(Prism.languages.markup.tag.inside['attr-value'].inside.entity = Prism.languages.markup.entity), +(Prism.languages.markup.doctype.inside['internal-subset'].inside = Prism.languages.markup), +Prism.hooks.add('wrap', (e) => { + e.type === 'entity' + && (e.attributes.title = e.content.replace(/&/, '&')); +}), +Object.defineProperty(Prism.languages.markup.tag, 'addInlined', { + value(e, t) { + const n = {}; + (n[`language-${t}`] = { + pattern: /(^$)/i, + lookbehind: !0, + inside: Prism.languages[t], + }), + (n.cdata = /^$/i); + const a = { + 'included-cdata': { pattern: //i, inside: n }, + }; + a[`language-${t}`] = { pattern: /[\s\S]+/, inside: Prism.languages[t] }; + const r = {}; + (r[e] = { + pattern: RegExp( + /(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace( + /__/g, + () => e, + ), + 'i', + ), + lookbehind: !0, + greedy: !0, + inside: a, + }), + Prism.languages.insertBefore('markup', 'cdata', r); + }, +}), +Object.defineProperty(Prism.languages.markup.tag, 'addAttribute', { + value(e, t) { + Prism.languages.markup.tag.inside['special-attr'].push({ + pattern: RegExp( + `${/(^|["'\s])/.source + }(?:${ + e + })${ + /\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source}`, + 'i', + ), + lookbehind: !0, + inside: { + 'attr-name': /^[^\s=]+/, + 'attr-value': { + pattern: /=[\s\S]+/, + inside: { + value: { + pattern: /(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/, + lookbehind: !0, + alias: [t, `language-${t}`], + inside: Prism.languages[t], + }, + punctuation: [{ pattern: /^=/, alias: 'attr-equals' }, /"|'/], + }, + }, + }, + }); + }, +}), +(Prism.languages.html = Prism.languages.markup), +(Prism.languages.mathml = Prism.languages.markup), +(Prism.languages.svg = Prism.languages.markup), +(Prism.languages.xml = Prism.languages.extend('markup', {})), +(Prism.languages.ssml = Prism.languages.xml), +(Prism.languages.atom = Prism.languages.xml), +(Prism.languages.rss = Prism.languages.xml), +(function (e) { + const t = /(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/; + (e.languages.css = { + comment: /\/\*[\s\S]*?\*\//, + atrule: { + pattern: RegExp( + `@[\\w-](?:${ + /[^;{\s"']|\s+(?!\s)/.source + }|${ + t.source + })*?${ + /(?:;|(?=\s*\{))/.source}`, + ), + inside: { + rule: /^@[\w-]+/, + 'selector-function-argument': { + pattern: + /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/, + lookbehind: !0, + alias: 'selector', + }, + keyword: { + pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/, + lookbehind: !0, + }, + }, + }, + url: { + pattern: RegExp( + `\\burl\\((?:${ + t.source + }|${ + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + })\\)`, + 'i', + ), + greedy: !0, + inside: { + function: /^url/i, + punctuation: /^\(|\)$/, + string: { pattern: RegExp(`^${t.source}$`), alias: 'url' }, + }, + }, + selector: { + pattern: RegExp( + `(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|${ + t.source + })*(?=\\s*\\{)`, + ), + lookbehind: !0, + }, + string: { pattern: t, greedy: !0 }, + property: { + pattern: + /(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i, + lookbehind: !0, + }, + important: /!important\b/i, + function: { pattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i, lookbehind: !0 }, + punctuation: /[(){};:,]/, + }), + (e.languages.css.atrule.inside.rest = e.languages.css); + const n = e.languages.markup; + n && (n.tag.addInlined('style', 'css'), n.tag.addAttribute('style', 'css')); +}(Prism)), +(Prism.languages.clike = { + comment: [ + { + pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, + lookbehind: !0, + greedy: !0, + }, + { pattern: /(^|[^\\:])\/\/.*/, lookbehind: !0, greedy: !0 }, + ], + string: { + pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + greedy: !0, + }, + 'class-name': { + pattern: + /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i, + lookbehind: !0, + inside: { punctuation: /[.\\]/ }, + }, + keyword: + /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/, + boolean: /\b(?:false|true)\b/, + function: /\b\w+(?=\()/, + number: /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i, + operator: /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/, + punctuation: /[{}[\];(),.:]/, +}), +(Prism.languages.javascript = Prism.languages.extend('clike', { + 'class-name': [ + Prism.languages.clike['class-name'], + { + pattern: + /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/, + lookbehind: !0, + }, + ], + keyword: [ + { pattern: /((?:^|\})\s*)catch\b/, lookbehind: !0 }, + { + pattern: + /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/, + lookbehind: !0, + }, + ], + function: + /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/, + number: { + pattern: RegExp( + `${/(^|[^\w$])/.source + }(?:${ + /NaN|Infinity/.source + }|${ + /0[bB][01]+(?:_[01]+)*n?/.source + }|${ + /0[oO][0-7]+(?:_[0-7]+)*n?/.source + }|${ + /0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source + }|${ + /\d+(?:_\d+)*n/.source + }|${ + /(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/ + .source + })${ + /(?![\w$])/.source}`, + ), + lookbehind: !0, + }, + operator: + /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/, +})), +(Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/), +Prism.languages.insertBefore('javascript', 'keyword', { + regex: { + pattern: RegExp( + `${/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source + + /\//.source + }(?:${ + /(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/ + .source + }|${ + /(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/ + .source + })${ + /(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/ + .source}`, + ), + lookbehind: !0, + greedy: !0, + inside: { + 'regex-source': { + pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/, + lookbehind: !0, + alias: 'language-regex', + inside: Prism.languages.regex, + }, + 'regex-delimiter': /^\/|\/$/, + 'regex-flags': /^[a-z]+$/, + }, + }, + 'function-variable': { + pattern: + /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/, + alias: 'function', + }, + parameter: [ + { + pattern: + /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + { + pattern: + /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + { + pattern: + /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + { + pattern: + /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/, + lookbehind: !0, + inside: Prism.languages.javascript, + }, + ], + constant: /\b[A-Z](?:[A-Z_]|\dx?)*\b/, +}), +Prism.languages.insertBefore('javascript', 'string', { + hashbang: { pattern: /^#!.*/, greedy: !0, alias: 'comment' }, + 'template-string': { + pattern: + /`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/, + greedy: !0, + inside: { + 'template-punctuation': { pattern: /^`|`$/, alias: 'string' }, + interpolation: { + pattern: + /((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/, + lookbehind: !0, + inside: { + 'interpolation-punctuation': { + pattern: /^\$\{|\}$/, + alias: 'punctuation', + }, + rest: Prism.languages.javascript, + }, + }, + string: /[\s\S]+/, + }, + }, + 'string-property': { + pattern: + /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m, + lookbehind: !0, + greedy: !0, + alias: 'property', + }, +}), +Prism.languages.insertBefore('javascript', 'operator', { + 'literal-property': { + pattern: + /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m, + lookbehind: !0, + alias: 'property', + }, +}), +Prism.languages.markup + && (Prism.languages.markup.tag.addInlined('script', 'javascript'), + Prism.languages.markup.tag.addAttribute( + /on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/ + .source, + 'javascript', + )), +(Prism.languages.js = Prism.languages.javascript), +(function () { + if (void 0 !== Prism && typeof document !== 'undefined') { + Element.prototype.matches + || (Element.prototype.matches = Element.prototype.msMatchesSelector + || Element.prototype.webkitMatchesSelector); + const e = { + js: 'javascript', + py: 'python', + rb: 'ruby', + ps1: 'powershell', + psm1: 'powershell', + sh: 'bash', + bat: 'batch', + h: 'c', + tex: 'latex', + }; + const t = 'data-src-status'; + const n = 'loading'; + const a = 'loaded'; + const r = `pre[data-src]:not([${ + t + }="${ + a + }"]):not([${ + t + }="${ + n + }"])`; + Prism.hooks.add('before-highlightall', (e) => { + e.selector += `, ${r}`; + }), + Prism.hooks.add('before-sanity-check', (s) => { + const i = s.element; + if (i.matches(r)) { + (s.code = ''), i.setAttribute(t, n); + const o = i.appendChild(document.createElement('CODE')); + o.textContent = 'Loading…'; + const l = i.getAttribute('data-src'); + let u = s.language; + if (u === 'none') { + const g = (/\.(\w+)$/.exec(l) || [, 'none'])[1]; + u = e[g] || g; + } + Prism.util.setLanguage(o, u), Prism.util.setLanguage(i, u); + const c = Prism.plugins.autoloader; + c && c.loadLanguages(u), + (function (e, t, n) { + const a = new XMLHttpRequest(); + a.open('GET', e, !0), + (a.onreadystatechange = function () { + a.readyState == 4 + && (a.status < 400 && a.responseText + ? t(a.responseText) + : a.status >= 400 + ? n( + `✖ Error ${ + a.status + } while fetching file: ${ + a.statusText}`, + ) + : n('✖ Error: File does not exist or is empty')); + }), + a.send(null); + }( + l, + (e) => { + i.setAttribute(t, a); + const n = (function (e) { + const t = /^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec( + e || '', + ); + if (t) { + const n = Number(t[1]); + const a = t[2]; + const r = t[3]; + return a ? (r ? [n, Number(r)] : [n, void 0]) : [n, n]; + } + }(i.getAttribute('data-range'))); + if (n) { + const r = e.split(/\r\n?|\n/g); + let s = n[0]; + let l = n[1] == null ? r.length : n[1]; + s < 0 && (s += r.length), + (s = Math.max(0, Math.min(s - 1, r.length))), + l < 0 && (l += r.length), + (l = Math.max(0, Math.min(l, r.length))), + (e = r.slice(s, l).join('\n')), + i.hasAttribute('data-start') + || i.setAttribute('data-start', String(s + 1)); + } + (o.textContent = e), Prism.highlightElement(o); + }, + (e) => { + i.setAttribute(t, 'failed'), (o.textContent = e); + }, + )); + } + }), + (Prism.plugins.fileHighlight = { + highlight(e) { + for ( + var t, n = (e || document).querySelectorAll(r), a = 0; + (t = n[a++]); + + ) Prism.highlightElement(t); + }, + }); + let s = !1; + Prism.fileHighlight = function () { + s + || (console.warn( + 'Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.', + ), + (s = !0)), + Prism.plugins.fileHighlight.highlight.apply(this, arguments); + }; + } +}()); +// # sourceMappingURL=/sm/1f55244a569fc0911044b5e4725a97872b6d85b0662a3429a809bb62f713c381.map diff --git a/frontend/app/components/Alerts/AlertForm.js b/frontend/app/components/Alerts/AlertForm.js index da3b74148..db6f50944 100644 --- a/frontend/app/components/Alerts/AlertForm.js +++ b/frontend/app/components/Alerts/AlertForm.js @@ -1,395 +1,397 @@ -import React, {useEffect} from 'react'; -import {Form, Input, SegmentSelection, Checkbox, Icon} from 'UI'; -import {alertConditions as conditions} from 'App/constants'; -import stl from './alertForm.module.css'; -import DropdownChips from './DropdownChips'; -import {validateEmail} from 'App/validate'; +import React, { useEffect } from 'react'; +import { + Form, Input, SegmentSelection, Checkbox, Icon, +} from 'UI'; +import { alertConditions as conditions } from 'App/constants'; +import { validateEmail } from 'App/validate'; import cn from 'classnames'; -import {useStore} from 'App/mstore' -import {observer} from 'mobx-react-lite' +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; import Select from 'Shared/Select'; -import {Button} from "antd"; +import { Button } from 'antd'; +import DropdownChips from './DropdownChips'; +import stl from './alertForm.module.css'; const thresholdOptions = [ - {label: '15 minutes', value: 15}, - {label: '30 minutes', value: 30}, - {label: '1 hour', value: 60}, - {label: '2 hours', value: 120}, - {label: '4 hours', value: 240}, - {label: '1 day', value: 1440}, + { label: '15 minutes', value: 15 }, + { label: '30 minutes', value: 30 }, + { label: '1 hour', value: 60 }, + { label: '2 hours', value: 120 }, + { label: '4 hours', value: 240 }, + { label: '1 day', value: 1440 }, ]; const changeOptions = [ - {label: 'change', value: 'change'}, - {label: '% change', value: 'percent'}, + { label: 'change', value: 'change' }, + { label: '% change', value: 'percent' }, ]; -const Circle = ({text}) => ( +function Circle({ text }) { + return (
- {text} + {text}
-); + ); +} -const Section = ({index, title, description, content}) => ( +function Section({ + index, title, description, content, +}) { + return (
-
- -
- {title} - {description &&
{description}
} -
+
+ +
+ {title} + {description &&
{description}
}
+
-
{content}
+
{content}
-); + ); +} function AlertForm(props) { - const { - slackChannels, - msTeamsChannels, - webhooks, - onDelete, - style = {height: "calc('100vh - 40px')"}, - } = props; - const {alertsStore, metricStore} = useStore() - const { - triggerOptions: allTriggerSeries, - loading, - } = alertsStore + const { + slackChannels, + msTeamsChannels, + webhooks, + onDelete, + style = { height: "calc('100vh - 40px')" }, + } = props; + const { alertsStore, metricStore } = useStore(); + const { + triggerOptions: allTriggerSeries, + loading, + } = alertsStore; - const triggerOptions = metricStore.instance.series.length > 0 ? allTriggerSeries.filter(s => { - return metricStore.instance.series.findIndex(ms => ms.seriesId === s.value) !== -1 - }).map(v => { - const labelArr = v.label.split('.') - labelArr.shift() - return { - ...v, - label: labelArr.join('.') - } - }) : allTriggerSeries - const instance = alertsStore.instance - const deleting = loading - - const write = ({target: {value, name}}) => alertsStore.edit({[name]: value}); - const writeOption = (e, {name, value}) => alertsStore.edit({[name]: value.value}); - const onChangeCheck = ({target: {checked, name}}) => alertsStore.edit({[name]: checked}); - - useEffect(() => { - void alertsStore.fetchTriggerOptions(); - }, []); - - const writeQueryOption = (e, {name, value}) => { - const {query} = instance; - alertsStore.edit({query: {...query, [name]: value}}); + const triggerOptions = metricStore.instance.series.length > 0 ? allTriggerSeries.filter((s) => metricStore.instance.series.findIndex((ms) => ms.seriesId === s.value) !== -1).map((v) => { + const labelArr = v.label.split('.'); + labelArr.shift(); + return { + ...v, + label: labelArr.join('.'), }; + }) : allTriggerSeries; + const { instance } = alertsStore; + const deleting = loading; - const writeQuery = ({target: {value, name}}) => { - const {query} = instance; - alertsStore.edit({query: {...query, [name]: value}}); - }; + const write = ({ target: { value, name } }) => alertsStore.edit({ [name]: value }); + const writeOption = (e, { name, value }) => alertsStore.edit({ [name]: value.value }); + const onChangeCheck = ({ target: { checked, name } }) => alertsStore.edit({ [name]: checked }); - const metric = - instance && instance.query.left - ? triggerOptions.find((i) => i.value === instance.query.left) - : null; - const unit = metric ? metric.unit : ''; - const isThreshold = instance.detectionMethod === 'threshold'; + useEffect(() => { + void alertsStore.fetchTriggerOptions(); + }, []); - return ( -
props.onSubmit(instance)} - id="alert-form" - > -
- -
-
- alertsStore.edit({[name]: value})} - value={{value: instance.detectionMethod}} - list={[ - {name: 'Threshold', value: 'threshold'}, - {name: 'Change', value: 'change'}, - ]} - /> -
- {isThreshold && - 'Eg. Alert me if memory.avg is greater than 500mb over the past 4 hours.'} - {!isThreshold && - 'Eg. Alert me if % change of memory.avg is greater than 10% over the past 4 hours compared to the previous 4 hours.'} -
-
-
- } + const writeQueryOption = (e, { name, value }) => { + const { query } = instance; + alertsStore.edit({ query: { ...query, [name]: value } }); + }; + + const writeQuery = ({ target: { value, name } }) => { + const { query } = instance; + alertsStore.edit({ query: { ...query, [name]: value } }); + }; + + const metric = instance && instance.query.left + ? triggerOptions.find((i) => i.value === instance.query.left) + : null; + const unit = metric ? metric.unit : ''; + const isThreshold = instance.detectionMethod === 'threshold'; + + return ( + props.onSubmit(instance)} + id="alert-form" + > +
+ +
+
+ alertsStore.edit({ [name]: value })} + value={{ value: instance.detectionMethod }} + list={[ + { name: 'Threshold', value: 'threshold' }, + { name: 'Change', value: 'change' }, + ]} + /> +
+ {isThreshold + && 'Eg. Alert me if memory.avg is greater than 500mb over the past 4 hours.'} + {!isThreshold + && 'Eg. Alert me if % change of memory.avg is greater than 10% over the past 4 hours compared to the previous 4 hours.'} +
+
+
+ )} + /> + +
+ +
+ {!isThreshold && ( +
+ + writeOption(null, {name: 'change', value})} - id="change-dropdown" - /> -
- )} - -
- - i.value === instance.query.left)} // onChange={ writeQueryOption } - onChange={({value}) => - writeQueryOption(null, {name: 'left', value: value.value}) - } - /> -
+ onChange={({ value }) => writeQueryOption(null, { name: 'left', value: value.value })} + /> +
-
- -
- - writeQueryOption(null, {name: 'operator', value: value.value}) - } - /> - {unit && ( - <> - writeQueryOption(null, { name: 'operator', value: value.value })} + /> + {unit && ( + <> + - {'test'} - - )} - {!unit && ( - + test + + )} + {!unit && ( + - )} -
-
+ name="right" + value={instance.query.right} + onChange={writeQuery} + placeholder="Specify value" + /> + )} +
+
-
- - writeOption(null, {name: 'currentPeriod', value})} - /> -
- {!isThreshold && ( -
- - writeOption(null, {name: 'previousPeriod', value})} - /> -
- )} -
- } + onChange={({ value }) => writeOption(null, { name: 'previousPeriod', value })} /> +
+ )} + + )} + /> -
+
-
-
- - - - -
- - {instance.slack && ( -
- -
- alertsStore.edit({slackInput: selected})} - /> -
-
- )} - {instance.msteams && ( -
- -
- alertsStore.edit({msteamsInput: selected})} - /> -
-
- )} - - {instance.email && ( -
- -
- alertsStore.edit({emailInput: selected})} - /> -
-
- )} - - {instance.webhook && ( -
- - alertsStore.edit({webhookInput: selected})} - /> -
- )} - - } +
+
+ -
+ + + + -
-
- -
- + {instance.slack && ( +
+ +
+ alertsStore.edit({ slackInput: selected })} + />
-
- {instance.exists() && ( - - )} +
+ )} + {instance.msteams && ( +
+ +
+ alertsStore.edit({ msteamsInput: selected })} + />
+
+ )} + + {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 50e0c3cf6..05a751919 100644 --- a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx +++ b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx @@ -1,17 +1,15 @@ -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, confirm } from 'UI'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { SLACK, TEAMS, WEBHOOK } from 'App/constants/schedule'; import AlertForm from '../AlertForm'; -import {SLACK, TEAMS, WEBHOOK} from 'App/constants/schedule'; -import {confirm} from 'UI'; interface Select { label: string; value: string | number } - interface Props { showModal?: boolean; metricId?: number; @@ -19,77 +17,76 @@ interface Props { } function AlertFormModal(props: Props) { - const {alertsStore, settingsStore} = useStore() - const {metricId = null, showModal = false} = props; - const [showForm, setShowForm] = useState(false); - const webhooks = settingsStore.webhooks - useEffect(() => { - settingsStore.fetchWebhooks(); - }, []); + const { alertsStore, settingsStore } = useStore(); + const { metricId = null, showModal = false } = props; + const [showForm, setShowForm] = useState(false); + const { webhooks } = settingsStore; + useEffect(() => { + settingsStore.fetchWebhooks(); + }, []); + const slackChannels: Select[] = []; + const hooks: Select[] = []; + const msTeamsChannels: Select[] = []; - const slackChannels: Select[] = [] - const hooks: Select[] = [] - const msTeamsChannels: Select[] = [] + webhooks.forEach((hook) => { + const option = { value: hook.webhookId, label: hook.name }; + if (hook.type === SLACK) { + slackChannels.push(option); + } + if (hook.type === WEBHOOK) { + hooks.push(option); + } + if (hook.type === TEAMS) { + msTeamsChannels.push(option); + } + }); - webhooks.forEach((hook) => { - const option = {value: hook.webhookId, label: hook.name} - if (hook.type === SLACK) { - slackChannels.push(option) - } - if (hook.type === WEBHOOK) { - hooks.push(option) - } - if (hook.type === TEAMS) { - msTeamsChannels.push(option) - } - }) + const saveAlert = (instance) => { + const wasUpdating = instance.exists(); + alertsStore.save(instance).then(() => { + if (!wasUpdating) { + toggleForm(null, false); + } + if (props.onClose) { + props.onClose(); + } + }); + }; - const saveAlert = (instance) => { - const wasUpdating = instance.exists(); - alertsStore.save(instance).then(() => { - if (!wasUpdating) { - toggleForm(null, false); - } - if (props.onClose) { - props.onClose(); - } - }); - }; + const onDelete = async (instance) => { + if ( + await confirm({ + header: 'Confirm', + confirmButton: 'Yes, delete', + confirmation: 'Are you sure you want to permanently delete this alert?', + }) + ) { + alertsStore.remove(instance.alertId).then(() => { + toggleForm(null, false); + }); + } + }; - const onDelete = async (instance) => { - if ( - await confirm({ - header: 'Confirm', - confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this alert?`, - }) - ) { - alertsStore.remove(instance.alertId).then(() => { - toggleForm(null, false); - }); - } - }; + const toggleForm = (instance, state) => { + if (instance) { + alertsStore.init(instance); + } + return setShowForm(state || !showForm); + }; - const toggleForm = (instance, state) => { - if (instance) { - alertsStore.init(instance); - } - return setShowForm(state ? state : !showForm); - }; - - return ( - - ); + return ( + + ); } export default observer(AlertFormModal); diff --git a/frontend/app/components/Alerts/AlertFormModal/index.ts b/frontend/app/components/Alerts/AlertFormModal/index.ts index 6eb4de1f2..1c1d42263 100644 --- a/frontend/app/components/Alerts/AlertFormModal/index.ts +++ b/frontend/app/components/Alerts/AlertFormModal/index.ts @@ -1 +1 @@ -export { default } from './AlertFormModal'; \ No newline at end of file +export { default } from './AlertFormModal'; diff --git a/frontend/app/components/Alerts/DropdownChips/DropdownChips.js b/frontend/app/components/Alerts/DropdownChips/DropdownChips.js index 1f805057d..a753fab1c 100644 --- a/frontend/app/components/Alerts/DropdownChips/DropdownChips.js +++ b/frontend/app/components/Alerts/DropdownChips/DropdownChips.js @@ -2,65 +2,65 @@ import React from 'react'; import { Input, TagBadge } from 'UI'; import Select from 'Shared/Select'; -const DropdownChips = ({ - textFiled = false, - validate = null, - placeholder = '', - selected = [], - options = [], - badgeClassName = 'lowercase', - onChange = () => null, - ...props -}) => { - const onRemove = (id) => { - onChange(selected.filter((i) => i !== id)); - }; +function DropdownChips({ + textFiled = false, + validate = null, + placeholder = '', + selected = [], + options = [], + badgeClassName = 'lowercase', + onChange = () => null, + ...props +}) { + const onRemove = (id) => { + onChange(selected.filter((i) => i !== id)); + }; - const onSelect = ({ value }) => { - const newSlected = selected.concat(value.value); - onChange(newSlected); - }; + const onSelect = ({ value }) => { + const newSlected = selected.concat(value.value); + onChange(newSlected); + }; - const onKeyPress = (e) => { - const val = e.target.value; - if (e.key !== 'Enter' || selected.includes(val)) return; - e.preventDefault(); - e.stopPropagation(); - if (validate && !validate(val)) return; + const onKeyPress = (e) => { + const val = e.target.value; + if (e.key !== 'Enter' || selected.includes(val)) return; + e.preventDefault(); + e.stopPropagation(); + if (validate && !validate(val)) return; - const newSlected = selected.concat(val); - e.target.value = ''; - onChange(newSlected); - }; + const newSlected = selected.concat(val); + e.target.value = ''; + onChange(newSlected); + }; - const _options = options.filter((item) => !selected.includes(item.value)); + const _options = options.filter((item) => !selected.includes(item.value)); - const renderBadge = (item) => { - const val = typeof item === 'string' ? item : item.value; - const text = typeof item === 'string' ? item : item.label; - return onRemove(val)} outline={true} />; - }; + const renderBadge = (item) => { + const val = typeof item === 'string' ? item : item.value; + const text = typeof item === 'string' ? item : item.label; + return onRemove(val)} outline />; + }; - return ( -
- {textFiled ? ( - - ) : ( - + ) : ( + - - - - -
- - -
-
- - )); + +
+ + + + +
+
+ +
+ + +
+
+ + )); } export default EditRecordingModal; diff --git a/frontend/app/components/Assist/RecordingsList/Recordings.tsx b/frontend/app/components/Assist/RecordingsList/Recordings.tsx index 394db4aac..4a8b36048 100644 --- a/frontend/app/components/Assist/RecordingsList/Recordings.tsx +++ b/frontend/app/components/Assist/RecordingsList/Recordings.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { PageTitle } from 'UI'; import Select from 'Shared/Select'; -import RecordingsSearch from './RecordingsSearch'; -import RecordingsList from './RecordingsList'; import { useStore } from 'App/mstore'; import SelectDateRange from 'Shared/SelectDateRange/SelectDateRange'; import { observer } from 'mobx-react-lite'; +import RecordingsList from './RecordingsList'; +import RecordingsSearch from './RecordingsSearch'; function Recordings() { const { recordingsStore, userStore } = useStore(); @@ -13,7 +13,7 @@ function Recordings() { const recordingsOwner = [ { value: '0', label: 'All Videos' }, - { value: userId, label: 'My Videos' } + { value: userId, label: 'My Videos' }, ]; const onDateChange = (e: any) => { @@ -21,22 +21,22 @@ function Recordings() { }; return ( -
-
-
- +
+
+
+
-
- +
+ -
- ); + return ( +
+ + +
+ ); } export default observer(RecordingsSearch); diff --git a/frontend/app/components/Assist/RecordingsList/RecordsListItem.tsx b/frontend/app/components/Assist/RecordingsList/RecordsListItem.tsx index 3d5f70cc6..463a1349d 100644 --- a/frontend/app/components/Assist/RecordingsList/RecordsListItem.tsx +++ b/frontend/app/components/Assist/RecordingsList/RecordsListItem.tsx @@ -34,7 +34,7 @@ function RecordsListItem(props: Props) { const onDelete = () => { recordingsStore.deleteRecording(record.recordId).then(() => { recordingsStore.setRecordings( - recordingsStore.recordings.filter((rec) => rec.recordId !== record.recordId) + recordingsStore.recordings.filter((rec) => rec.recordId !== record.recordId), ); toast.success('Recording deleted'); }); diff --git a/frontend/app/components/Assist/RequestingWindow/RequestingWindow.tsx b/frontend/app/components/Assist/RequestingWindow/RequestingWindow.tsx index 2aff2db05..498708e77 100644 --- a/frontend/app/components/Assist/RequestingWindow/RequestingWindow.tsx +++ b/frontend/app/components/Assist/RequestingWindow/RequestingWindow.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { INDEXES } from 'App/constants/zindex'; import { Loader, Icon } from 'UI'; -import { Button } from 'antd' +import { Button } from 'antd'; import { PlayerContext } from 'App/components/Session/playerContext'; -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; interface Props { @@ -41,30 +41,29 @@ const WIN_VARIANTS = { icon: 'record-circle' as const, iconColor: 'red', action: Actions.RecordingEnd, - } + }, }; function RequestingWindow({ getWindowType }: Props) { const { sessionStore } = useStore(); - const userDisplayName = sessionStore.current.userDisplayName; - const windowType = getWindowType() + const { userDisplayName } = sessionStore.current; + const windowType = getWindowType(); if (!windowType) return; - const { player } = React.useContext(PlayerContext) - + const { player } = React.useContext(PlayerContext); const { assistManager: { initiateCallEnd, releaseRemoteControl, stopRecording, - } - } = player + }, + } = player; const actions = { [Actions.CallEnd]: initiateCallEnd, [Actions.ControlEnd]: releaseRemoteControl, [Actions.RecordingEnd]: stopRecording, - } + }; return (
- Waiting for {userDisplayName} + Waiting for + {' '} + {userDisplayName}
{WIN_VARIANTS[windowType].text} diff --git a/frontend/app/components/Assist/RequestingWindow/index.ts b/frontend/app/components/Assist/RequestingWindow/index.ts index 1a50403c4..5a610cd8e 100644 --- a/frontend/app/components/Assist/RequestingWindow/index.ts +++ b/frontend/app/components/Assist/RequestingWindow/index.ts @@ -1 +1 @@ -export { default, WindowType } from './RequestingWindow' +export { default, WindowType } from './RequestingWindow'; diff --git a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx index 40281b8a9..7ca030472 100644 --- a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx +++ b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx @@ -1,20 +1,22 @@ import React, { useState, useEffect } from 'react'; import { Button } from 'antd'; import cn from 'classnames'; -import ChatWindow from '../../ChatWindow'; -import { CallingState, ConnectionStatus, RemoteControlStatus, RequestLocalStream } from 'Player'; +import { + CallingState, ConnectionStatus, RemoteControlStatus, RequestLocalStream, +} from 'Player'; import type { LocalStream } from 'Player'; import { PlayerContext, ILivePlayerContext } from 'App/components/Session/playerContext'; import { observer } from 'mobx-react-lite'; import { toast } from 'react-toastify'; import { confirm, Icon, Tooltip } from 'UI'; -import stl from './AassistActions.module.css'; import ScreenRecorder from 'App/components/Session_/ScreenRecorder/ScreenRecorder'; import { audioContextManager } from 'App/utils/screenRecorder'; -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; +import stl from './AassistActions.module.css'; +import ChatWindow from '../../ChatWindow'; function onReject() { - toast.info(`Call was rejected.`); + toast.info('Call was rejected.'); } function onControlReject() { @@ -39,13 +41,13 @@ interface Props { const AssistActionsPing = { control: { start: 's_control_started', - end: 's_control_ended' + end: 's_control_ended', }, call: { start: 's_call_started', - end: 's_call_ended' + end: 's_call_ended', }, -} as const +} as const; function AssistActions({ userId, @@ -57,9 +59,9 @@ function AssistActions({ const { sessionStore, userStore } = useStore(); const permissions = userStore.account.permissions || []; const hasPermission = permissions.includes('ASSIST_CALL') || permissions.includes('SERVICE_ASSIST_CALL'); - const isEnterprise = userStore.isEnterprise; + const { isEnterprise } = userStore; const agentId = userStore.account.id; - const userDisplayName = sessionStore.current.userDisplayName; + const { userDisplayName } = sessionStore.current; const { assistManager: { @@ -82,12 +84,11 @@ function AssistActions({ const [isPrestart, setPrestart] = useState(false); const [incomeStream, setIncomeStream] = useState([]); const [localStream, setLocalStream] = useState(null); - const [callObject, setCallObject] = useState<{ end: () => void } | null>(null); + const [callObject, setCallObject] = useState<{ end:() => void } | null>(null); const onCall = calling === CallingState.OnCall || calling === CallingState.Reconnecting; const callRequesting = calling === CallingState.Connecting; - const cannotCall = - peerConnectionStatus !== ConnectionStatus.Connected || (isEnterprise && !hasPermission); + const cannotCall = peerConnectionStatus !== ConnectionStatus.Connected || (isEnterprise && !hasPermission); const remoteRequesting = remoteControlStatus === RemoteControlStatus.Requesting; const remoteActive = remoteControlStatus === RemoteControlStatus.Enabled; @@ -121,13 +122,11 @@ function AssistActions({ } }, [remoteActive]); - useEffect(() => { - return callObject?.end(); - }, []); + useEffect(() => callObject?.end(), []); useEffect(() => { if (peerConnectionStatus == ConnectionStatus.Disconnected) { - toast.info(`Live session was closed.`); + toast.info('Live session was closed.'); } }, [peerConnectionStatus]); @@ -151,11 +150,11 @@ function AssistActions({ lStream, addIncomeStream, () => { - player.assistManager.ping(AssistActionsPing.call.end, agentId) + player.assistManager.ping(AssistActionsPing.call.end, agentId); lStream.stop.bind(lStream); }, onReject, - onError + onError, ); setCallObject(callPeer()); if (additionalAgentIds) { @@ -172,7 +171,7 @@ function AssistActions({ await confirm({ header: 'Start Call', confirmButton: 'Call', - confirmation: `Are you sure you want to call ${userId ? userId : 'User'}?`, + confirmation: `Are you sure you want to call ${userId || 'User'}?`, }) ) { call(agentIds); @@ -181,15 +180,15 @@ function AssistActions({ const requestControl = () => { const onStart = () => { - player.assistManager.ping(AssistActionsPing.control.start, agentId) - } + player.assistManager.ping(AssistActionsPing.control.start, agentId); + }; const onEnd = () => { - player.assistManager.ping(AssistActionsPing.control.end, agentId) - } + player.assistManager.ping(AssistActionsPing.control.end, agentId); + }; setRemoteControlCallbacks({ onReject: onControlReject, - onStart: onStart, - onEnd: onEnd, + onStart, + onEnd, onBusy: onControlBusy, }); requestReleaseRemoteControl(); @@ -197,9 +196,9 @@ function AssistActions({ React.useEffect(() => { if (onCall) { - player.assistManager.ping(AssistActionsPing.call.start, agentId) + player.assistManager.ping(AssistActionsPing.call.start, agentId); } - }, [onCall]) + }, [onCall]); return (
@@ -214,7 +213,7 @@ function AssistActions({ >
-
- {Object.keys(graphs.currentPeriod).map((i: PeriodKeys) => ( -
-
- - {chartNames[i]} - -
- - {graphs.currentPeriod[i] - ? durationFromMsFormatted(graphs.currentPeriod[i]) - : null} - - {graphs.previousPeriod[i] ? ( -
+ {Object.keys(graphs.currentPeriod).map((i: PeriodKeys) => ( +
+
+ + {chartNames[i]} + +
+ + {graphs.currentPeriod[i] + ? durationFromMsFormatted(graphs.currentPeriod[i]) + : null} + + {graphs.previousPeriod[i] ? ( +
graphs.previousPeriod[i] - ? 'flex items-center gap-1 text-green' - : 'flex items-center gap-2 text-red' + ? 'flex items-center gap-1 text-green' + : 'flex items-center gap-2 text-red' } - > - graphs.previousPeriod[i] ? 0 : 180} - /> - {`${Math.round( - calculatePercentageDelta( - graphs.currentPeriod[i], - graphs.previousPeriod[i] - ) - )}%`} -
- ) : null} -
+ > + graphs.previousPeriod[i] ? 0 : 180} + /> + {`${Math.round( + calculatePercentageDelta( + graphs.currentPeriod[i], + graphs.previousPeriod[i], + ), + )}%`} +
+ ) : null}
- - -
- ))} + + + +
+ ))}
-
+
-
+
-
+
); } diff --git a/frontend/app/components/AssistStats/components/Charts.tsx b/frontend/app/components/AssistStats/components/Charts.tsx index 665040277..80b39fc9d 100644 --- a/frontend/app/components/AssistStats/components/Charts.tsx +++ b/frontend/app/components/AssistStats/components/Charts.tsx @@ -21,7 +21,7 @@ function Chart(props: Props) { return ( No data available
} + title={
No data available
} show={data && data.length === 0} style={{ height: '100px' }} > @@ -51,7 +51,7 @@ function Chart(props: Props) { fillOpacity={1} strokeWidth={2} strokeOpacity={0.8} - fill={'url(#colorCount)'} + fill="url(#colorCount)" /> diff --git a/frontend/app/components/AssistStats/components/Table.tsx b/frontend/app/components/AssistStats/components/Table.tsx index 01abade37..a9bbe8304 100644 --- a/frontend/app/components/AssistStats/components/Table.tsx +++ b/frontend/app/components/AssistStats/components/Table.tsx @@ -1,9 +1,10 @@ -import { DownOutlined } from '@ant-design/icons'; +import { DownOutlined, CloudDownloadOutlined, TableOutlined } from '@ant-design/icons'; import { AssistStatsSession, SessionsResponse } from 'App/services/AssistStatsService'; import { numberWithCommas } from 'App/utils'; import React from 'react'; -import { Button, Dropdown, Space, Typography, Tooltip } from 'antd'; -import { CloudDownloadOutlined, TableOutlined } from '@ant-design/icons'; +import { + Button, Dropdown, Space, Typography, Tooltip, +} from 'antd'; import { Loader, Pagination, NoContent } from 'UI'; import PlayLink from 'Shared/SessionItem/PlayLink'; import { recordingsService } from 'App/services'; @@ -43,7 +44,9 @@ const sortItems = [ // }, ]; -function StatsTable({ onSort, isLoading, onPageChange, page, sessions, exportCSV }: Props) { +function StatsTable({ + onSort, isLoading, onPageChange, page, sessions, exportCSV, +}: Props) { const [sortValue, setSort] = React.useState(sortItems[0].label); const updateRange = ({ key }: { key: string }) => { const item = sortItems.find((item) => item.key === key); @@ -52,14 +55,14 @@ function StatsTable({ onSort, isLoading, onPageChange, page, sessions, exportCSV }; return ( -
-
+
+
Assisted Sessions -
+
-
-
+
Date Team Members Live Duration @@ -83,31 +86,52 @@ function StatsTable({ onSort, isLoading, onPageChange, page, sessions, exportCSV Remote Duration {/* BUTTONS */}
-
- +
+ No data available
} + size="small" + title={
No data available
} show={sessions.list && sessions.list.length === 0} style={{ height: '100px' }} > - {sessions.list.map((session) => ( - - ))} + {sessions.list.map((session) => ( + + ))} -
+
-
+
{sessions.total > 0 ? (
- Showing {(page - 1) * PER_PAGE + 1} to{' '} - {(page - 1) * PER_PAGE + sessions.list.length} of{' '} - {numberWithCommas(sessions.total)} sessions. + Showing + {' '} + {(page - 1) * PER_PAGE + 1} + {' '} + to + {' '} + {(page - 1) * PER_PAGE + sessions.list.length} + {' '} + of + {' '} + {numberWithCommas(sessions.total)} + {' '} + sessions.
) : (
- Showing 0 to 0{' '} - of 0 sessions. + Showing + {' '} + 0 + {' '} + to + {' '} + 0 + {' '} + of + {' '} + 0 + {' '} + sessions.
)} +
{checkForRecent(getDateFromMill(session.timestamp)!, 'LLL dd, hh:mm a')} -
+
{session.teamMembers.map((member) => ( -
{member.name}
+
{member.name}
))}
@@ -139,7 +163,7 @@ function Row({ session }: { session: AssistStatsSession }) { {durationFromMsFormatted(session.callDuration)} {durationFromMsFormatted(session.controlDuration)} -
+
{session.recordings?.length > 0 ? ( session.recordings?.length > 1 ? ( - recordingsService.fetchRecording(item.key as unknown as number), + onClick: (item) => recordingsService.fetchRecording(item.key as unknown as number), }} > ) : (
recordingsService.fetchRecording(session.recordings[0].recordId)} > diff --git a/frontend/app/components/AssistStats/components/TeamMembers.tsx b/frontend/app/components/AssistStats/components/TeamMembers.tsx index d1440095d..7dc7da4f5 100644 --- a/frontend/app/components/AssistStats/components/TeamMembers.tsx +++ b/frontend/app/components/AssistStats/components/TeamMembers.tsx @@ -1,11 +1,12 @@ import { DownOutlined, TableOutlined } from '@ant-design/icons'; -import { Button, Dropdown, Space, Typography, Tooltip } from 'antd'; +import { + Button, Dropdown, Space, Typography, Tooltip, +} from 'antd'; import { durationFromMsFormatted } from 'App/date'; import { Member } from 'App/services/AssistStatsService'; -import { getInitials } from 'App/utils'; +import { getInitials, exportCSVFile } from 'App/utils'; import React from 'react'; import { Loader, NoContent } from 'UI'; -import { exportCSVFile } from 'App/utils'; const items = [ { @@ -65,14 +66,14 @@ function TeamMembers({ }; return ( -
-
+
+
Team Members -
+
-
No data available
} + size="small" + title={
No data available
} show={topMembers.list && topMembers.list.length === 0} style={{ height: '100px' }} > {topMembers.list.map((member) => ( -
+
{getInitials(member.name)}
{member.name}
-
+
{membersSort === 'sessionsAssisted' ? member.count : durationFromMsFormatted(member.count)} @@ -113,7 +114,7 @@ function TeamMembers({ ))} -
+
{isLoading || topMembers.list.length === 0 ? '' : `Showing 1 to ${topMembers.total} of the total`} diff --git a/frontend/app/components/AssistStats/components/UserSearch.tsx b/frontend/app/components/AssistStats/components/UserSearch.tsx index 3e9baac1a..3765f3924 100644 --- a/frontend/app/components/AssistStats/components/UserSearch.tsx +++ b/frontend/app/components/AssistStats/components/UserSearch.tsx @@ -4,7 +4,7 @@ import type { SelectProps } from 'antd/es/select'; import { observer } from 'mobx-react-lite'; import { useStore } from 'App/mstore'; -const UserSearch = ({ onUserSelect }: { onUserSelect: (id: any) => void }) => { +function UserSearch({ onUserSelect }: { onUserSelect: (id: any) => void }) { const [selectedValue, setSelectedValue] = useState(undefined); const { userStore } = useStore(); const allUsers = userStore.list.map((user) => ({ @@ -20,7 +20,7 @@ const UserSearch = ({ onUserSelect }: { onUserSelect: (id: any) => void }) => { r.map((user: any) => ({ value: user.userId, label: user.name, - })) + })), ); }); } @@ -28,12 +28,12 @@ const UserSearch = ({ onUserSelect }: { onUserSelect: (id: any) => void }) => { const handleSearch = (value: string) => { setOptions( - value ? allUsers.filter((u) => u.label.toLowerCase().includes(value.toLocaleLowerCase())) : [] + value ? allUsers.filter((u) => u.label.toLowerCase().includes(value.toLocaleLowerCase())) : [], ); }; const onSelect = (value?: string) => { - onUserSelect(value) + onUserSelect(value); setSelectedValue(allUsers.find((u) => u.value === value)?.label || ''); }; @@ -46,8 +46,8 @@ const UserSearch = ({ onUserSelect }: { onUserSelect: (id: any) => void }) => { onSearch={handleSearch} value={selectedValue} onChange={(e) => { - setSelectedValue(e) - if (!e) onUserSelect(undefined) + setSelectedValue(e); + if (!e) onUserSelect(undefined); }} onClear={() => onSelect(undefined)} onDeselect={() => onSelect(undefined)} @@ -56,12 +56,12 @@ const UserSearch = ({ onUserSelect }: { onUserSelect: (id: any) => void }) => { ); -}; +} export default observer(UserSearch); diff --git a/frontend/app/components/AssistStats/index.ts b/frontend/app/components/AssistStats/index.ts index 96108d5f2..dbc6886e4 100644 --- a/frontend/app/components/AssistStats/index.ts +++ b/frontend/app/components/AssistStats/index.ts @@ -1 +1 @@ -export { default } from './AssistStats' +export { default } from './AssistStats'; diff --git a/frontend/app/components/AssistStats/pdfGenerator.ts b/frontend/app/components/AssistStats/pdfGenerator.ts index 2d1f0f3f1..e8bbf0b5c 100644 --- a/frontend/app/components/AssistStats/pdfGenerator.ts +++ b/frontend/app/components/AssistStats/pdfGenerator.ts @@ -28,9 +28,9 @@ export const getPdf2 = async () => { }).then((canvas) => { const imgData = canvas.toDataURL('img/png'); - let imgWidth = 290; - let pageHeight = 200; - let imgHeight = (canvas.height * imgWidth) / canvas.width; + const imgWidth = 290; + const pageHeight = 200; + const imgHeight = (canvas.height * imgWidth) / canvas.width; let heightLeft = imgHeight - pageHeight; let position = 0; const A4Height = 295; @@ -39,15 +39,16 @@ export const getPdf2 = async () => { doc.addImage(imgData, 'PNG', 3, 10, imgWidth, imgHeight); doc.addImage('/assets/img/cobrowising-report-head.png', 'png', A4Height / 2 - headerW / 2, 2, 45, 5); - if (position === 0 && heightLeft === 0) + if (position === 0 && heightLeft === 0) { doc.addImage( '/assets/img/report-head.png', 'png', imgWidth / 2 - headerW / 2, pageHeight - 5, logoWidth, - 5 + 5, ); + } while (heightLeft >= 0) { position = heightLeft - imgHeight; @@ -59,12 +60,12 @@ export const getPdf2 = async () => { A4Height / 2 - headerW / 2, pageHeight - 5, logoWidth, - 5 + 5, ); heightLeft -= pageHeight; } - doc.save(fileNameFormat('Assist_Stats_' + Date.now(), '.pdf')); + doc.save(fileNameFormat(`Assist_Stats_${Date.now()}`, '.pdf')); }); } diff --git a/frontend/app/components/Charts/BarChart.tsx b/frontend/app/components/Charts/BarChart.tsx index 2d23dd834..f2666dbfb 100644 --- a/frontend/app/components/Charts/BarChart.tsx +++ b/frontend/app/components/Charts/BarChart.tsx @@ -1,12 +1,12 @@ import React from 'react'; +import { BarChart } from 'echarts/charts'; import { DataProps, buildCategories, - customTooltipFormatter + customTooltipFormatter, } from './utils'; import { buildBarDatasetsAndSeries } from './barUtils'; -import { defaultOptions, echarts, initWindowStorages } from "./init"; -import { BarChart } from 'echarts/charts'; +import { defaultOptions, echarts, initWindowStorages } from './init'; echarts.use([BarChart]); @@ -23,7 +23,7 @@ function ORBarChart(props: BarChartProps) { React.useEffect(() => { if (!chartRef.current) return; const chart = echarts.init(chartRef.current); - const obs = new ResizeObserver(() => chart.resize()) + const obs = new ResizeObserver(() => chart.resize()); obs.observe(chartRef.current); const categories = buildCategories(props.data); @@ -45,7 +45,6 @@ function ORBarChart(props: BarChartProps) { }); }); - const xAxis: any = { type: 'category', data: categories, @@ -81,11 +80,11 @@ function ORBarChart(props: BarChartProps) { chart.on('click', (event) => { const index = event.dataIndex; const timestamp = (window as any).__timestampMap?.[chartUuid.current]?.[index]; - props.onClick?.({ activePayload: [{ payload: { timestamp }}]}) + props.onClick?.({ activePayload: [{ payload: { timestamp } }] }); setTimeout(() => { - props.onSeriesFocus?.(event.seriesName) - }, 0) - }) + props.onSeriesFocus?.(event.seriesName); + }, 0); + }); return () => { chart.dispose(); diff --git a/frontend/app/components/Charts/ColumnChart.tsx b/frontend/app/components/Charts/ColumnChart.tsx index f16992761..b19d84abe 100644 --- a/frontend/app/components/Charts/ColumnChart.tsx +++ b/frontend/app/components/Charts/ColumnChart.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { defaultOptions, echarts } from './init'; import { BarChart } from 'echarts/charts'; +import { defaultOptions, echarts } from './init'; import { customTooltipFormatter } from './utils'; -import { buildColumnChart } from './barUtils' +import { buildColumnChart } from './barUtils'; echarts.use([BarChart]); @@ -32,7 +32,7 @@ function ColumnChart(props: ColumnChartProps) { const { data, compData, label } = props; const chartRef = React.useRef(null); const chartUuid = React.useRef( - Math.random().toString(36).substring(7) + Math.random().toString(36).substring(7), ); React.useEffect(() => { @@ -42,10 +42,10 @@ function ColumnChart(props: ColumnChartProps) { (window as any).__seriesValueMap[chartUuid.current] = {}; (window as any).__seriesColorMap = (window as any).__seriesColorMap ?? {}; (window as any).__seriesColorMap[chartUuid.current] = {}; - (window as any).__yAxisData = (window as any).__yAxisData ?? {} + (window as any).__yAxisData = (window as any).__yAxisData ?? {}; const { yAxisData, series } = buildColumnChart(chartUuid.current, data, compData); - (window as any).__yAxisData[chartUuid.current] = yAxisData + (window as any).__yAxisData[chartUuid.current] = yAxisData; chart.setOption({ ...defaultOptions, @@ -89,7 +89,7 @@ function ColumnChart(props: ColumnChartProps) { chart.on('click', (event) => { const focusedSeriesName = event.name; props.onSeriesFocus?.(focusedSeriesName); - }) + }); return () => { chart.dispose(); diff --git a/frontend/app/components/Charts/LineChart.tsx b/frontend/app/components/Charts/LineChart.tsx index 9155ed92c..da73fa7f2 100644 --- a/frontend/app/components/Charts/LineChart.tsx +++ b/frontend/app/components/Charts/LineChart.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { echarts, defaultOptions, initWindowStorages } from './init'; -import { customTooltipFormatter, buildCategories, buildDatasetsAndSeries } from './utils' -import type { DataProps } from './utils' import { LineChart } from 'echarts/charts'; +import { echarts, defaultOptions, initWindowStorages } from './init'; +import { customTooltipFormatter, buildCategories, buildDatasetsAndSeries } from './utils'; +import type { DataProps } from './utils'; echarts.use([LineChart]); @@ -22,7 +22,7 @@ function ORLineChart(props: Props) { React.useEffect(() => { if (!chartRef.current) return; const chart = echarts.init(chartRef.current); - const obs = new ResizeObserver(() => chart.resize()) + const obs = new ResizeObserver(() => chart.resize()); obs.observe(chartRef.current); const categories = buildCategories(props.data); @@ -55,7 +55,7 @@ function ORLineChart(props: Props) { chart.setOption({ ...defaultOptions, title: { - text: props.chartName ?? "Line Chart", + text: props.chartName ?? 'Line Chart', show: false, }, legend: { @@ -75,7 +75,7 @@ function ORLineChart(props: Props) { nameTextStyle: { padding: [0, 0, 0, 15], }, - minInterval: 1 + minInterval: 1, }, tooltip: { ...defaultOptions.tooltip, @@ -92,11 +92,11 @@ function ORLineChart(props: Props) { chart.on('click', (event) => { const index = event.dataIndex; const timestamp = (window as any).__timestampMap?.[chartUuid.current]?.[index]; - props.onClick?.({ activePayload: [{ payload: { timestamp }}]}) + props.onClick?.({ activePayload: [{ payload: { timestamp } }] }); setTimeout(() => { - props.onSeriesFocus?.(event.seriesName) - }, 0) - }) + props.onSeriesFocus?.(event.seriesName); + }, 0); + }); return () => { chart.dispose(); diff --git a/frontend/app/components/Charts/PieChart.tsx b/frontend/app/components/Charts/PieChart.tsx index 86a5c9ade..1e86da7ab 100644 --- a/frontend/app/components/Charts/PieChart.tsx +++ b/frontend/app/components/Charts/PieChart.tsx @@ -22,13 +22,15 @@ interface PieChartProps { } function PieChart(props: PieChartProps) { - const { data, label, onClick = () => {}, inGrid = false } = props; + const { + data, label, onClick = () => {}, inGrid = false, + } = props; const chartRef = useRef(null); useEffect(() => { if (!chartRef.current) return; if (!data.chart || data.chart.length === 0) { - chartRef.current.innerHTML = `
No data available
`; + chartRef.current.innerHTML = '
No data available
'; return; } @@ -36,7 +38,7 @@ function PieChart(props: PieChartProps) { const pieData = buildPieData(data.chart, data.namesMap); if (!pieData.length) { - chartRef.current.innerHTML = `
No data available
`; + chartRef.current.innerHTML = '
No data available
'; return; } @@ -75,28 +77,24 @@ function PieChart(props: PieChartProps) { name: label ?? 'Data', radius: [50, 100], center: ['50%', '55%'], - data: pieData.map((d, idx) => { - return { - name: d.name, - value: d.value, - label: { - show: false, //d.value / largestVal >= 0.03, - position: 'outside', - formatter: (params: any) => { - return params.value; - }, - }, - labelLine: { - show: false, // d.value / largestVal >= 0.03, - length: 10, - length2: 20, - lineStyle: { color: '#3EAAAF' }, - }, - itemStyle: { - color: pickColorByIndex(idx), - }, - }; - }), + data: pieData.map((d, idx) => ({ + name: d.name, + value: d.value, + label: { + show: false, // d.value / largestVal >= 0.03, + position: 'outside', + formatter: (params: any) => params.value, + }, + labelLine: { + show: false, // d.value / largestVal >= 0.03, + length: 10, + length2: 20, + lineStyle: { color: '#3EAAAF' }, + }, + itemStyle: { + color: pickColorByIndex(idx), + }, + })), emphasis: { scale: true, scaleSize: 4, @@ -106,11 +104,11 @@ function PieChart(props: PieChartProps) { }; chartInstance.setOption(option); - const obs = new ResizeObserver(() => chartInstance.resize()) + const obs = new ResizeObserver(() => chartInstance.resize()); obs.observe(chartRef.current); - chartInstance.on('click', function (params) { - const focusedSeriesName = params.name + chartInstance.on('click', (params) => { + const focusedSeriesName = params.name; props.onSeriesFocus?.(focusedSeriesName); }); diff --git a/frontend/app/components/Charts/SankeyChart.tsx b/frontend/app/components/Charts/SankeyChart.tsx index 33197da5e..a0c7e9c8e 100644 --- a/frontend/app/components/Charts/SankeyChart.tsx +++ b/frontend/app/components/Charts/SankeyChart.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { echarts, defaultOptions } from './init'; import { SankeyChart } from 'echarts/charts'; -import { sankeyTooltip, getEventPriority, getNodeName } from './sankeyUtils'; import { NoContent } from 'App/components/ui'; import { InfoCircleOutlined } from '@ant-design/icons'; +import { sankeyTooltip, getEventPriority, getNodeName } from './sankeyUtils'; +import { echarts, defaultOptions } from './init'; echarts.use([SankeyChart]); @@ -36,21 +36,23 @@ interface Props { } const EChartsSankey: React.FC = (props) => { - const { data, height = 240, onChartClick, isUngrouped } = props; + const { + data, height = 240, onChartClick, isUngrouped, + } = props; const chartRef = React.useRef(null); if (data.nodes.length === 0 || data.links.length === 0) { return ( Set a start or end point to visualize the journey. If set, try adjusting filters.
- } - show={true} + )} + show /> ); } @@ -60,8 +62,8 @@ const EChartsSankey: React.FC = (props) => { React.useEffect(() => { if (!chartRef.current) return; - let finalNodes = data.nodes; - let finalLinks = data.links; + const finalNodes = data.nodes; + const finalLinks = data.links; const chart = echarts.init(chartRef.current); @@ -71,8 +73,8 @@ const EChartsSankey: React.FC = (props) => { const sourceNode = finalNodes.find((n) => n.id === l.source); const targetNode = finalNodes.find((n) => n.id === l.target); return ( - (sourceNode?.depth ?? 0) <= maxDepth && - (targetNode?.depth ?? 0) <= maxDepth + (sourceNode?.depth ?? 0) <= maxDepth + && (targetNode?.depth ?? 0) <= maxDepth ); }); @@ -89,10 +91,9 @@ const EChartsSankey: React.FC = (props) => { } else { nodeValues[i] = 0; } - const itemColor = - computedName === 'Others' - ? 'rgba(34,44,154,.9)' - : n.eventType === 'DROP' + const itemColor = computedName === 'Others' + ? 'rgba(34,44,154,.9)' + : n.eventType === 'DROP' ? '#B5B7C8' : '#394eff'; @@ -110,9 +111,8 @@ const EChartsSankey: React.FC = (props) => { return ( getEventPriority(a.type || '') - getEventPriority(b.type || '') ); - } else { - return (a.depth as number) - (b.depth as number); } + return (a.depth as number) - (b.depth as number); }); const echartLinks = filteredLinks.map((l) => ({ @@ -174,25 +174,24 @@ const EChartsSankey: React.FC = (props) => { maxWidth: 30, distance: 3, offset: [-20, 0], - formatter: function (params: any) { + formatter(params: any) { const nodeVal = params.value; const percentage = startNodeValue - ? ((nodeVal / startNodeValue) * 100).toFixed(1) + '%' + ? `${((nodeVal / startNodeValue) * 100).toFixed(1)}%` : '0%'; const maxLen = 20; - const safeName = - params.name.length > maxLen - ? params.name.slice(0, maxLen / 2 - 2) + - '...' + - params.name.slice(-(maxLen / 2 - 2)) - : params.name; + const safeName = params.name.length > maxLen + ? `${params.name.slice(0, maxLen / 2 - 2) + }...${ + params.name.slice(-(maxLen / 2 - 2))}` + : params.name; const nodeType = params.data.type; - const icon = getIcon(nodeType) + const icon = getIcon(nodeType); return ( - `${icon}{header| ${safeName}}\n` + - `{body|}{percentage|${percentage}} {sessions|${nodeVal}}` + `${icon}{header| ${safeName}}\n` + + `{body|}{percentage|${percentage}} {sessions|${nodeVal}}` ); }, rich: { @@ -245,7 +244,7 @@ const EChartsSankey: React.FC = (props) => { }, customEventIcon: { backgroundColor: { - image: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWNvZGUiPjxwb2x5bGluZSBwb2ludHM9IjE2IDE4IDIyIDEyIDE2IDYiLz48cG9seWxpbmUgcG9pbnRzPSI4IDYgMiAxMiA4IDE4Ii8+PC9zdmc+' + image: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWNvZGUiPjxwb2x5bGluZSBwb2ludHM9IjE2IDE4IDIyIDEyIDE2IDYiLz48cG9seWxpbmUgcG9pbnRzPSI4IDYgMiAxMiA4IDE4Ii8+PC9zdmc+', }, height: 20, width: 14, @@ -263,7 +262,7 @@ const EChartsSankey: React.FC = (props) => { }, height: 20, width: 14, - } + }, }, }, tooltip: { @@ -318,17 +317,16 @@ const EChartsSankey: React.FC = (props) => { const originalNodes = [...echartNodes]; const originalLinks = [...echartLinks]; - chart.on('mouseover', function (params: any) { + chart.on('mouseover', (params: any) => { if (params.dataType === 'node') { const hoveredIndex = params.dataIndex; const connectedChain = getConnectedChain(hoveredIndex); const updatedNodes = echartNodes.map((node, idx) => { const baseOpacity = connectedChain.has(idx) ? 1 : 0.35; - const extraStyle = - idx === hoveredIndex - ? { borderColor: '#000', borderWidth: 1, borderType: 'dotted' } - : {}; + const extraStyle = idx === hoveredIndex + ? { borderColor: '#000', borderWidth: 1, borderType: 'dotted' } + : {}; return { ...node, itemStyle: { @@ -361,7 +359,7 @@ const EChartsSankey: React.FC = (props) => { } }); - chart.on('mouseout', function (params: any) { + chart.on('mouseout', (params: any) => { if (params.dataType === 'node') { chart.setOption({ series: [ @@ -374,7 +372,7 @@ const EChartsSankey: React.FC = (props) => { } }); - chart.on('click', function (params: any) { + chart.on('click', (params: any) => { if (!onChartClick) return; const unsupported = ['other', 'drop']; @@ -388,7 +386,7 @@ const EChartsSankey: React.FC = (props) => { } filters.push({ operator: 'is', - type: type, + type, value: [node.name], isEvent: true, }); @@ -403,8 +401,8 @@ const EChartsSankey: React.FC = (props) => { const firstNodeType = firstNode?.eventType?.toLowerCase() ?? 'location'; const lastNodeType = lastNode?.eventType?.toLowerCase() ?? 'location'; if ( - unsupported.includes(firstNodeType) || - unsupported.includes(lastNodeType) + unsupported.includes(firstNodeType) + || unsupported.includes(lastNodeType) ) { return; } @@ -457,7 +455,10 @@ const EChartsSankey: React.FC = (props) => { } return ( -
+
= (props) => { function getIcon(type: string) { if (type === 'LOCATION') { - return '{locationIcon|}' + return '{locationIcon|}'; } if (type === 'INPUT') { - return '{inputIcon|}' + return '{inputIcon|}'; } if (type === 'CUSTOM_EVENT') { - return '{customEventIcon|}' + return '{customEventIcon|}'; } if (type === 'CLICK') { return '{clickIcon|}'; @@ -486,7 +487,7 @@ function getIcon(type: string) { if (type === 'OTHER') { return '{groupIcon|}'; } - return '' + return ''; } export default EChartsSankey; diff --git a/frontend/app/components/Charts/barUtils.ts b/frontend/app/components/Charts/barUtils.ts index 86c55a95d..8dd7f197f 100644 --- a/frontend/app/components/Charts/barUtils.ts +++ b/frontend/app/components/Charts/barUtils.ts @@ -47,7 +47,6 @@ export function buildBarDatasetsAndSeries(props: DataProps) { return { datasets, series }; } - // START GEN function sumSeries(chart: DataItem[], seriesName: string): number { return chart.reduce((acc, row) => acc + (Number(row[seriesName]) || 0), 0); @@ -62,7 +61,7 @@ function sumSeries(chart: DataItem[], seriesName: string): number { export function buildColumnChart( chartUuid: string, data: DataProps['data'], - compData: DataProps['compData'] + compData: DataProps['compData'], ) { const categories = data.namesMap.filter(Boolean); diff --git a/frontend/app/components/Charts/init.ts b/frontend/app/components/Charts/init.ts index 6544dece3..f840bc454 100644 --- a/frontend/app/components/Charts/init.ts +++ b/frontend/app/components/Charts/init.ts @@ -18,7 +18,7 @@ echarts.use([ LegendComponent, // TransformComponent, SVGRenderer, - ToolboxComponent + ToolboxComponent, ]); const defaultOptions = { @@ -38,9 +38,9 @@ const defaultOptions = { type: 'cross', snap: true, label: { - backgroundColor: '#6a7985' + backgroundColor: '#6a7985', }, - } + }, }, grid: { bottom: 20, @@ -56,16 +56,16 @@ const defaultOptions = { feature: { saveAsImage: { pixelRatio: 1.5, - } - } + }, + }, }, legend: { type: 'plain', show: true, top: 10, - icon: 'pin' + icon: 'pin', }, -} +}; export function initWindowStorages(chartUuid: string, categories: string[] = [], chartArr: any[] = [], compChartArr: any[] = []) { (window as any).__seriesValueMap = (window as any).__seriesValueMap ?? {}; @@ -91,4 +91,4 @@ export function initWindowStorages(chartUuid: string, categories: string[] = [], } } -export { echarts, defaultOptions }; \ No newline at end of file +export { echarts, defaultOptions }; diff --git a/frontend/app/components/Charts/pieUtils.ts b/frontend/app/components/Charts/pieUtils.ts index 2c5426cf4..0d441e480 100644 --- a/frontend/app/components/Charts/pieUtils.ts +++ b/frontend/app/components/Charts/pieUtils.ts @@ -1,10 +1,9 @@ -import { colors } from './utils'; import { numberWithCommas } from 'App/utils'; - +import { colors } from './utils'; export function buildPieData( chart: Array>, - namesMap: string[] + namesMap: string[], ) { const result: { name: string; value: number }[] = namesMap.map((name) => { let sum = 0; @@ -17,7 +16,9 @@ export function buildPieData( } export function pieTooltipFormatter(params: any) { - const { name, value, marker, percent } = params; + const { + name, value, marker, percent, + } = params; return `
${marker} ${name}
@@ -28,4 +29,4 @@ export function pieTooltipFormatter(params: any) { export function pickColorByIndex(idx: number) { return colors[idx % colors.length]; -} \ No newline at end of file +} diff --git a/frontend/app/components/Charts/sankeyUtils.ts b/frontend/app/components/Charts/sankeyUtils.ts index a4e0826af..56fa2ea60 100644 --- a/frontend/app/components/Charts/sankeyUtils.ts +++ b/frontend/app/components/Charts/sankeyUtils.ts @@ -1,6 +1,6 @@ export function sankeyTooltip( echartNodes: any[], - nodeValues: Record + nodeValues: Record, ) { return (params: any) => { if ('source' in params.data && 'target' in params.data) { @@ -25,8 +25,8 @@ export function sankeyTooltip(
${params.data.value} ( ${params.data.percentage.toFixed( - 2 - )}% ) + 2, +)}% ) Sessions
@@ -49,13 +49,12 @@ const shortenString = (str: string) => { const limit = 60; const leftPart = 25; const rightPart = 20; - const safeStr = - str.length > limit - ? `${str.slice(0, leftPart)}...${str.slice( - str.length - rightPart, - str.length - )}` - : str; + const safeStr = str.length > limit + ? `${str.slice(0, leftPart)}...${str.slice( + str.length - rightPart, + str.length, + )}` + : str; return safeStr; }; @@ -73,7 +72,7 @@ export const getEventPriority = (type: string): number => { export const getNodeName = ( eventType: string, - nodeName: string | null + nodeName: string | null, ): string => { if (!nodeName) { return eventType.charAt(0) + eventType.slice(1).toLowerCase(); diff --git a/frontend/app/components/Charts/utils.ts b/frontend/app/components/Charts/utils.ts index 8a5454991..1b63f5a71 100644 --- a/frontend/app/components/Charts/utils.ts +++ b/frontend/app/components/Charts/utils.ts @@ -54,7 +54,7 @@ function buildCategoryColorMap(categories: string[]): Record { */ export function assignColorsByCategory( series: any[], - categories: string[] + categories: string[], ) { const categoryColorMap = buildCategoryColorMap(categories); @@ -112,8 +112,8 @@ export function customTooltipFormatter(uuid: string) {
+ params.color +};" class="flex flex-col px-2 ml-2">
Total:
@@ -124,8 +124,7 @@ export function customTooltipFormatter(uuid: string) {
`; if (partnerValue !== undefined) { - const partnerColor = - (window as any).__seriesColorMap?.[uuid]?.[partnerName] || '#999'; + const partnerColor = (window as any).__seriesColorMap?.[uuid]?.[partnerName] || '#999'; str += `
@@ -178,8 +177,8 @@ export function customTooltipFormatter(uuid: string) {
+ params.color +};" class="flex flex-col px-2 ml-2">
${firstTs ? formatTimeOrDate(firstTs) : categoryLabel}
@@ -191,8 +190,7 @@ export function customTooltipFormatter(uuid: string) { `; if (partnerVal !== undefined) { - const partnerColor = - (window as any).__seriesColorMap?.[uuid]?.[partnerName] || '#999'; + const partnerColor = (window as any).__seriesColorMap?.[uuid]?.[partnerName] || '#999'; tooltipContent += `
@@ -262,8 +260,7 @@ export function createDataset(id: string, data: DataProps['data']) { const source = data.chart.map((item, idx) => { const row: (number | undefined)[] = [idx]; data.namesMap.forEach((name) => { - const val = - typeof item[name] === 'number' ? (item[name] as number) : undefined; + const val = typeof item[name] === 'number' ? (item[name] as number) : undefined; row.push(val); }); return row; @@ -279,7 +276,7 @@ export function createSeries( data: DataProps['data'], datasetId: string, dashed: boolean, - hideFromLegend: boolean + hideFromLegend: boolean, ) { return data.namesMap.filter(Boolean).map((fullName) => { const baseName = fullName.replace(/^Previous\s+/, ''); diff --git a/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx b/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx index 634eace5d..f6230296b 100644 --- a/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx +++ b/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx @@ -6,48 +6,48 @@ interface Props { audit: any; } function AuditDetailModal(props: Props) { - const { audit } = props; - // const jsonResponse = typeof audit.payload === 'string' ? JSON.parse(audit.payload) : audit.payload; - // console.log('jsonResponse', jsonResponse) + const { audit } = props; + // const jsonResponse = typeof audit.payload === 'string' ? JSON.parse(audit.payload) : audit.payload; + // console.log('jsonResponse', jsonResponse) - return ( -
-

Audit Details

-
-
{ 'URL'}
-
{ audit.endPoint }
+ return ( +
+

Audit Details

+
+
URL
+
{ audit.endPoint }
-
-
-
Username
-
{audit.username}
-
-
-
Created At
-
{audit.createdAt && checkForRecent(audit.createdAt, 'LLL dd, yyyy, hh:mm a')}
-
-
- -
-
-
Action
-
{audit.action}
-
-
-
Method
-
{audit.method}
-
-
- - { audit.payload && ( -
-
Payload
- -
- )} -
+
+
+
Username
+
{audit.username}
+
+
+
Created At
+
{audit.createdAt && checkForRecent(audit.createdAt, 'LLL dd, yyyy, hh:mm a')}
+
- ); + +
+
+
Action
+
{audit.action}
+
+
+
Method
+
{audit.method}
+
+
+ + { audit.payload && ( +
+
Payload
+ +
+ )} +
+
+ ); } -export default AuditDetailModal; \ No newline at end of file +export default AuditDetailModal; diff --git a/frontend/app/components/Client/Audit/AuditDetailModal/index.ts b/frontend/app/components/Client/Audit/AuditDetailModal/index.ts index fcf6bb2b4..9fe899989 100644 --- a/frontend/app/components/Client/Audit/AuditDetailModal/index.ts +++ b/frontend/app/components/Client/Audit/AuditDetailModal/index.ts @@ -1 +1 @@ -export { default } from './AuditDetailModal'; \ No newline at end of file +export { default } from './AuditDetailModal'; diff --git a/frontend/app/components/Client/Audit/AuditList/AuditList.tsx b/frontend/app/components/Client/Audit/AuditList/AuditList.tsx index 43ba629e3..1f2fb4b83 100644 --- a/frontend/app/components/Client/Audit/AuditList/AuditList.tsx +++ b/frontend/app/components/Client/Audit/AuditList/AuditList.tsx @@ -3,73 +3,73 @@ import { useStore } from 'App/mstore'; import { useObserver } from 'mobx-react-lite'; import React, { useEffect } from 'react'; import { Loader, Pagination, NoContent } from 'UI'; +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import AuditDetailModal from '../AuditDetailModal'; import AuditListItem from '../AuditListItem'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; interface Props { } function AuditList(props: Props) { - const { auditStore } = useStore(); - const loading = useObserver(() => auditStore.isLoading); - const list = useObserver(() => auditStore.list); - const searchQuery = useObserver(() => auditStore.searchQuery); - const page = useObserver(() => auditStore.page); - const order = useObserver(() => auditStore.order); - const period = useObserver(() => auditStore.period); - const { showModal } = useModal(); - - useEffect(() => { - const { startTimestamp, endTimestamp } = period.toTimestamps(); - auditStore.fetchAudits({ - page: auditStore.page, - limit: auditStore.pageSize, - query: auditStore.searchQuery, - order: auditStore.order, - startDate: startTimestamp, - endDate: endTimestamp, - }); - }, [page, searchQuery, order, period]); + const { auditStore } = useStore(); + const loading = useObserver(() => auditStore.isLoading); + const list = useObserver(() => auditStore.list); + const searchQuery = useObserver(() => auditStore.searchQuery); + const page = useObserver(() => auditStore.page); + const order = useObserver(() => auditStore.order); + const period = useObserver(() => auditStore.period); + const { showModal } = useModal(); - return useObserver(() => ( - - - -
No data available
-
- } - size="small" - show={list.length === 0} - > -
-
Name
-
Action
-
Time
-
+ useEffect(() => { + const { startTimestamp, endTimestamp } = period.toTimestamps(); + auditStore.fetchAudits({ + page: auditStore.page, + limit: auditStore.pageSize, + query: auditStore.searchQuery, + order: auditStore.order, + startDate: startTimestamp, + endDate: endTimestamp, + }); + }, [page, searchQuery, order, period]); - {list.map((item, index) => ( - showModal(, { right: true, width: 500 })} - /> - ))} - -
- auditStore.updateKey('page', page)} - limit={auditStore.pageSize} - debounceRequest={200} - /> -
- - - )); + return useObserver(() => ( + + + +
No data available
+
+ )} + size="small" + show={list.length === 0} + > +
+
Name
+
Action
+
Time
+
+ + {list.map((item, index) => ( + showModal(, { right: true, width: 500 })} + /> + ))} + +
+ auditStore.updateKey('page', page)} + limit={auditStore.pageSize} + debounceRequest={200} + /> +
+ + + )); } -export default AuditList; \ No newline at end of file +export default AuditList; diff --git a/frontend/app/components/Client/Audit/AuditList/index.ts b/frontend/app/components/Client/Audit/AuditList/index.ts index 2e6bc3739..6f70bca2f 100644 --- a/frontend/app/components/Client/Audit/AuditList/index.ts +++ b/frontend/app/components/Client/Audit/AuditList/index.ts @@ -1 +1 @@ -export { default } from './AuditList' \ No newline at end of file +export { default } from './AuditList'; diff --git a/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx b/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx index 2c9792d33..993e9dbf6 100644 --- a/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx +++ b/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx @@ -6,14 +6,14 @@ interface Props { onShowDetails: () => void; } function AuditListItem(props: Props) { - const { audit, onShowDetails } = props; - return ( -
-
{audit.username}
-
{audit.action}
-
{audit.createdAt && checkForRecent(audit.createdAt, 'LLL dd, yyyy, hh:mm a')}
-
- ); + const { audit, onShowDetails } = props; + return ( +
+
{audit.username}
+
{audit.action}
+
{audit.createdAt && checkForRecent(audit.createdAt, 'LLL dd, yyyy, hh:mm a')}
+
+ ); } -export default AuditListItem; \ No newline at end of file +export default AuditListItem; diff --git a/frontend/app/components/Client/Audit/AuditListItem/index.ts b/frontend/app/components/Client/Audit/AuditListItem/index.ts index 821ee9639..dbd6b2a5f 100644 --- a/frontend/app/components/Client/Audit/AuditListItem/index.ts +++ b/frontend/app/components/Client/Audit/AuditListItem/index.ts @@ -1 +1 @@ -export { default } from './AuditListItem'; \ No newline at end of file +export { default } from './AuditListItem'; diff --git a/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx b/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx index 93adf3d3e..0dc368f6e 100644 --- a/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx +++ b/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx @@ -2,33 +2,33 @@ import React, { useEffect } from 'react'; import { Icon, Input } from 'UI'; import { debounce } from 'App/utils'; -let debounceUpdate: any = () => {} +let debounceUpdate: any = () => {}; interface Props { onChange: (value: string) => void; } function AuditSearchField(props: Props) { - const { onChange } = props; - - useEffect(() => { - debounceUpdate = debounce((value) => onChange(value), 500); - }, []) + const { onChange } = props; - const write = ({ target: { name, value } }) => { - debounceUpdate(value); - } + useEffect(() => { + debounceUpdate = debounce((value) => onChange(value), 500); + }, []); - return ( -
- - { + debounceUpdate(value); + }; + + return ( +
+ + -
- ); + placeholder="Filter by name" + onChange={write} + icon="search" + /> +
+ ); } -export default AuditSearchField; \ No newline at end of file +export default AuditSearchField; diff --git a/frontend/app/components/Client/Audit/AuditSearchField/index.ts b/frontend/app/components/Client/Audit/AuditSearchField/index.ts index 646947095..ac0f6c188 100644 --- a/frontend/app/components/Client/Audit/AuditSearchField/index.ts +++ b/frontend/app/components/Client/Audit/AuditSearchField/index.ts @@ -1 +1 @@ -export { default } from './AuditSearchField'; \ No newline at end of file +export { default } from './AuditSearchField'; diff --git a/frontend/app/components/Client/Audit/AuditView/AuditView.tsx b/frontend/app/components/Client/Audit/AuditView/AuditView.tsx index 1fde1ff31..986b16f58 100644 --- a/frontend/app/components/Client/Audit/AuditView/AuditView.tsx +++ b/frontend/app/components/Client/Audit/AuditView/AuditView.tsx @@ -1,77 +1,77 @@ import React, { useEffect } from 'react'; import { PageTitle, Icon } from 'UI'; -import { Button } from 'antd' -import AuditList from '../AuditList'; -import AuditSearchField from '../AuditSearchField'; +import { Button } from 'antd'; import { useStore } from 'App/mstore'; import { useObserver } from 'mobx-react-lite'; import Select from 'Shared/Select'; import SelectDateRange from 'Shared/SelectDateRange'; import { numberWithCommas } from 'App/utils'; import withPageTitle from 'HOCs/withPageTitle'; +import AuditSearchField from '../AuditSearchField'; +import AuditList from '../AuditList'; function AuditView() { - const { auditStore } = useStore(); - const order = useObserver(() => auditStore.order); - const total = useObserver(() => numberWithCommas(auditStore.total)); + const { auditStore } = useStore(); + const order = useObserver(() => auditStore.order); + const total = useObserver(() => numberWithCommas(auditStore.total)); - useEffect(() => { - return () => { - auditStore.updateKey('searchQuery', ''); - } - }, []) + useEffect(() => () => { + auditStore.updateKey('searchQuery', ''); + }, []); - const exportToCsv = () => { - auditStore.exportToCsv(); - } + const exportToCsv = () => { + auditStore.exportToCsv(); + }; - const onChange = (data) => { - auditStore.setDateRange(data); - } + const onChange = (data) => { + auditStore.setDateRange(data); + }; - return useObserver(() => ( -
-
- - Audit Trail - {total} -
- } /> -
-
- -
-
- auditStore.updateKey('order', value.value)} + /> +
+ { + auditStore.updateKey('searchQuery', value); + auditStore.updateKey('page', 1); + }} + /> +
+ +
- )); +
+ + +
+ )); } -export default withPageTitle('Audit Trail - OpenReplay Preferences')(AuditView); \ No newline at end of file +export default withPageTitle('Audit Trail - OpenReplay Preferences')(AuditView); diff --git a/frontend/app/components/Client/Audit/AuditView/index.ts b/frontend/app/components/Client/Audit/AuditView/index.ts index ba32b1be0..fcaf5cf0c 100644 --- a/frontend/app/components/Client/Audit/AuditView/index.ts +++ b/frontend/app/components/Client/Audit/AuditView/index.ts @@ -1 +1 @@ -export { default } from './AuditView' \ No newline at end of file +export { default } from './AuditView'; diff --git a/frontend/app/components/Client/Client.tsx b/frontend/app/components/Client/Client.tsx index 06991988d..1b7d089bc 100644 --- a/frontend/app/components/Client/Client.tsx +++ b/frontend/app/components/Client/Client.tsx @@ -3,6 +3,8 @@ import { withRouter } from 'react-router-dom'; import { Switch, Route, Redirect } from 'react-router'; import { CLIENT_TABS, client as clientRoute } from 'App/routes'; +import SessionsListingSettings from 'Components/Client/SessionsListingSettings'; +import Modules from 'Components/Client/Modules'; import ProfileSettings from './ProfileSettings'; import Integrations from './Integrations'; import UserView from './Users/UsersView'; @@ -13,8 +15,6 @@ import CustomFields from './CustomFields'; import Webhooks from './Webhooks'; import Notifications from './Notifications'; import Roles from './Roles'; -import SessionsListingSettings from 'Components/Client/SessionsListingSettings'; -import Modules from 'Components/Client/Modules'; @withRouter export default class Client extends React.PureComponent { @@ -46,11 +46,11 @@ export default class Client extends React.PureComponent { render() { const { match: { - params: { activeTab } - } + params: { activeTab }, + }, } = this.props; return ( -
+
{activeTab && this.renderActiveTab()}
); diff --git a/frontend/app/components/Client/CustomFields/CustomFieldForm.js b/frontend/app/components/Client/CustomFields/CustomFieldForm.js index 19cf244d2..2c42e3d3e 100644 --- a/frontend/app/components/Client/CustomFields/CustomFieldForm.js +++ b/frontend/app/components/Client/CustomFields/CustomFieldForm.js @@ -4,7 +4,9 @@ import { edit, save } from 'Duck/customField'; import { Form, Input, Button } from 'UI'; import styles from './customFieldForm.module.css'; -const CustomFieldForm = ({ field, saving, errors, edit, save, onSave, onClose, onDelete }) => { +function CustomFieldForm({ + field, saving, errors, edit, save, onSave, onClose, onDelete, +}) { const focusElementRef = useRef(null); const setFocus = () => focusElementRef.current.focus(); @@ -15,10 +17,14 @@ const CustomFieldForm = ({ field, saving, errors, edit, save, onSave, onClose, o return (
-

{exists ? 'Update' : 'Add'} Metadata Field

+

+ {exists ? 'Update' : 'Add'} + {' '} + Metadata Field +

- +
- +
); -}; +} const mapStateToProps = (state) => ({ field: state.getIn(['customFields', 'instance']), saving: state.getIn(['customFields', 'saveRequest', 'loading']), - errors: state.getIn(['customFields', 'saveRequest', 'errors']) + errors: state.getIn(['customFields', 'saveRequest', 'errors']), }); export default connect(mapStateToProps, { edit, save })(CustomFieldForm); diff --git a/frontend/app/components/Client/CustomFields/CustomFieldForm.tsx b/frontend/app/components/Client/CustomFields/CustomFieldForm.tsx index 82c0372d0..64428995c 100644 --- a/frontend/app/components/Client/CustomFields/CustomFieldForm.tsx +++ b/frontend/app/components/Client/CustomFields/CustomFieldForm.tsx @@ -1,12 +1,12 @@ import React, { useRef, useState } from 'react'; import { Form, Input } from 'UI'; -import styles from './customFieldForm.module.css'; import { useStore } from 'App/mstore'; import { useModal } from 'Components/Modal'; import { toast } from 'react-toastify'; import { Button, Modal } from 'antd'; import { Trash } from 'UI/Icons'; import { observer } from 'mobx-react-lite'; +import styles from './customFieldForm.module.css'; interface CustomFieldFormProps { siteId: string; @@ -25,11 +25,11 @@ const CustomFieldForm: React.FC = ({ siteId }) => { const onDelete = async () => { Modal.confirm({ title: 'Metadata', - content: `Are you sure you want to remove?`, + content: 'Are you sure you want to remove?', onOk: async () => { await store.remove(siteId, field?.index!); hideModal(); - } + }, }); }; @@ -51,10 +51,14 @@ const CustomFieldForm: React.FC = ({ siteId }) => { return (
-

{exists ? 'Update' : 'Add'} Metadata Field

+

+ {exists ? 'Update' : 'Add'} + {' '} + Metadata Field +

- + = ({ siteId }) => { > {exists ? 'Update' : 'Add'} -
- +
diff --git a/frontend/app/components/Client/CustomFields/CustomFields.tsx b/frontend/app/components/Client/CustomFields/CustomFields.tsx index d7e978d20..85061f84e 100644 --- a/frontend/app/components/Client/CustomFields/CustomFields.tsx +++ b/frontend/app/components/Client/CustomFields/CustomFields.tsx @@ -1,16 +1,17 @@ import React, { useEffect, useState } from 'react'; -import CustomFieldForm from './CustomFieldForm'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import { useModal } from 'App/components/Modal'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; -import { List, Space, Typography, Button, Tooltip, Empty } from 'antd'; +import { + List, Space, Typography, Button, Tooltip, Empty, +} from 'antd'; import { PlusIcon, Tags } from 'lucide-react'; -import {EditOutlined } from '@ant-design/icons'; +import { EditOutlined } from '@ant-design/icons'; import usePageTitle from '@/hooks/usePageTitle'; +import CustomFieldForm from './CustomFieldForm'; - -const CustomFields = () => { +function CustomFields() { usePageTitle('Metadata - OpenReplay Preferences'); const { customFieldStore: store, projectsStore } = useStore(); const currentSite = projectsStore.config.project; @@ -27,8 +28,8 @@ const CustomFields = () => { const handleInit = (field?: any) => { store.init(field); - showModal(, { - title: field ? 'Edit Metadata' : 'Add Metadata', right: true + showModal(, { + title: field ? 'Edit Metadata' : 'Add Metadata', right: true, }); }; @@ -39,7 +40,7 @@ const CustomFields = () => { Attach key-value pairs to session replays for enhanced filtering, searching, and identifying relevant user sessions. - + Learn more @@ -48,13 +49,17 @@ const CustomFields = () => { 0 ? '' : 'You\'ve reached the limit of 10 metadata.'} > - - {/*{remaining === 0 && }*/} + {/* {remaining === 0 && } */} {remaining === 0 ? 'You have reached the limit of 10 metadata.' : `${remaining}/10 Remaining for this project`} @@ -62,7 +67,7 @@ const CustomFields = () => { } /> + emptyText: } />, }} loading={loading} dataSource={fields} @@ -71,7 +76,7 @@ const CustomFields = () => { onClick={() => handleInit(field)} className="cursor-pointer group hover:bg-active-blue !px-4" actions={[ -
); -}; +} export default observer(CustomFields); diff --git a/frontend/app/components/Client/CustomFields/ListItem.js b/frontend/app/components/Client/CustomFields/ListItem.js index 00c484c6e..2dc945ee0 100644 --- a/frontend/app/components/Client/CustomFields/ListItem.js +++ b/frontend/app/components/Client/CustomFields/ListItem.js @@ -4,24 +4,24 @@ import { Icon } from 'UI'; import { Button } from 'antd'; import styles from './listItem.module.css'; -const ListItem = ({ field, onEdit, disabled }) => { +function ListItem({ field, onEdit, disabled }) { return (
field.index !== 0 && onEdit(field)} > {field.key}
-
); -}; +} export default ListItem; diff --git a/frontend/app/components/Client/CustomFields/index.js b/frontend/app/components/Client/CustomFields/index.js index 2b1c8b48b..8519422a1 100644 --- a/frontend/app/components/Client/CustomFields/index.js +++ b/frontend/app/components/Client/CustomFields/index.js @@ -1 +1 @@ -export { default } from './CustomFields'; \ No newline at end of file +export { default } from './CustomFields'; diff --git a/frontend/app/components/Client/DebugLog.tsx b/frontend/app/components/Client/DebugLog.tsx index 0a5f8f292..006080bd7 100644 --- a/frontend/app/components/Client/DebugLog.tsx +++ b/frontend/app/components/Client/DebugLog.tsx @@ -1,33 +1,32 @@ -import React from 'react' -import { KEY, options } from 'App/dev/console' +import React from 'react'; +import { KEY, options } from 'App/dev/console'; import { Switch } from 'UI'; function getDefaults() { - const storedString = localStorage.getItem(KEY) + const storedString = localStorage.getItem(KEY); if (storedString) { - const storedOptions = JSON.parse(storedString) - return storedOptions.verbose - } else { - return false + const storedOptions = JSON.parse(storedString); + return storedOptions.verbose; } + return false; } function DebugLog() { - const [showLogs, setShowLogs] = React.useState(getDefaults) + const [showLogs, setShowLogs] = React.useState(getDefaults); const onChange = (checked: boolean) => { - setShowLogs(checked) - options.logStuff(checked) - } + setShowLogs(checked); + options.logStuff(checked); + }; return (
-

Player Debug Logs

-
Show debug information in browser console.
-
+

Player Debug Logs

+
Show debug information in browser console.
+
- ) + ); } -export default DebugLog \ No newline at end of file +export default DebugLog; diff --git a/frontend/app/components/Client/Integrations/Backend/DatadogForm/DatadogFormModal.tsx b/frontend/app/components/Client/Integrations/Backend/DatadogForm/DatadogFormModal.tsx index 2910621d0..1a5f04dd0 100644 --- a/frontend/app/components/Client/Integrations/Backend/DatadogForm/DatadogFormModal.tsx +++ b/frontend/app/components/Client/Integrations/Backend/DatadogForm/DatadogFormModal.tsx @@ -23,15 +23,15 @@ const initialValues = { app_key: '', }; -const DatadogFormModal = ({ +function DatadogFormModal({ onClose, integrated, }: { onClose: () => void; integrated: boolean; -}) => { +}) { const { integrationsStore } = useStore(); - const siteId = integrationsStore.integrations.siteId; + const { siteId } = integrationsStore.integrations; const { data = initialValues, @@ -39,7 +39,9 @@ const DatadogFormModal = ({ saveMutation, removeMutation, } = useIntegration('datadog', siteId, initialValues); - const { values, errors, handleChange, hasErrors, checkErrors } = useForm(data, { + const { + values, errors, handleChange, hasErrors, checkErrors, + } = useForm(data, { site: { required: true, }, @@ -59,7 +61,7 @@ const DatadogFormModal = ({ try { await saveMutation.mutateAsync({ values, siteId, exists }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -68,7 +70,7 @@ const DatadogFormModal = ({ try { await removeMutation.mutateAsync({ siteId }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -117,7 +119,7 @@ const DatadogFormModal = ({ onChange={handleChange} errors={errors.app_key} /> -
+
)}
@@ -137,7 +139,7 @@ const DatadogFormModal = ({
); -}; +} DatadogFormModal.displayName = 'DatadogForm'; diff --git a/frontend/app/components/Client/Integrations/Backend/DynatraceForm/DynatraceFormModal.tsx b/frontend/app/components/Client/Integrations/Backend/DynatraceForm/DynatraceFormModal.tsx index 325fd6079..3054b5cd4 100644 --- a/frontend/app/components/Client/Integrations/Backend/DynatraceForm/DynatraceFormModal.tsx +++ b/frontend/app/components/Client/Integrations/Backend/DynatraceForm/DynatraceFormModal.tsx @@ -24,22 +24,24 @@ const initialValues = { client_secret: '', resource: '', }; -const DynatraceFormModal = ({ +function DynatraceFormModal({ onClose, integrated, }: { onClose: () => void; integrated: boolean; -}) => { +}) { const { integrationsStore } = useStore(); - const siteId = integrationsStore.integrations.siteId; + const { siteId } = integrationsStore.integrations; const { data = initialValues, isPending, saveMutation, removeMutation, } = useIntegration('dynatrace', siteId, initialValues); - const { values, errors, handleChange, hasErrors, checkErrors } = useForm(data, { + const { + values, errors, handleChange, hasErrors, checkErrors, + } = useForm(data, { environment: { required: true, }, @@ -62,7 +64,7 @@ const DynatraceFormModal = ({ try { await saveMutation.mutateAsync({ values, siteId, exists }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -71,7 +73,7 @@ const DynatraceFormModal = ({ try { await removeMutation.mutateAsync({ siteId }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -136,7 +138,7 @@ const DynatraceFormModal = ({ errors={errors.resource} /> -
+
)}
@@ -156,7 +158,7 @@ const DynatraceFormModal = ({
); -}; +} DynatraceFormModal.displayName = 'DynatraceFormModal'; diff --git a/frontend/app/components/Client/Integrations/Backend/ElasticForm/ElasticFormModal.tsx b/frontend/app/components/Client/Integrations/Backend/ElasticForm/ElasticFormModal.tsx index f86dfbd79..3feb1087c 100644 --- a/frontend/app/components/Client/Integrations/Backend/ElasticForm/ElasticFormModal.tsx +++ b/frontend/app/components/Client/Integrations/Backend/ElasticForm/ElasticFormModal.tsx @@ -33,14 +33,16 @@ function ElasticsearchForm({ integrated: boolean; }) { const { integrationsStore } = useStore(); - const siteId = integrationsStore.integrations.siteId; + const { siteId } = integrationsStore.integrations; const { data = initialValues, isPending, saveMutation, removeMutation, } = useIntegration('elasticsearch', siteId, initialValues); - const { values, errors, handleChange, hasErrors, checkErrors } = useForm(data, { + const { + values, errors, handleChange, hasErrors, checkErrors, + } = useForm(data, { url: { required: true, }, @@ -60,7 +62,7 @@ function ElasticsearchForm({ try { await saveMutation.mutateAsync({ values, siteId, exists }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -69,7 +71,7 @@ function ElasticsearchForm({ try { await removeMutation.mutateAsync({ siteId }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -126,7 +128,7 @@ function ElasticsearchForm({ onChange={handleChange} errors={errors.indexes} /> -
+
)}
diff --git a/frontend/app/components/Client/Integrations/Backend/SentryForm/SentryFormModal.tsx b/frontend/app/components/Client/Integrations/Backend/SentryForm/SentryFormModal.tsx index 76b427bfd..4aa7d482e 100644 --- a/frontend/app/components/Client/Integrations/Backend/SentryForm/SentryFormModal.tsx +++ b/frontend/app/components/Client/Integrations/Backend/SentryForm/SentryFormModal.tsx @@ -33,14 +33,16 @@ function SentryForm({ integrated: boolean; }) { const { integrationsStore } = useStore(); - const siteId = integrationsStore.integrations.siteId; + const { siteId } = integrationsStore.integrations; const { data = initialValues, isPending, saveMutation, removeMutation, } = useIntegration('sentry', siteId, initialValues); - const { values, errors, handleChange, hasErrors, checkErrors, } = useForm(data, { + const { + values, errors, handleChange, hasErrors, checkErrors, + } = useForm(data, { url: { required: false, }, @@ -63,7 +65,7 @@ function SentryForm({ try { await saveMutation.mutateAsync({ values, siteId, exists }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -72,7 +74,7 @@ function SentryForm({ try { await removeMutation.mutateAsync({ siteId }); } catch (e) { - console.error(e) + console.error(e); } onClose(); }; @@ -130,7 +132,7 @@ function SentryForm({ errors={errors.token} /> -
+
)}
diff --git a/frontend/app/components/Client/Integrations/FormField.tsx b/frontend/app/components/Client/Integrations/FormField.tsx index e6e17ea2f..463bc41c0 100644 --- a/frontend/app/components/Client/Integrations/FormField.tsx +++ b/frontend/app/components/Client/Integrations/FormField.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { Input } from 'antd' +import React from 'react'; +import { Input } from 'antd'; export function FormField({ label, @@ -30,4 +30,4 @@ export function FormField({
); } -export default FormField; \ No newline at end of file +export default FormField; diff --git a/frontend/app/components/Client/Integrations/GithubForm.js b/frontend/app/components/Client/Integrations/GithubForm.js index b54343c5f..060fa3062 100644 --- a/frontend/app/components/Client/Integrations/GithubForm.js +++ b/frontend/app/components/Client/Integrations/GithubForm.js @@ -1,32 +1,37 @@ import React from 'react'; -import IntegrationForm from './IntegrationForm'; import DocLink from 'Shared/DocLink/DocLink'; import IntegrationModalCard from 'Components/Client/Integrations/IntegrationModalCard'; +import IntegrationForm from './IntegrationForm'; -const GithubForm = (props) => ( -
- -
-
Integrate GitHub with OpenReplay and create issues directly from the recording page.
-
- +function GithubForm(props) { + return ( +
+ +
+
Integrate GitHub with OpenReplay and create issues directly from the recording page.
+
+ +
+
- -
-); + ); +} GithubForm.displayName = 'GithubForm'; diff --git a/frontend/app/components/Client/Integrations/IntegrationFilters.tsx b/frontend/app/components/Client/Integrations/IntegrationFilters.tsx index 898d38587..b1cf3ffcf 100644 --- a/frontend/app/components/Client/Integrations/IntegrationFilters.tsx +++ b/frontend/app/components/Client/Integrations/IntegrationFilters.tsx @@ -4,7 +4,6 @@ import React from 'react'; import { Icon } from 'UI'; - interface Props { onChange: any; activeItem: string; @@ -14,23 +13,22 @@ interface Props { const allItem = { key: 'all', title: 'All' }; function IntegrationFilters(props: Props) { - const segmentItems = [allItem, ...props.filters].map((item: any) => ({ key: item.key, value: item.key, label: ( -
- {item.icon ? : null} +
+ {item.icon ? : null}
{item.title}
), - })) + })); const onChange = (val) => { - props.onChange(val) - } + props.onChange(val); + }; return ( -
+
{ void fetchIntegrationList(initialSiteId); }; - const write = ({ target: { value, name: key, type, checked } }) => { + const write = ({ + target: { + value, name: key, type, checked, + }, + }) => { if (type === 'checkbox') edit({ [key]: checked }); else edit({ [key]: value }); }; @@ -65,10 +71,9 @@ function IntegrationForm(props: any) { type = 'text', checkIfDisplayed, autoFocus = false, - }) => - (typeof checkIfDisplayed !== 'function' || - checkIfDisplayed(config)) && - (type === 'checkbox' ? ( + }) => (typeof checkIfDisplayed !== 'function' + || checkIfDisplayed(config)) + && (type === 'checkbox' ? ( - )) + )), )} )} diff --git a/frontend/app/components/Client/Integrations/IntegrationItem.tsx b/frontend/app/components/Client/Integrations/IntegrationItem.tsx index 4c4e4db5e..2dd3041b8 100644 --- a/frontend/app/components/Client/Integrations/IntegrationItem.tsx +++ b/frontend/app/components/Client/Integrations/IntegrationItem.tsx @@ -1,8 +1,8 @@ import React from 'react'; import cn from 'classnames'; import { Icon } from 'UI'; -import stl from './integrationItem.module.css'; import { Tooltip } from 'antd'; +import stl from './integrationItem.module.css'; interface Props { integration: any; @@ -12,32 +12,34 @@ interface Props { useIcon?: boolean; } -const IntegrationItem = (props: Props) => { - const { integration, integrated, hide = false, useIcon } = props; +function IntegrationItem(props: Props) { + const { + integration, integrated, hide = false, useIcon, + } = props; return hide ? null : (
props.onClick(e)} style={{ height: '136px' }} > -
+
- {useIcon ? : integration} + {useIcon ? : integration}
-
-

{integration.title}

-

{integration.subtitle && integration.subtitle}

+
+

{integration.title}

+

{integration.subtitle && integration.subtitle}

{integrated && ( -
- - Integrated -
+
+ + Integrated +
)}
); -}; +} export default IntegrationItem; diff --git a/frontend/app/components/Client/Integrations/IntegrationModalCard.tsx b/frontend/app/components/Client/Integrations/IntegrationModalCard.tsx index 37ff588f0..5bc4cfee9 100644 --- a/frontend/app/components/Client/Integrations/IntegrationModalCard.tsx +++ b/frontend/app/components/Client/Integrations/IntegrationModalCard.tsx @@ -9,18 +9,20 @@ interface Props { } function IntegrationModalCard(props: Props) { - const { title, icon, description, useIcon } = props; + const { + title, icon, description, useIcon, + } = props; return ( -
-
- {useIcon ? : integration} +
+
+ {useIcon ? : integration}
-

{title}

+

{title}

{description}
); } -export default IntegrationModalCard; \ No newline at end of file +export default IntegrationModalCard; diff --git a/frontend/app/components/Client/Integrations/Integrations.tsx b/frontend/app/components/Client/Integrations/Integrations.tsx index b00e5a0b7..a7ee142bd 100644 --- a/frontend/app/components/Client/Integrations/Integrations.tsx +++ b/frontend/app/components/Client/Integrations/Integrations.tsx @@ -37,7 +37,7 @@ interface Props { function Integrations(props: Props) { const { integrationsStore, projectsStore } = useStore(); const initialSiteId = projectsStore.siteId; - const siteId = integrationsStore.integrations.siteId; + const { siteId } = integrationsStore.integrations; const fetchIntegrationList = integrationsStore.integrations.fetchIntegrations; const storeIntegratedList = integrationsStore.integrations.list; const { hideHeader = false } = props; @@ -61,9 +61,9 @@ function Integrations(props: Props) { const onClick = (integration: any, width: number) => { if ( - integration.slug && - integration.slug !== 'slack' && - integration.slug !== 'msteams' + integration.slug + && integration.slug !== 'slack' + && integration.slug !== 'msteams' ) { const intName = integration.slug as | 'sentry' @@ -86,7 +86,7 @@ function Integrations(props: Props) { siteId, onClose: hideModal, }), - { right: true, width } + { right: true, width }, ); }; @@ -110,7 +110,7 @@ function Integrations(props: Props) { })); const allIntegrations = filteredIntegrations.flatMap( - (cat) => cat.integrations + (cat) => cat.integrations, ); const onChangeSelect = ({ value }: any) => { @@ -120,7 +120,7 @@ function Integrations(props: Props) { return ( <>
-
+
{!hideHeader && Integrations
} />}
@@ -134,7 +134,7 @@ function Integrations(props: Props) {
{allIntegrations.map((integration, i) => ( @@ -142,21 +142,17 @@ function Integrations(props: Props) { integrated={integratedList.includes(integration.slug)} integration={integration} useIcon={integration.useIcon} - onClick={() => - onClick( - integration, - filteredIntegrations.find((cat) => - cat.integrations.includes(integration) - )?.title === 'Plugins' - ? 500 - : 350 - ) - } + onClick={() => onClick( + integration, + filteredIntegrations.find((cat) => cat.integrations.includes(integration))?.title === 'Plugins' + ? 500 + : 350, + )} hide={ - (integration.slug === 'github' && - integratedList.includes('jira')) || - (integration.slug === 'jira' && - integratedList.includes('github')) + (integration.slug === 'github' + && integratedList.includes('jira')) + || (integration.slug === 'jira' + && integratedList.includes('github')) } /> @@ -167,7 +163,7 @@ function Integrations(props: Props) { } export default withPageTitle('Integrations - OpenReplay Preferences')( - observer(Integrations) + observer(Integrations), ); const integrations = [ diff --git a/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js b/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js index dc8f3e49f..bb182b9b3 100644 --- a/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js +++ b/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js @@ -1,56 +1,60 @@ import React from 'react'; -import IntegrationForm from '../IntegrationForm'; import DocLink from 'Shared/DocLink/DocLink'; import { useModal } from 'App/components/Modal'; import IntegrationModalCard from 'Components/Client/Integrations/IntegrationModalCard'; +import IntegrationForm from '../IntegrationForm'; -const JiraForm = (props) => { +function JiraForm(props) { const { hideModal } = useModal(); return ( -
- +
+ - -
-
How it works?
-
    +
    +
    How it works?
    +
    1. Create a new API token
    2. Enter the token below
    -
    - +
    +
    -
    ); -}; +} JiraForm.displayName = 'JiraForm'; diff --git a/frontend/app/components/Client/Integrations/JiraForm/index.js b/frontend/app/components/Client/Integrations/JiraForm/index.js index d914b3234..8f007bd52 100644 --- a/frontend/app/components/Client/Integrations/JiraForm/index.js +++ b/frontend/app/components/Client/Integrations/JiraForm/index.js @@ -1 +1 @@ -export { default } from './JiraForm'; \ No newline at end of file +export { default } from './JiraForm'; diff --git a/frontend/app/components/Client/Integrations/ProfilerDoc/ProfilerDoc.js b/frontend/app/components/Client/Integrations/ProfilerDoc/ProfilerDoc.js index 171224871..a319a7820 100644 --- a/frontend/app/components/Client/Integrations/ProfilerDoc/ProfilerDoc.js +++ b/frontend/app/components/Client/Integrations/ProfilerDoc/ProfilerDoc.js @@ -1,4 +1,4 @@ -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import React from 'react'; import { observer } from 'mobx-react-lite'; import { CodeBlock } from 'UI'; @@ -6,11 +6,11 @@ import { CodeBlock } from 'UI'; import DocLink from 'Shared/DocLink/DocLink'; import ToggleContent from 'Shared/ToggleContent'; -const ProfilerDoc = () => { +function ProfilerDoc() { const { integrationsStore, projectsStore } = useStore(); const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; const usage = `import OpenReplay from '@openreplay/tracker'; import trackerProfiler from '@openreplay/tracker-profiler'; @@ -58,8 +58,8 @@ const fn = profiler('call_name')(() => {
    Installation
    Usage
    @@ -72,8 +72,8 @@ const fn = profiler('call_name')(() => {
    Usage
    } - second={} + first={} + second={} /> {
); -}; +} ProfilerDoc.displayName = 'ProfilerDoc'; diff --git a/frontend/app/components/Client/Integrations/ProfilerDoc/index.js b/frontend/app/components/Client/Integrations/ProfilerDoc/index.js index 5a3da5d09..3a5655ce7 100644 --- a/frontend/app/components/Client/Integrations/ProfilerDoc/index.js +++ b/frontend/app/components/Client/Integrations/ProfilerDoc/index.js @@ -1 +1 @@ -export { default } from './ProfilerDoc' \ No newline at end of file +export { default } from './ProfilerDoc'; diff --git a/frontend/app/components/Client/Integrations/SlackAddForm/SlackAddForm.js b/frontend/app/components/Client/Integrations/SlackAddForm/SlackAddForm.js index 79feddbc3..5e2cfe029 100644 --- a/frontend/app/components/Client/Integrations/SlackAddForm/SlackAddForm.js +++ b/frontend/app/components/Client/Integrations/SlackAddForm/SlackAddForm.js @@ -1,25 +1,24 @@ import React from 'react'; -import { Form, Input, Message, confirm } from 'UI'; -import { Button } from 'antd' -import { observer } from 'mobx-react-lite' -import { useStore } from 'App/mstore' +import { + Form, Input, Message, confirm, +} from 'UI'; +import { Button } from 'antd'; +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; function SlackAddForm(props) { const { onClose } = props; const { integrationsStore } = useStore(); - const instance = integrationsStore.slack.instance; + const { instance } = integrationsStore.slack; const saving = integrationsStore.slack.loading; - const errors = integrationsStore.slack.errors; - const edit = integrationsStore.slack.edit; + const { errors } = integrationsStore.slack; + const { edit } = integrationsStore.slack; const onSave = integrationsStore.slack.saveIntegration; - const update = integrationsStore.slack.update; - const init = integrationsStore.slack.init; + const { update } = integrationsStore.slack; + const { init } = integrationsStore.slack; const onRemove = integrationsStore.slack.removeInt; - - React.useEffect(() => { - return () => init({}) - }, []) + React.useEffect(() => () => init({}), []); const save = () => { if (instance.exists()) { @@ -34,7 +33,7 @@ function SlackAddForm(props) { await confirm({ header: 'Confirm', confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this channel?`, + confirmation: 'Are you sure you want to permanently delete this channel?', }) ) { await onRemove(id); @@ -43,7 +42,7 @@ function SlackAddForm(props) { }; const write = ({ target: { name, value } }) => edit({ [name]: value }); - + return (
@@ -79,11 +78,11 @@ function SlackAddForm(props) { {instance.exists() ? 'Update' : 'Add'} - +
diff --git a/frontend/app/components/Client/Integrations/SlackAddForm/index.js b/frontend/app/components/Client/Integrations/SlackAddForm/index.js index beb10bb6d..33b9a4b2f 100644 --- a/frontend/app/components/Client/Integrations/SlackAddForm/index.js +++ b/frontend/app/components/Client/Integrations/SlackAddForm/index.js @@ -1 +1 @@ -export { default } from './SlackAddForm' \ No newline at end of file +export { default } from './SlackAddForm'; diff --git a/frontend/app/components/Client/Integrations/SlackChannelList/SlackChannelList.js b/frontend/app/components/Client/Integrations/SlackChannelList/SlackChannelList.js index db53d3100..04597dcf3 100644 --- a/frontend/app/components/Client/Integrations/SlackChannelList/SlackChannelList.js +++ b/frontend/app/components/Client/Integrations/SlackChannelList/SlackChannelList.js @@ -1,48 +1,48 @@ import React from 'react'; import { NoContent } from 'UI'; import DocLink from 'Shared/DocLink/DocLink'; -import { observer } from 'mobx-react-lite' -import { useStore } from 'App/mstore' +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; function SlackChannelList(props) { - const { integrationsStore } = useStore(); - const list = integrationsStore.slack.list; - const edit = integrationsStore.slack.edit; + const { integrationsStore } = useStore(); + const { list } = integrationsStore.slack; + const { edit } = integrationsStore.slack; - const onEdit = (instance) => { - edit(instance.toData()); - props.onEdit(); - }; + const onEdit = (instance) => { + edit(instance.toData()); + props.onEdit(); + }; - return ( -
- -
- Integrate Slack with OpenReplay and share insights with the rest of the team, directly from the recording page. -
- -
- } - size="small" - show={list.length === 0} - > - {list.map((c) => ( -
onEdit(c)} - > -
-
{c.name}
-
{c.endpoint}
-
-
- ))} - -
- ); + return ( +
+ +
+ Integrate Slack with OpenReplay and share insights with the rest of the team, directly from the recording page. +
+ +
+ )} + size="small" + show={list.length === 0} + > + {list.map((c) => ( +
onEdit(c)} + > +
+
{c.name}
+
{c.endpoint}
+
+
+ ))} + +
+ ); } export default observer(SlackChannelList); diff --git a/frontend/app/components/Client/Integrations/SlackChannelList/index.js b/frontend/app/components/Client/Integrations/SlackChannelList/index.js index d9709c104..9056062a5 100644 --- a/frontend/app/components/Client/Integrations/SlackChannelList/index.js +++ b/frontend/app/components/Client/Integrations/SlackChannelList/index.js @@ -1 +1 @@ -export { default } from './SlackChannelList' \ No newline at end of file +export { default } from './SlackChannelList'; diff --git a/frontend/app/components/Client/Integrations/SlackForm.tsx b/frontend/app/components/Client/Integrations/SlackForm.tsx index 4c7e97209..8c01f16f0 100644 --- a/frontend/app/components/Client/Integrations/SlackForm.tsx +++ b/frontend/app/components/Client/Integrations/SlackForm.tsx @@ -1,48 +1,48 @@ import React, { useEffect } from 'react'; -import SlackChannelList from './SlackChannelList/SlackChannelList'; -import SlackAddForm from './SlackAddForm'; import { Icon } from 'UI'; import { Button } from 'antd'; -import { observer } from 'mobx-react-lite' -import { useStore } from 'App/mstore' +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; +import SlackAddForm from './SlackAddForm'; +import SlackChannelList from './SlackChannelList/SlackChannelList'; -const SlackForm = () => { - const { integrationsStore } = useStore(); - const init = integrationsStore.slack.init; - const fetchList = integrationsStore.slack.fetchIntegrations; - const [active, setActive] = React.useState(false); +function SlackForm() { + const { integrationsStore } = useStore(); + const { init } = integrationsStore.slack; + const fetchList = integrationsStore.slack.fetchIntegrations; + const [active, setActive] = React.useState(false); - const onEdit = () => { - setActive(true); - }; + const onEdit = () => { + setActive(true); + }; - const onNew = () => { - setActive(true); - init({}); - } + const onNew = () => { + setActive(true); + init({}); + }; - useEffect(() => { - void fetchList(); - }, []); + useEffect(() => { + void fetchList(); + }, []); - return ( -
- {active && ( -
- setActive(false)} /> -
- )} -
-
-

Slack

-
- -
+ return ( +
+ {active && ( +
+ setActive(false)} />
- ); -}; + )} +
+
+

Slack

+
+ +
+
+ ); +} SlackForm.displayName = 'SlackForm'; -export default observer(SlackForm); \ No newline at end of file +export default observer(SlackForm); diff --git a/frontend/app/components/Client/Integrations/Teams/TeamsAddForm.tsx b/frontend/app/components/Client/Integrations/Teams/TeamsAddForm.tsx index 9341b08ef..9e8e27d3f 100644 --- a/frontend/app/components/Client/Integrations/Teams/TeamsAddForm.tsx +++ b/frontend/app/components/Client/Integrations/Teams/TeamsAddForm.tsx @@ -2,8 +2,10 @@ import { observer } from 'mobx-react-lite'; import React from 'react'; import { useStore } from 'App/mstore'; -import { confirm, Form, Input, Message } from 'UI'; -import { Button } from 'antd' +import { + confirm, Form, Input, Message, +} from 'UI'; +import { Button } from 'antd'; interface Props { onClose: () => void; @@ -11,18 +13,16 @@ interface Props { function TeamsAddForm({ onClose }: Props) { const { integrationsStore } = useStore(); - const instance = integrationsStore.msteams.instance; + const { instance } = integrationsStore.msteams; const saving = integrationsStore.msteams.loading; - const errors = integrationsStore.msteams.errors; - const edit = integrationsStore.msteams.edit; + const { errors } = integrationsStore.msteams; + const { edit } = integrationsStore.msteams; const onSave = integrationsStore.msteams.saveIntegration; - const init = integrationsStore.msteams.init; + const { init } = integrationsStore.msteams; const onRemove = integrationsStore.msteams.removeInt; - const update = integrationsStore.msteams.update; + const { update } = integrationsStore.msteams; - React.useEffect(() => { - return () => init({}); - }, []); + React.useEffect(() => () => init({}), []); const save = () => { if (instance?.exists()) { @@ -41,7 +41,7 @@ function TeamsAddForm({ onClose }: Props) { await confirm({ header: 'Confirm', confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this channel?` + confirmation: 'Are you sure you want to permanently delete this channel?', }) ) { void onRemove(id).then(onClose); @@ -49,8 +49,8 @@ function TeamsAddForm({ onClose }: Props) { }; const write = ({ - target: { name, value } - }: { + target: { name, value }, + }: { target: { name: string; value: string }; }) => edit({ [name]: value }); @@ -89,14 +89,14 @@ function TeamsAddForm({ onClose }: Props) { {instance?.exists() ? 'Update' : 'Add'} - +
diff --git a/frontend/app/components/Client/Integrations/Teams/TeamsChannelList.tsx b/frontend/app/components/Client/Integrations/Teams/TeamsChannelList.tsx index 131a404c8..a2d7f8c11 100644 --- a/frontend/app/components/Client/Integrations/Teams/TeamsChannelList.tsx +++ b/frontend/app/components/Client/Integrations/Teams/TeamsChannelList.tsx @@ -8,8 +8,8 @@ import DocLink from 'Shared/DocLink/DocLink'; function TeamsChannelList(props: { onEdit: () => void }) { const { integrationsStore } = useStore(); - const list = integrationsStore.msteams.list; - const edit = integrationsStore.msteams.edit; + const { list } = integrationsStore.msteams; + const { edit } = integrationsStore.msteams; const onEdit = (instance: Record) => { edit(instance); @@ -19,7 +19,7 @@ function TeamsChannelList(props: { onEdit: () => void }) { return (
Integrate MS Teams with OpenReplay and share insights with the @@ -31,7 +31,7 @@ function TeamsChannelList(props: { onEdit: () => void }) { url="https://docs.openreplay.com/integrations/msteams" />
- } + )} size="small" show={list.length === 0} > diff --git a/frontend/app/components/Client/Integrations/Teams/index.tsx b/frontend/app/components/Client/Integrations/Teams/index.tsx index 21ffec387..417e6944a 100644 --- a/frontend/app/components/Client/Integrations/Teams/index.tsx +++ b/frontend/app/components/Client/Integrations/Teams/index.tsx @@ -2,47 +2,47 @@ import React, { useEffect } from 'react'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { Icon } from 'UI'; -import { Button } from 'antd' +import { Button } from 'antd'; import TeamsChannelList from './TeamsChannelList'; import TeamsAddForm from './TeamsAddForm'; -const MSTeams = () => { - const { integrationsStore } = useStore(); - const fetchList = integrationsStore.msteams.fetchIntegrations; - const init = integrationsStore.msteams.init; - const [active, setActive] = React.useState(false); +function MSTeams() { + const { integrationsStore } = useStore(); + const fetchList = integrationsStore.msteams.fetchIntegrations; + const { init } = integrationsStore.msteams; + const [active, setActive] = React.useState(false); - const onEdit = () => { - setActive(true); - }; + const onEdit = () => { + setActive(true); + }; - const onNew = () => { - setActive(true); - init({}); - } + const onNew = () => { + setActive(true); + init({}); + }; - useEffect(() => { - void fetchList(); - }, []); + useEffect(() => { + void fetchList(); + }, []); - return ( -
- {active && ( -
- setActive(false)} /> -
- )} -
-
-

Microsoft Teams

-
- -
+ return ( +
+ {active && ( +
+ setActive(false)} />
- ); -}; + )} +
+
+

Microsoft Teams

+
+ +
+
+ ); +} MSTeams.displayName = 'MSTeams'; diff --git a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistDoc.js b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistDoc.js index 1165af6ec..b08e9bb29 100644 --- a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistDoc.js @@ -1,59 +1,58 @@ -import { useStore } from "App/mstore"; -import React from 'react'; +import { useStore } from 'App/mstore'; +import React, { useState } from 'react'; import DocLink from 'Shared/DocLink/DocLink'; +import { Tabs, CodeBlock } from 'UI'; +import { observer } from 'mobx-react-lite'; import AssistScript from './AssistScript'; import AssistNpm from './AssistNpm'; -import { Tabs, CodeBlock } from 'UI'; -import { useState } from 'react'; -import { observer } from 'mobx-react-lite' const NPM = 'NPM'; const SCRIPT = 'SCRIPT'; const TABS = [ - { key: SCRIPT, text: SCRIPT }, - { key: NPM, text: NPM }, + { key: SCRIPT, text: SCRIPT }, + { key: NPM, text: NPM }, ]; -const AssistDoc = () => { - const { integrationsStore, projectsStore } = useStore(); - const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey - const [activeTab, setActiveTab] = useState(SCRIPT); +function AssistDoc() { + const { integrationsStore, projectsStore } = useStore(); + const sites = projectsStore.list; + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; + const [activeTab, setActiveTab] = useState(SCRIPT); - const renderActiveTab = () => { - switch (activeTab) { - case SCRIPT: - return ; - case NPM: - return ; - } - return null; - }; + const renderActiveTab = () => { + switch (activeTab) { + case SCRIPT: + return ; + case NPM: + return ; + } + return null; + }; - return ( -
-

Assist

-
-
- OpenReplay Assist allows you to support your users by seeing their live screen and instantly hopping on call (WebRTC) with them - without requiring any 3rd-party screen sharing software. -
- -
Installation
- -
- -
Usage
- setActiveTab(tab)} /> - -
{renderActiveTab()}
- - -
+ return ( +
+

Assist

+
+
+ OpenReplay Assist allows you to support your users by seeing their live screen and instantly hopping on call (WebRTC) with them + without requiring any 3rd-party screen sharing software.
- ); -}; + +
Installation
+ +
+ +
Usage
+ setActiveTab(tab)} /> + +
{renderActiveTab()}
+ + +
+
+ ); +} AssistDoc.displayName = 'AssistDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistNpm.tsx b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistNpm.tsx index 00fe1cb26..3c769359e 100644 --- a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistNpm.tsx +++ b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistNpm.tsx @@ -56,7 +56,7 @@ type ButtonOptions = HTMLButtonElement | string | { innerHTML?: string, // to pass an svg string or text style?: StyleObject, // style object (i.e {color: 'red', borderRadius: '10px'}) } -` +`; return (

diff --git a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistScript.tsx b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistScript.tsx index 23ce8ff02..e53e4d6de 100644 --- a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistScript.tsx +++ b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/AssistScript.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { CodeBlock } from "UI"; +import { CodeBlock } from 'UI'; function AssistScript(props) { const scriptCode = ` @@ -18,15 +18,15 @@ function AssistScript(props) { r.isActive=function(){return false}; r.getSessionToken=function(){}; })(0, "${props.projectKey}", "${window.env.TRACKER_HOST || '//static.openreplay.com'}/${window.env.TRACKER_VERSION}/openreplay-assist.js", 1, 28); -` +`; return (

If your OpenReplay tracker is set up using the JS snippet, then simply replace the .../openreplay.js occurrence with .../openreplay-assist.js. Below is an example of how the script should like after the change:

- +
); } -export default AssistScript; \ No newline at end of file +export default AssistScript; diff --git a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/index.js index 6086d5389..8d1c447e9 100644 --- a/frontend/app/components/Client/Integrations/Tracker/AssistDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/AssistDoc/index.js @@ -1 +1 @@ -export { default } from './AssistDoc' \ No newline at end of file +export { default } from './AssistDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/GraphQLDoc.js b/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/GraphQLDoc.js index 889ecfd1f..d00208b28 100644 --- a/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/GraphQLDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/GraphQLDoc.js @@ -1,16 +1,16 @@ -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import React from 'react'; -import { CodeBlock } from "UI"; +import { CodeBlock } from 'UI'; import DocLink from 'Shared/DocLink/DocLink'; import ToggleContent from 'Shared/ToggleContent'; -import { observer } from 'mobx-react-lite' +import { observer } from 'mobx-react-lite'; -const GraphQLDoc = () => { - const { integrationsStore, projectsStore } = useStore(); - const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey - const usage = `import OpenReplay from '@openreplay/tracker'; +function GraphQLDoc() { + const { integrationsStore, projectsStore } = useStore(); + const sites = projectsStore.list; + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; + const usage = `import OpenReplay from '@openreplay/tracker'; import trackerGraphQL from '@openreplay/tracker-graphql'; //... const tracker = new OpenReplay({ @@ -18,8 +18,8 @@ const tracker = new OpenReplay({ }); tracker.start() //... -export const recordGraphQL = tracker.use(trackerGraphQL());` - const usageCjs = `import OpenReplay from '@openreplay/tracker/cjs'; +export const recordGraphQL = tracker.use(trackerGraphQL());`; + const usageCjs = `import OpenReplay from '@openreplay/tracker/cjs'; import trackerGraphQL from '@openreplay/tracker-graphql/cjs'; //... const tracker = new OpenReplay({ @@ -32,43 +32,43 @@ function SomeFunctionalComponent() { }, []) } //... -export const recordGraphQL = tracker.use(trackerGraphQL());` - return ( -
-

GraphQL

-
-

- This plugin allows you to capture GraphQL requests and inspect them later on while replaying session recordings. This is very - useful for understanding and fixing issues. -

-

GraphQL plugin is compatible with Apollo and Relay implementations.

+export const recordGraphQL = tracker.use(trackerGraphQL());`; + return ( +
+

GraphQL

+
+

+ This plugin allows you to capture GraphQL requests and inspect them later on while replaying session recordings. This is very + useful for understanding and fixing issues. +

+

GraphQL plugin is compatible with Apollo and Relay implementations.

-
Installation
- +
Installation
+ -
Usage
-

- The plugin call will return the function, which receives four variables operationKind, operationName, variables and result. It - returns result without changes. -

+
Usage
+

+ The plugin call will return the function, which receives four variables operationKind, operationName, variables and result. It + returns result without changes. +

-
+
- + } - second={ - + second={ + } - /> + /> - -
-
- ); -}; + +
+
+ ); +} GraphQLDoc.displayName = 'GraphQLDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/index.js index 6fe38bba7..f7317d7d4 100644 --- a/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/GraphQLDoc/index.js @@ -1 +1 @@ -export { default } from './GraphQLDoc' \ No newline at end of file +export { default } from './GraphQLDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/MobxDoc/MobxDoc.js b/frontend/app/components/Client/Integrations/Tracker/MobxDoc/MobxDoc.js index 2541aae2b..159d4665b 100644 --- a/frontend/app/components/Client/Integrations/Tracker/MobxDoc/MobxDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/MobxDoc/MobxDoc.js @@ -1,17 +1,17 @@ import React from 'react'; import ToggleContent from 'Shared/ToggleContent'; import DocLink from 'Shared/DocLink/DocLink'; -import { CodeBlock } from "UI"; +import { CodeBlock } from 'UI'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; -const MobxDoc = () => { - const { integrationsStore, projectsStore } = useStore(); - const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey +function MobxDoc() { + const { integrationsStore, projectsStore } = useStore(); + const sites = projectsStore.list; + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; - const mobxUsage = `import OpenReplay from '@openreplay/tracker'; + const mobxUsage = `import OpenReplay from '@openreplay/tracker'; import trackerMobX from '@openreplay/tracker-mobx'; //... const tracker = new OpenReplay({ @@ -19,9 +19,9 @@ const tracker = new OpenReplay({ }); tracker.use(trackerMobX()); // check list of available options below tracker.start(); -` +`; - const mobxUsageCjs = `import OpenReplay from '@openreplay/tracker/cjs'; + const mobxUsageCjs = `import OpenReplay from '@openreplay/tracker/cjs'; import trackerMobX from '@openreplay/tracker-mobx/cjs'; //... const tracker = new OpenReplay({ @@ -33,40 +33,40 @@ function SomeFunctionalComponent() { useEffect(() => { // or componentDidMount in case of Class approach tracker.start() }, []) -}` +}`; - return ( -
-

MobX

-
-
- This plugin allows you to capture MobX events and inspect them later on while replaying session recordings. This is very useful - for understanding and fixing issues. -
- -
Installation
- - -
Usage
-

- Initialize the @openreplay/tracker package as usual and load the plugin into it. Then put the generated middleware into your Redux - chain. -

-
- -
Usage
- } - second={} - /> - - -
+ return ( +
+

MobX

+
+
+ This plugin allows you to capture MobX events and inspect them later on while replaying session recordings. This is very useful + for understanding and fixing issues.
- ); -}; + +
Installation
+ + +
Usage
+

+ Initialize the @openreplay/tracker package as usual and load the plugin into it. Then put the generated middleware into your Redux + chain. +

+
+ +
Usage
+ } + second={} + /> + + +
+
+ ); +} MobxDoc.displayName = 'MobxDoc'; -export default observer(MobxDoc) +export default observer(MobxDoc); diff --git a/frontend/app/components/Client/Integrations/Tracker/MobxDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/MobxDoc/index.js index 51b6dedae..ed631b7b7 100644 --- a/frontend/app/components/Client/Integrations/Tracker/MobxDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/MobxDoc/index.js @@ -1 +1 @@ -export { default } from './MobxDoc' \ No newline at end of file +export { default } from './MobxDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/NgRxDoc.js b/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/NgRxDoc.js index f960918b6..44b9b7d21 100644 --- a/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/NgRxDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/NgRxDoc.js @@ -1,16 +1,16 @@ -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import React from 'react'; -import { CodeBlock } from "UI"; +import { CodeBlock } from 'UI'; import ToggleContent from 'Shared/ToggleContent'; import DocLink from 'Shared/DocLink/DocLink'; -import { observer } from 'mobx-react-lite' +import { observer } from 'mobx-react-lite'; -const NgRxDoc = () => { +function NgRxDoc() { const { integrationsStore, projectsStore } = useStore(); const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey - const usage = `import { StoreModule } from '@ngrx/store'; + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; + const usage = `import { StoreModule } from '@ngrx/store'; import { reducers } from './reducers'; import OpenReplay from '@openreplay/tracker'; import trackerNgRx from '@openreplay/tracker-ngrx'; @@ -25,7 +25,7 @@ const metaReducers = [tracker.use(trackerNgRx())]; // check list of ava @NgModule({ imports: [StoreModule.forRoot(reducers, { metaReducers })] }) -export class AppModule {}` +export class AppModule {}`; const usageCjs = `import { StoreModule } from '@ngrx/store'; import { reducers } from './reducers'; import OpenReplay from '@openreplay/tracker/cjs'; @@ -46,39 +46,39 @@ const metaReducers = [tracker.use(trackerNgRx())]; // check list of ava imports: [StoreModule.forRoot(reducers, { metaReducers })] }) export class AppModule {} -}` - return ( -
-

NgRx

-
-
- This plugin allows you to capture NgRx actions/state and inspect them later on while replaying session recordings. This is very - useful for understanding and fixing issues. -
- -
Installation
- - -
Usage
-

Add the generated meta-reducer into your imports. See NgRx documentation for more details.

-
- -
Usage
- - } - second={ - - } - /> - - -
+}`; + return ( +
+

NgRx

+
+
+ This plugin allows you to capture NgRx actions/state and inspect them later on while replaying session recordings. This is very + useful for understanding and fixing issues.
- ); -}; + +
Installation
+ + +
Usage
+

Add the generated meta-reducer into your imports. See NgRx documentation for more details.

+
+ +
Usage
+ + } + second={ + + } + /> + + +
+
+ ); +} NgRxDoc.displayName = 'NgRxDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/index.js index 65f97eed5..12044446b 100644 --- a/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/NgRxDoc/index.js @@ -1 +1 @@ -export { default } from './NgRxDoc' \ No newline at end of file +export { default } from './NgRxDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/PiniaDoc.tsx b/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/PiniaDoc.tsx index b63b50fba..539645942 100644 --- a/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/PiniaDoc.tsx +++ b/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/PiniaDoc.tsx @@ -7,10 +7,10 @@ import { CodeBlock } from 'UI'; import DocLink from 'Shared/DocLink/DocLink'; -const PiniaDoc = () => { +function PiniaDoc() { const { integrationsStore, projectsStore } = useStore(); const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId; + const { siteId } = integrationsStore.integrations; const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; @@ -77,7 +77,7 @@ piniaStorePlugin(examplePiniaStore)
Installation
@@ -103,7 +103,7 @@ piniaStorePlugin(examplePiniaStore)
); -}; +} PiniaDoc.displayName = 'PiniaDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/index.js index 730c76beb..95010dbc2 100644 --- a/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/PiniaDoc/index.js @@ -1 +1 @@ -export { default } from './PiniaDoc' +export { default } from './PiniaDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/ReduxDoc.js b/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/ReduxDoc.js index 5c69bec47..8d356059c 100644 --- a/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/ReduxDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/ReduxDoc.js @@ -1,17 +1,17 @@ -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import React from 'react'; -import { CodeBlock } from 'UI' +import { CodeBlock } from 'UI'; import ToggleContent from 'Components/shared/ToggleContent'; import DocLink from 'Shared/DocLink/DocLink'; -import { observer } from 'mobx-react-lite' +import { observer } from 'mobx-react-lite'; -const ReduxDoc = () => { +function ReduxDoc() { const { integrationsStore, projectsStore } = useStore(); const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; - const usage = `import { applyMiddleware, createStore } from 'redux'; + const usage = `import { applyMiddleware, createStore } from 'redux'; import OpenReplay from '@openreplay/tracker'; import trackerRedux from '@openreplay/tracker-redux'; //... @@ -23,7 +23,7 @@ tracker.start() const store = createStore( reducer, applyMiddleware(tracker.use(trackerRedux())) // check list of available options below -);` +);`; const usageCjs = `import { applyMiddleware, createStore } from 'redux'; import OpenReplay from '@openreplay/tracker/cjs'; import trackerRedux from '@openreplay/tracker-redux/cjs'; @@ -41,38 +41,38 @@ const store = createStore( reducer, applyMiddleware(tracker.use(trackerRedux())) // check list of available options below ); -}` - return ( -
-

Redux

+}`; + return ( +
+

Redux

-
-
- This plugin allows you to capture Redux actions/state and inspect them later on while replaying session recordings. This is very - useful for understanding and fixing issues. -
- -
Installation
- - -
Usage
-

Initialize the tracker then put the generated middleware into your Redux chain.

-
- - } - second={ - - } - /> - - -
+
+
+ This plugin allows you to capture Redux actions/state and inspect them later on while replaying session recordings. This is very + useful for understanding and fixing issues.
- ); -}; + +
Installation
+ + +
Usage
+

Initialize the tracker then put the generated middleware into your Redux chain.

+
+ + } + second={ + + } + /> + + +
+
+ ); +} ReduxDoc.displayName = 'ReduxDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/index.js index 3c6245bd8..248102d25 100644 --- a/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/ReduxDoc/index.js @@ -1 +1 @@ -export { default } from './ReduxDoc' \ No newline at end of file +export { default } from './ReduxDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/VueDoc/VueDoc.js b/frontend/app/components/Client/Integrations/Tracker/VueDoc/VueDoc.js index f9e23c67a..2576d1349 100644 --- a/frontend/app/components/Client/Integrations/Tracker/VueDoc/VueDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/VueDoc/VueDoc.js @@ -1,15 +1,15 @@ -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import React from 'react'; -import { CodeBlock } from "UI"; +import { CodeBlock } from 'UI'; import ToggleContent from 'Components/shared/ToggleContent'; import DocLink from 'Shared/DocLink/DocLink'; import { observer } from 'mobx-react-lite'; -const VueDoc = () => { +function VueDoc() { const { integrationsStore, projectsStore } = useStore(); const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; const usage = `import Vuex from 'vuex' import OpenReplay from '@openreplay/tracker'; @@ -23,7 +23,7 @@ tracker.start() const store = new Vuex.Store({ //... plugins: [tracker.use(trackerVuex())] // check list of available options below -});` +});`; const usageCjs = `import Vuex from 'vuex' import OpenReplay from '@openreplay/tracker/cjs'; import trackerVuex from '@openreplay/tracker-vuex/cjs'; @@ -41,7 +41,7 @@ const store = new Vuex.Store({ //... plugins: [tracker.use(trackerVuex())] // check list of available options below }); -}` +}`; return (

VueX

@@ -52,7 +52,7 @@ const store = new Vuex.Store({
Installation
- +
Usage

@@ -64,10 +64,10 @@ const store = new Vuex.Store({ + } second={ - + } /> @@ -79,7 +79,7 @@ const store = new Vuex.Store({

); -}; +} VueDoc.displayName = 'VueDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/VueDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/VueDoc/index.js index 555e8acfb..b50d6d1dd 100644 --- a/frontend/app/components/Client/Integrations/Tracker/VueDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/VueDoc/index.js @@ -1 +1 @@ -export { default } from './VueDoc' \ No newline at end of file +export { default } from './VueDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/ZustandDoc.js b/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/ZustandDoc.js index eb7dcd091..170c0effb 100644 --- a/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/ZustandDoc.js +++ b/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/ZustandDoc.js @@ -1,17 +1,17 @@ -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import React from 'react'; -import { CodeBlock } from "UI"; +import { CodeBlock } from 'UI'; import ToggleContent from 'Components//shared/ToggleContent'; import DocLink from 'Shared/DocLink/DocLink'; -import { observer } from 'mobx-react-lite' +import { observer } from 'mobx-react-lite'; -const ZustandDoc = (props) => { +function ZustandDoc(props) { const { integrationsStore, projectsStore } = useStore(); const sites = projectsStore.list; - const siteId = integrationsStore.integrations.siteId - const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey + const { siteId } = integrationsStore.integrations; + const projectKey = siteId ? sites.find((site) => site.id === siteId)?.projectKey : sites[0]?.projectKey; - const usage = `import create from "zustand"; + const usage = `import create from "zustand"; import Tracker from '@openreplay/tracker'; import trackerZustand, { StateLogger } from '@openreplay/tracker-zustand'; @@ -37,8 +37,8 @@ const useBearStore = create( 'bear_store' ) ) -` - const usageCjs =`import create from "zustand"; +`; + const usageCjs = `import create from "zustand"; import Tracker from '@openreplay/tracker/cjs'; import trackerZustand, { StateLogger } from '@openreplay/tracker-zustand/cjs'; @@ -63,41 +63,41 @@ const useBearStore = create( // and is randomly generated if undefined 'bear_store' ) -)` - return ( -
-

Zustand

-
-
- This plugin allows you to capture Zustand mutations/state and inspect them later on while replaying session recordings. This is very - useful for understanding and fixing issues. -
- -
Installation
- - -
Usage
-

- Initialize the @openreplay/tracker package as usual and load the plugin into it. Then put the generated plugin into your plugins - field of your store. -

-
- - - } - second={ - - } - /> - - -
+)`; + return ( +
+

Zustand

+
+
+ This plugin allows you to capture Zustand mutations/state and inspect them later on while replaying session recordings. This is very + useful for understanding and fixing issues.
- ); -}; + +
Installation
+ + +
Usage
+

+ Initialize the @openreplay/tracker package as usual and load the plugin into it. Then put the generated plugin into your plugins + field of your store. +

+
+ + + } + second={ + + } + /> + + +
+
+ ); +} ZustandDoc.displayName = 'ZustandDoc'; diff --git a/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/index.js b/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/index.js index f7061eb7a..d0e1674b3 100644 --- a/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/index.js +++ b/frontend/app/components/Client/Integrations/Tracker/ZustandDoc/index.js @@ -1 +1 @@ -export { default } from './ZustandDoc' +export { default } from './ZustandDoc'; diff --git a/frontend/app/components/Client/Integrations/apiMethods.ts b/frontend/app/components/Client/Integrations/apiMethods.ts index 3924a068b..c870ccdee 100644 --- a/frontend/app/components/Client/Integrations/apiMethods.ts +++ b/frontend/app/components/Client/Integrations/apiMethods.ts @@ -12,10 +12,10 @@ export const serviceNames: Record = { export async function getIntegrationData( name: ServiceName, - projectId: string + projectId: string, ): Promise { const r = await client.get( - `/integrations/v1/integrations/${name}/${projectId}` + `/integrations/v1/integrations/${name}/${projectId}`, ); return r.json(); } @@ -23,7 +23,7 @@ export async function getIntegrationData( export function useIntegration( name: ServiceName, projectId: string, - initialValues: T + initialValues: T, ) { const { data, isPending } = useQuery({ queryKey: ['integrationData', name], @@ -36,12 +36,12 @@ export function useIntegration( }, initialData: initialValues, retry: (failureCount, error) => { - const status = error.status || error.response.status + const status = error.status || error.response.status; if (status === 404) { return false; } return failureCount < 4; - } + }, }); const saveMutation = useMutation({ @@ -56,8 +56,7 @@ export function useIntegration( }) => saveIntegration(name, values, siteId, exists), }); const removeMutation = useMutation({ - mutationFn: ({ siteId }: { siteId: string }) => - removeIntegration(name, siteId), + mutationFn: ({ siteId }: { siteId: string }) => removeIntegration(name, siteId), }); return { @@ -72,13 +71,13 @@ export async function saveIntegration( name: string, data: T, projectId: string, - exists?: boolean + exists?: boolean, ) { const method = exists ? 'patch' : 'post'; try { const r = await client[method]( `/integrations/v1/integrations/${name}/${projectId}`, - { data } + { data }, ); if (r.ok) { toast.success(`${name} integration saved`); @@ -99,7 +98,7 @@ export async function saveIntegration( export async function removeIntegration(name: string, projectId: string) { try { const r = await client.delete( - `/integrations/v1/integrations/${name}/${projectId}` + `/integrations/v1/integrations/${name}/${projectId}`, ); if (r.ok) { toast.success(`${name} integration removed`); diff --git a/frontend/app/components/Client/Integrations/index.js b/frontend/app/components/Client/Integrations/index.js index 1a6b7f6cb..033519dfa 100644 --- a/frontend/app/components/Client/Integrations/index.js +++ b/frontend/app/components/Client/Integrations/index.js @@ -1 +1 @@ -export { default } from './Integrations'; \ No newline at end of file +export { default } from './Integrations'; diff --git a/frontend/app/components/Client/Modules/ModuleCard.tsx b/frontend/app/components/Client/Modules/ModuleCard.tsx index f6d6cadc6..72437062a 100644 --- a/frontend/app/components/Client/Modules/ModuleCard.tsx +++ b/frontend/app/components/Client/Modules/ModuleCard.tsx @@ -3,7 +3,6 @@ import { Icon } from 'UI'; import { Switch } from 'antd'; import { Module } from 'Components/Client/Modules/index'; - interface Props { module: Module; onToggle: (module: Module) => void; @@ -12,22 +11,26 @@ interface Props { function ModuleCard(props: Props) { const { module } = props; return ( -
-
- +
+
+
-
-
-

{module.label}

-

{module.description}

+
+
+

{module.label}

+

{module.description}

-
- props.onToggle(module)} /> +
+ props.onToggle(module)} + />
); } -export default ModuleCard; \ No newline at end of file +export default ModuleCard; diff --git a/frontend/app/components/Client/Modules/Modules.tsx b/frontend/app/components/Client/Modules/Modules.tsx index 2767ff76f..bd801d3aa 100644 --- a/frontend/app/components/Client/Modules/Modules.tsx +++ b/frontend/app/components/Client/Modules/Modules.tsx @@ -1,15 +1,15 @@ import React, { useEffect } from 'react'; import ModuleCard from 'Components/Client/Modules/ModuleCard'; -import { modules as list } from './'; import withPageTitle from 'HOCs/withPageTitle'; import { userService } from 'App/services'; import { toast } from 'react-toastify'; -import { useStore } from "App/mstore"; +import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; +import { modules as list } from '.'; function Modules() { const { userStore } = useStore(); - const updateModule = userStore.updateModule; + const { updateModule } = userStore; const modules = userStore.account.settings?.modules ?? []; const isEnterprise = userStore.account.edition === 'ee'; const [modulesState, setModulesState] = React.useState([]); @@ -40,20 +40,19 @@ function Modules() { setModulesState(list.filter((module) => !module.hidden && (!module.enterprise || isEnterprise))); }, [modules]); - return (
-
-

Modules

-