diff --git a/frontend/src/lib/components/Support/supportLogic.ts b/frontend/src/lib/components/Support/supportLogic.ts index 2546a7d3f4413..3e0f670074598 100644 --- a/frontend/src/lib/components/Support/supportLogic.ts +++ b/frontend/src/lib/components/Support/supportLogic.ts @@ -46,6 +46,29 @@ function getSessionReplayLink(): string { return `\nSession: ${replayUrl}` } +function getErrorTrackingLink(): string { + const filterGroup = encodeURIComponent( + JSON.stringify({ + type: 'AND', + values: [ + { + type: 'AND', + values: [ + { + key: '$session_id', + value: [posthog.get_session_id()], + operator: 'exact', + type: 'event', + }, + ], + }, + ], + }) + ) + + return `\nExceptions: https://us.posthog.com/project/2/error_tracking?filterGroup=${filterGroup}` +} + function getDjangoAdminLink( user: UserType | null, cloudRegion: Region | null | undefined, @@ -452,6 +475,7 @@ export const supportLogic = kea([ `\nTarget area: ${target_area}` + `\nReport event: http://go/ticketByUUID/${zendesk_ticket_uuid}` + getSessionReplayLink() + + getErrorTrackingLink() + getCurrentLocationLink() + getDjangoAdminLink( userLogic.values.user, diff --git a/frontend/src/scenes/error-tracking/errorTrackingLogic.ts b/frontend/src/scenes/error-tracking/errorTrackingLogic.ts index c1a847a8ab647..260e4e4d08ccb 100644 --- a/frontend/src/scenes/error-tracking/errorTrackingLogic.ts +++ b/frontend/src/scenes/error-tracking/errorTrackingLogic.ts @@ -27,7 +27,9 @@ const customOptions: Record = { all: [lastYear, lastMonth, lastDay], } -const DEFAULT_FILTER_GROUP = { +export const DEFAULT_ERROR_TRACKING_DATE_RANGE = { date_from: '-7d', date_to: null } + +export const DEFAULT_ERROR_TRACKING_FILTER_GROUP = { type: FilterLogicalOperator.And, values: [{ type: FilterLogicalOperator.And, values: [] }], } @@ -42,15 +44,15 @@ export const errorTrackingLogic = kea([ actions({ setDateRange: (dateRange: DateRange) => ({ dateRange }), setAssignee: (assignee: number | null) => ({ assignee }), + setSearchQuery: (searchQuery: string) => ({ searchQuery }), setFilterGroup: (filterGroup: UniversalFiltersGroup) => ({ filterGroup }), setFilterTestAccounts: (filterTestAccounts: boolean) => ({ filterTestAccounts }), - setSearchQuery: (searchQuery: string) => ({ searchQuery }), setSparklineSelectedPeriod: (period: string | null) => ({ period }), _setSparklineOptions: (options: SparklineOption[]) => ({ options }), }), reducers({ dateRange: [ - { date_from: '-7d', date_to: null } as DateRange, + DEFAULT_ERROR_TRACKING_DATE_RANGE as DateRange, { persist: true }, { setDateRange: (_, { dateRange }) => dateRange, @@ -64,7 +66,7 @@ export const errorTrackingLogic = kea([ }, ], filterGroup: [ - DEFAULT_FILTER_GROUP as UniversalFiltersGroup, + DEFAULT_ERROR_TRACKING_FILTER_GROUP as UniversalFiltersGroup, { persist: true }, { setFilterGroup: (_, { filterGroup }) => filterGroup, diff --git a/frontend/src/scenes/error-tracking/errorTrackingSceneLogic.ts b/frontend/src/scenes/error-tracking/errorTrackingSceneLogic.ts index bd36ead868256..92dbd6d61dcac 100644 --- a/frontend/src/scenes/error-tracking/errorTrackingSceneLogic.ts +++ b/frontend/src/scenes/error-tracking/errorTrackingSceneLogic.ts @@ -1,9 +1,17 @@ +import equal from 'fast-deep-equal' import { actions, connect, kea, path, reducers, selectors } from 'kea' +import { actionToUrl, router, urlToAction } from 'kea-router' import { subscriptions } from 'kea-subscriptions' +import { objectsEqual } from 'lib/utils' +import { Params } from 'scenes/sceneTypes' import { DataTableNode, ErrorTrackingQuery } from '~/queries/schema' -import { errorTrackingLogic } from './errorTrackingLogic' +import { + DEFAULT_ERROR_TRACKING_DATE_RANGE, + DEFAULT_ERROR_TRACKING_FILTER_GROUP, + errorTrackingLogic, +} from './errorTrackingLogic' import type { errorTrackingSceneLogicType } from './errorTrackingSceneLogicType' import { errorTrackingQuery } from './queries' @@ -23,6 +31,10 @@ export const errorTrackingSceneLogic = kea([ 'hasGroupActions', ], ], + actions: [ + errorTrackingLogic, + ['setAssignee', 'setDateRange', 'setFilterGroup', 'setSearchQuery', 'setFilterTestAccounts'], + ], }), actions({ @@ -86,4 +98,79 @@ export const errorTrackingSceneLogic = kea([ subscriptions(({ actions }) => ({ query: () => actions.setSelectedIssueIds([]), })), + + actionToUrl(({ values }) => { + const buildURL = (): [ + string, + Params, + Record, + { + replace: boolean + } + ] => { + const searchParams: Params = { + orderBy: values.orderBy, + filterTestAccounts: values.filterTestAccounts, + } + + if (values.assignee) { + searchParams.assignee = values.assignee + } + if (values.searchQuery) { + searchParams.searchQuery = values.searchQuery + } + if (!objectsEqual(values.filterGroup, DEFAULT_ERROR_TRACKING_FILTER_GROUP)) { + searchParams.filterGroup = values.filterGroup + } + if (!objectsEqual(values.dateRange, DEFAULT_ERROR_TRACKING_DATE_RANGE)) { + searchParams.dateRange = values.dateRange + } + + if (!objectsEqual(searchParams, router.values.searchParams)) { + return [router.values.location.pathname, searchParams, router.values.hashParams, { replace: true }] + } + + return [ + router.values.location.pathname, + router.values.searchParams, + router.values.hashParams, + { replace: false }, + ] + } + + return { + setOrderBy: () => buildURL(), + setAssignee: () => buildURL(), + setDateRange: () => buildURL(), + setFilterGroup: () => buildURL(), + setSearchQuery: () => buildURL(), + setFilterTestAccounts: () => buildURL(), + } + }), + + urlToAction(({ actions, values }) => { + const urlToAction = (_: any, params: Params): void => { + if (params.orderBy && !equal(params.orderBy, values.orderBy)) { + actions.setOrderBy(params.orderBy) + } + if (params.dateRange && !equal(params.dateRange, values.dateRange)) { + actions.setDateRange(params.dateRange) + } + if (params.filterGroup && !equal(params.filterGroup, values.filterGroup)) { + actions.setFilterGroup(params.filterGroup) + } + if (params.filterTestAccounts && !equal(params.filterTestAccounts, values.filterTestAccounts)) { + actions.setFilterTestAccounts(params.filterTestAccounts) + } + if (params.assignee && !equal(params.assignee, values.assignee)) { + actions.setAssignee(params.assignee) + } + if (params.searchQuery && !equal(params.searchQuery, values.searchQuery)) { + actions.setSearchQuery(params.searchQuery) + } + } + return { + '*': urlToAction, + } + }), ])