log-entry.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { memo, MouseEventHandler, useCallback, useState } from 'react'
  2. import HumanReadableLogsHints from '../../../../ide/human-readable-logs/HumanReadableLogsHints'
  3. import { sendMB } from '@/infrastructure/event-tracking'
  4. import {
  5. ErrorLevel,
  6. LogEntry as LogEntryData,
  7. SourceLocation,
  8. } from '@/features/pdf-preview/util/types'
  9. import LogEntryHeader from './log-entry-header'
  10. import PdfLogEntryContent from '@/features/pdf-preview/components/pdf-log-entry-content'
  11. function LogEntry({
  12. ruleId,
  13. headerTitle,
  14. rawContent,
  15. logType,
  16. formattedContent,
  17. extraInfoURL,
  18. level,
  19. sourceLocation,
  20. showSourceLocationLink = true,
  21. entryAriaLabel = undefined,
  22. contentDetails,
  23. onSourceLocationClick,
  24. index,
  25. logEntry,
  26. id,
  27. alwaysExpandRawContent = false,
  28. }: {
  29. headerTitle: string | React.ReactNode
  30. level: ErrorLevel
  31. ruleId?: string
  32. rawContent?: string
  33. logType?: string
  34. formattedContent?: React.ReactNode
  35. extraInfoURL?: string | null
  36. sourceLocation?: SourceLocation
  37. showSourceLocationLink?: boolean
  38. entryAriaLabel?: string
  39. contentDetails?: string[]
  40. onSourceLocationClick?: (sourceLocation: SourceLocation) => void
  41. index?: number
  42. logEntry?: LogEntryData
  43. id?: string
  44. alwaysExpandRawContent?: boolean
  45. }) {
  46. const [collapsed, setCollapsed] = useState(true)
  47. if (ruleId && HumanReadableLogsHints[ruleId]) {
  48. const hint = HumanReadableLogsHints[ruleId]
  49. formattedContent = hint.formattedContent(contentDetails)
  50. extraInfoURL = hint.extraInfoURL
  51. }
  52. const handleLogEntryLinkClick: MouseEventHandler<HTMLButtonElement> =
  53. useCallback(
  54. event => {
  55. event.preventDefault()
  56. if (onSourceLocationClick && sourceLocation) {
  57. onSourceLocationClick(sourceLocation)
  58. const parts = sourceLocation?.file?.split('.')
  59. const extension =
  60. parts?.length && parts?.length > 1 ? parts.pop() : ''
  61. sendMB('log-entry-link-click', { level, ruleId, extension })
  62. }
  63. },
  64. [level, onSourceLocationClick, ruleId, sourceLocation]
  65. )
  66. return (
  67. <div
  68. className="log-entry"
  69. data-ruleid={ruleId}
  70. data-log-entry-id={id}
  71. aria-label={entryAriaLabel}
  72. >
  73. <LogEntryHeader
  74. level={level}
  75. sourceLocation={sourceLocation}
  76. headerTitle={headerTitle}
  77. logType={logType}
  78. showSourceLocationLink={showSourceLocationLink}
  79. onSourceLocationClick={handleLogEntryLinkClick}
  80. collapsed={collapsed}
  81. onToggleCollapsed={() => setCollapsed(collapsed => !collapsed)}
  82. id={id}
  83. logEntry={logEntry}
  84. />
  85. {!collapsed && (
  86. <>
  87. <div className="horizontal-divider" />
  88. <PdfLogEntryContent
  89. alwaysExpandRawContent={alwaysExpandRawContent}
  90. rawContent={rawContent}
  91. formattedContent={formattedContent}
  92. extraInfoURL={extraInfoURL}
  93. index={index}
  94. logEntry={logEntry}
  95. />
  96. </>
  97. )}
  98. </div>
  99. )
  100. }
  101. export default memo(LogEntry)