log-entry.tsx 3.1 KB

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