0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-21 13:39:22 +01:00

fix linting & add comment

This commit is contained in:
David Newell 2024-11-18 18:38:20 +00:00
parent 3972d067fb
commit 98a4722be3
10 changed files with 157 additions and 141 deletions

View File

@ -1,5 +1,5 @@
import { IconX } from '@posthog/icons'
import { LemonButton, Tooltip } from '@posthog/lemon-ui'
import { LemonButton } from '@posthog/lemon-ui'
import clsx from 'clsx'
import { useActions, useValues } from 'kea'
@ -31,9 +31,13 @@ export function SidePanelPaneHeader({ children, title }: SidePanelPaneHeaderProp
</h3>
) : null}
{children}
<Tooltip placement={modalMode ? 'top' : 'bottom-end'} title={modalMode ? 'Close' : 'Close this side panel'}>
<LemonButton size="small" sideIcon={<IconX />} onClick={() => closeSidePanel()} />
</Tooltip>
<LemonButton
size="small"
sideIcon={<IconX />}
onClick={() => closeSidePanel()}
tooltip={modalMode ? 'Close' : 'Close this side panel'}
tooltipPlacement={modalMode ? 'top' : 'bottom-end'}
/>
</header>
)
}

View File

@ -17,7 +17,6 @@ import clsx from 'clsx'
import { useActions, useValues } from 'kea'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { ProfilePicture } from 'lib/lemon-ui/ProfilePicture'
import { Tooltip } from 'lib/lemon-ui/Tooltip'
import { UploadedLogo } from 'lib/lemon-ui/UploadedLogo'
import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
import { inviteLogic } from 'scenes/settings/organization/inviteLogic'
@ -85,27 +84,27 @@ function CurrentOrganization({ organization }: { organization: OrganizationBasic
const { closeAccountPopover } = useActions(navigationLogic)
return (
<Tooltip title="Organization settings" placement="left">
<LemonButton
data-attr="top-menu-item-org-settings"
icon={
<UploadedLogo
name={organization.name}
entityId={organization.id}
mediaId={organization.logo_media_id}
/>
}
sideIcon={<IconGear />}
fullWidth
to={urls.settings('organization')}
onClick={closeAccountPopover}
>
<div className="grow">
<span className="font-medium">{organization.name}</span>
<AccessLevelIndicator organization={organization} />
</div>
</LemonButton>
</Tooltip>
<LemonButton
data-attr="top-menu-item-org-settings"
icon={
<UploadedLogo
name={organization.name}
entityId={organization.id}
mediaId={organization.logo_media_id}
/>
}
sideIcon={<IconGear />}
fullWidth
to={urls.settings('organization')}
onClick={closeAccountPopover}
tooltip="Organization settings"
tooltipPlacement="left"
>
<div className="grow">
<span className="font-medium">{organization.name}</span>
<AccessLevelIndicator organization={organization} />
</div>
</LemonButton>
)
}

View File

@ -5,7 +5,7 @@ import { ActivityLogItem } from 'lib/components/ActivityLog/humanizeActivity'
import { apiStatusLogic } from 'lib/logic/apiStatusLogic'
import { objectClean, toParams } from 'lib/utils'
import posthog from 'posthog-js'
import { ErrorTrackingSymbolSet } from 'scenes/error-tracking/errorTrackingConfigurationSceneLogic'
import { ErrorTrackingSymbolSet } from 'scenes/error-tracking/errorTrackingSymbolSetLogic'
import { stringifiedFingerprint } from 'scenes/error-tracking/utils'
import { RecordingComment } from 'scenes/session-recordings/player/inspector/playerInspectorLogic'
import { SavedSessionRecordingPlaylistsResult } from 'scenes/session-recordings/saved-playlists/savedSessionRecordingPlaylistsLogic'
@ -726,10 +726,6 @@ class ApiRequest {
return this.errorTrackingSymbolSets().addPathComponent('missing')
}
public errorTrackingStackFrames(ids: string[]): ApiRequest {
return this.errorTracking().addPathComponent('stack_frames').withQueryString({ ids })
}
// # Warehouse
public dataWarehouseTables(teamId?: TeamType['id']): ApiRequest {
return this.projectsDetail(teamId).addPathComponent('warehouse_tables')
@ -1872,10 +1868,6 @@ const api = {
async missingSymbolSets(): Promise<ErrorTrackingSymbolSet[]> {
return await new ApiRequest().errorTrackingMissingSymbolSets().get()
},
async fetchStackFrames(ids: string[]): Promise<{ content: string }> {
return await new ApiRequest().errorTrackingStackFrames(ids).get()
},
},
recordings: {

View File

@ -1,13 +1,15 @@
import './ErrorDisplay.scss'
import { IconFlag } from '@posthog/icons'
import { LemonCollapse } from '@posthog/lemon-ui'
import { IconFlag, IconUpload } from '@posthog/icons'
import { LemonButton, LemonCollapse } from '@posthog/lemon-ui'
import { useActions } from 'kea'
import { TitledSnack } from 'lib/components/TitledSnack'
import { LemonDivider } from 'lib/lemon-ui/LemonDivider'
import { LemonSwitch } from 'lib/lemon-ui/LemonSwitch'
import { LemonTag } from 'lib/lemon-ui/LemonTag/LemonTag'
import { Link } from 'lib/lemon-ui/Link'
import { useState } from 'react'
import { errorTrackingSymbolSetLogic } from 'scenes/error-tracking/errorTrackingSymbolSetLogic'
import { EventType } from '~/types'
@ -29,29 +31,53 @@ interface Exception {
value: string
}
function StackTrace({ frames, showAllFrames }: { frames: StackFrame[]; showAllFrames: boolean }): JSX.Element | null {
function StackTrace({
frames,
showAllFrames,
resolved,
}: {
frames: StackFrame[]
showAllFrames: boolean
resolved: boolean
}): JSX.Element | null {
const { setUploadSymbolSetReference } = useActions(errorTrackingSymbolSetLogic)
const displayFrames = showAllFrames ? frames : frames.filter((f) => f.in_app)
const panels = displayFrames.map(({ filename, lineno, colno, function: functionName }, index) => {
return {
key: index,
header: (
<div className="flex flex-wrap space-x-0.5">
<span>{filename}</span>
{functionName ? (
<div className="flex space-x-0.5">
<span className="text-muted">in</span>
<span>{functionName}</span>
</div>
) : null}
{lineno && colno ? (
<div className="flex space-x-0.5">
<span className="text-muted">at line</span>
<div className="flex flex-1 justify-between items-center">
<div className="flex flex-wrap space-x-0.5">
<span>{filename}</span>
{functionName ? (
<div className="flex space-x-0.5">
<span className="text-muted">in</span>
<span>{functionName}</span>
</div>
) : null}
{lineno && colno ? (
<div className="flex space-x-0.5">
<span className="text-muted">at line</span>
<span>
{lineno}:{colno}
</span>
</div>
) : null}
</div>
{!resolved && (
<div className="flex items-center space-x-1">
<span>
{lineno}:{colno}
<LemonTag>Unresolved</LemonTag>
</span>
<LemonButton
icon={<IconUpload />}
size="xsmall"
onClick={() => setUploadSymbolSetReference(filename)}
tooltip="Upload source map"
/>
</div>
) : null}
)}
</div>
),
content: null,
@ -78,7 +104,7 @@ function ChainedStackTraces({ exceptionList }: { exceptionList: Exception[] }):
/>
</div>
{exceptionList.map(({ stacktrace, value }, index) => {
const { frames } = stacktrace || {}
const { frames, type } = stacktrace || {}
if (!showAllFrames && !frames?.some((frame) => frame.in_app)) {
// if we're not showing all frames and there are no in_app frames, skip this exception
return null
@ -87,7 +113,11 @@ function ChainedStackTraces({ exceptionList }: { exceptionList: Exception[] }):
return (
<div key={index} className="ErrorDisplay__stacktrace flex flex-col gap-1 mt-6">
<h3 className="mb-0">{value}</h3>
<StackTrace frames={frames || []} showAllFrames={showAllFrames} />
<StackTrace
frames={frames || []}
resolved={type === 'resolved'}
showAllFrames={showAllFrames}
/>
</div>
)
})}

View File

@ -1,9 +1,3 @@
import { kea, path } from 'kea'
import { loaders } from 'kea-loaders'
import api from 'lib/api'
import type { stackFrameLogicType } from './stackFrameLogicType'
export interface StackFrame {
filename: string
lineno: number
@ -11,20 +5,3 @@ export interface StackFrame {
function: string
in_app?: boolean
}
export const stackFrameLogic = kea<stackFrameLogicType>([
path(['components', 'Errors', 'stackFrameLogic']),
loaders(({ values }) => ({
stackFrames: [
{} as Record<string, StackFrame>,
{
loadFrames: async ({ frameIds }: { frameIds: string[] }) => {
const loadedFrameIds = Object.keys(values.stackFrames)
const ids = frameIds.filter((id) => loadedFrameIds.includes(id))
await api.errorTracking.fetchStackFrames(ids)
return {}
},
},
],
})),
])

View File

@ -1,25 +1,30 @@
import { IconUpload } from '@posthog/icons'
import { LemonButton, LemonFileInput, LemonModal, LemonTable } from '@posthog/lemon-ui'
import { LemonButton, LemonTable } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { Form } from 'kea-forms'
import { IconUploadFile } from 'lib/lemon-ui/icons'
import { LemonField } from 'lib/lemon-ui/LemonField'
import { SceneExport } from 'scenes/sceneTypes'
import { errorTrackingConfigurationSceneLogic } from './errorTrackingConfigurationSceneLogic'
import { errorTrackingSymbolSetLogic } from './errorTrackingSymbolSetLogic'
import { SymbolSetUploadModal } from './SymbolSetUploadModal'
export const scene: SceneExport = {
component: ErrorTrackingConfigurationScene,
logic: errorTrackingConfigurationSceneLogic,
logic: errorTrackingSymbolSetLogic,
}
export function ErrorTrackingConfigurationScene(): JSX.Element {
const { missingSymbolSets, missingSymbolSetsLoading } = useValues(errorTrackingConfigurationSceneLogic)
const { setUploadSymbolSetReference } = useActions(errorTrackingConfigurationSceneLogic)
const { setUploadSymbolSetReference } = useActions(errorTrackingSymbolSetLogic)
const { missingSymbolSets, missingSymbolSetsLoading } = useValues(errorTrackingSymbolSetLogic)
return (
<div>
<h2>Missing symbol sets</h2>
<p>
Source maps are required to demangle any minified code in your exception stack traces. PostHog
automatically retrieves source maps where possible. Cases where it was not possible are listed below.
Source maps can be uploaded retroactively but changes will only apply to all future exceptions ingested.
</p>
<LemonTable
showHeader={false}
columns={[
{ title: 'Reference', dataIndex: 'ref' },
{
@ -43,60 +48,7 @@ export function ErrorTrackingConfigurationScene(): JSX.Element {
loading={missingSymbolSetsLoading}
dataSource={missingSymbolSets}
/>
<SymbolSetUploadModal onClose={() => setUploadSymbolSetReference(null)} />
<SymbolSetUploadModal />
</div>
)
}
const SymbolSetUploadModal = ({ onClose }: { onClose: () => void }): JSX.Element => {
const { uploadSymbolSetReference, isUploadSymbolSetSubmitting, uploadSymbolSet } = useValues(
errorTrackingConfigurationSceneLogic
)
return (
<LemonModal title="" onClose={onClose} isOpen={!!uploadSymbolSetReference} simple>
<Form
logic={errorTrackingConfigurationSceneLogic}
formKey="uploadSymbolSet"
className="gap-1"
enableFormOnSubmit
>
<LemonModal.Header>
<h3>Upload source map</h3>
</LemonModal.Header>
<LemonModal.Content className="space-y-2">
<LemonField name="files">
<LemonFileInput
accept="text/plain"
multiple={false}
callToAction={
<div className="flex flex-col items-center justify-center space-y-2 border border-dashed rounded p-4">
<span className="flex items-center gap-2 font-semibold">
<IconUploadFile className="text-2xl" /> Add source map
</span>
<div>
Drag and drop your local source map here or click to open the file browser.
</div>
</div>
}
/>
</LemonField>
</LemonModal.Content>
<LemonModal.Footer>
<LemonButton type="secondary" onClick={onClose}>
Cancel
</LemonButton>
<LemonButton
disabledReason={uploadSymbolSet.files.length < 1 ? 'Upload a source map' : undefined}
type="primary"
status="alt"
htmlType="submit"
loading={isUploadSymbolSetSubmitting}
>
Upload
</LemonButton>
</LemonModal.Footer>
</Form>
</LemonModal>
)
}

View File

@ -13,6 +13,7 @@ import { AssigneeSelect } from './AssigneeSelect'
import ErrorTrackingFilters from './ErrorTrackingFilters'
import { errorTrackingGroupSceneLogic } from './errorTrackingGroupSceneLogic'
import { OverviewTab } from './groups/OverviewTab'
import { SymbolSetUploadModal } from './SymbolSetUploadModal'
export const scene: SceneExport = {
component: ErrorTrackingGroupScene,
@ -82,6 +83,7 @@ export function ErrorTrackingGroupScene(): JSX.Element {
<LemonDivider className="mt-2" />
<ErrorTrackingFilters.Options isGroup />
<OverviewTab />
<SymbolSetUploadModal />
</>
)
}

View File

@ -0,0 +1,59 @@
import { LemonButton, LemonFileInput, LemonModal } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { Form } from 'kea-forms'
import { IconUploadFile } from 'lib/lemon-ui/icons'
import { LemonField } from 'lib/lemon-ui/LemonField'
import { errorTrackingSymbolSetLogic } from './errorTrackingSymbolSetLogic'
export const SymbolSetUploadModal = (): JSX.Element => {
const { setUploadSymbolSetReference } = useActions(errorTrackingSymbolSetLogic)
const { uploadSymbolSetReference, isUploadSymbolSetSubmitting, uploadSymbolSet } =
useValues(errorTrackingSymbolSetLogic)
const onClose = (): void => {
setUploadSymbolSetReference(null)
}
return (
<LemonModal title="" onClose={onClose} isOpen={!!uploadSymbolSetReference} simple>
<Form logic={errorTrackingSymbolSetLogic} formKey="uploadSymbolSet" className="gap-1" enableFormOnSubmit>
<LemonModal.Header>
<h3>Upload source map</h3>
</LemonModal.Header>
<LemonModal.Content className="space-y-2">
<LemonField name="files">
<LemonFileInput
accept="text/plain"
multiple={false}
callToAction={
<div className="flex flex-col items-center justify-center space-y-2 border border-dashed rounded p-4">
<span className="flex items-center gap-2 font-semibold">
<IconUploadFile className="text-2xl" /> Add source map
</span>
<div>
Drag and drop your local source map here or click to open the file browser.
</div>
</div>
}
/>
</LemonField>
</LemonModal.Content>
<LemonModal.Footer>
<LemonButton type="secondary" onClick={onClose}>
Cancel
</LemonButton>
<LemonButton
disabledReason={uploadSymbolSet.files.length < 1 ? 'Upload a source map' : undefined}
type="primary"
status="alt"
htmlType="submit"
loading={isUploadSymbolSetSubmitting}
>
Upload
</LemonButton>
</LemonModal.Footer>
</Form>
</LemonModal>
)
}

View File

@ -8,7 +8,7 @@ import { urls } from 'scenes/urls'
import { Breadcrumb } from '~/types'
import type { errorTrackingConfigurationSceneLogicType } from './errorTrackingConfigurationSceneLogicType'
import type { errorTrackingSymbolSetLogicType } from './errorTrackingSymbolSetLogicType'
export enum ErrorGroupTab {
Overview = 'overview',
@ -19,8 +19,8 @@ export interface ErrorTrackingSymbolSet {
ref: string
}
export const errorTrackingConfigurationSceneLogic = kea<errorTrackingConfigurationSceneLogicType>([
path((key) => ['scenes', 'error-tracking', 'errorTrackingConfigurationSceneLogic', key]),
export const errorTrackingSymbolSetLogic = kea<errorTrackingSymbolSetLogicType>([
path(['scenes', 'error-tracking', 'errorTrackingSymbolSetLogic']),
actions({
setUploadSymbolSetReference: (ref: string | null) => ({ ref }),

View File

@ -63,6 +63,7 @@ class ErrorTrackingSymbolSetViewSet(TeamAndOrgViewSetMixin, mixins.UpdateModelMi
storage_ptr = upload_symbol_set(request.FILES["source_map"], self.team_id)
symbol_set.storage_ptr = storage_ptr
symbol_set.save()
# TODO: cascade delete the associated frame resolutions
return Response({"ok": True}, status=status.HTTP_204_NO_CONTENT)
@extend_schema(exclude=True)