LogDetailsPanel.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import dayjs from 'dayjs'
  2. import { Input, SidePanel, TextArea } from 'ui'
  3. import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
  4. import {
  5. FormSection,
  6. FormSectionContent,
  7. FormSectionLabel,
  8. } from '@/components/ui/Forms/FormSection'
  9. import {
  10. TIMESTAMP_MICROS_PER_MS,
  11. type AuditLog,
  12. } from '@/data/organizations/organization-audit-logs-query'
  13. interface LogDetailsPanelProps {
  14. selectedLog?: AuditLog
  15. onClose: () => void
  16. }
  17. export const LogDetailsPanel = ({ selectedLog, onClose }: LogDetailsPanelProps) => {
  18. const timestamp = selectedLog
  19. ? dayjs(selectedLog.timestamp / TIMESTAMP_MICROS_PER_MS).format('DD MMM YYYY, HH:mm:ss')
  20. : ''
  21. const timestampWithTz = selectedLog
  22. ? dayjs(selectedLog.timestamp / TIMESTAMP_MICROS_PER_MS).format('DD MMM YYYY, HH:mm:ss (ZZ)')
  23. : ''
  24. return (
  25. <SidePanel
  26. size="large"
  27. header={selectedLog ? `"${selectedLog.action.name}" on ${timestamp}` : ''}
  28. visible={selectedLog !== undefined}
  29. onCancel={onClose}
  30. cancelText="Close"
  31. >
  32. <FormSection header={<FormSectionLabel>General</FormSectionLabel>}>
  33. <FormSectionContent loading={false}>
  34. <FormItemLayout label="Occurred at" description={timestampWithTz} isReactForm={false}>
  35. <Input
  36. readOnly
  37. size="small"
  38. value={
  39. selectedLog
  40. ? dayjs(selectedLog.timestamp / TIMESTAMP_MICROS_PER_MS).toISOString()
  41. : ''
  42. }
  43. />
  44. </FormItemLayout>
  45. <FormItemLayout label="Request ID" isReactForm={false}>
  46. <Input readOnly size="small" value={selectedLog?.request_id ?? ''} />
  47. </FormItemLayout>
  48. {selectedLog?.organization_slug && (
  49. <FormItemLayout label="Organization" isReactForm={false}>
  50. <Input readOnly size="small" value={selectedLog.organization_slug} />
  51. </FormItemLayout>
  52. )}
  53. {selectedLog?.project_ref && (
  54. <FormItemLayout label="Project ref" isReactForm={false}>
  55. <Input readOnly size="small" value={selectedLog.project_ref} />
  56. </FormItemLayout>
  57. )}
  58. </FormSectionContent>
  59. </FormSection>
  60. <SidePanel.Separator />
  61. <FormSection header={<FormSectionLabel>Actor</FormSectionLabel>}>
  62. <FormSectionContent loading={false}>
  63. <FormItemLayout label="Token type" isReactForm={false}>
  64. <Input readOnly size="small" value={selectedLog?.actor.token_type ?? ''} />
  65. </FormItemLayout>
  66. {selectedLog?.actor.email && (
  67. <FormItemLayout label="Email" isReactForm={false}>
  68. <Input readOnly size="small" value={selectedLog?.actor.email ?? ''} />
  69. </FormItemLayout>
  70. )}
  71. {selectedLog?.actor.user_id && (
  72. <FormItemLayout label="User ID" isReactForm={false}>
  73. <Input readOnly size="small" value={selectedLog?.actor.user_id ?? ''} />
  74. </FormItemLayout>
  75. )}
  76. {selectedLog?.actor.ip && (
  77. <FormItemLayout label="IP address" isReactForm={false}>
  78. <Input readOnly size="small" value={selectedLog?.actor.ip ?? ''} />
  79. </FormItemLayout>
  80. )}
  81. {selectedLog?.actor.oauth_app_name && (
  82. <FormItemLayout label="OAuth app" isReactForm={false}>
  83. <Input readOnly size="small" value={selectedLog?.actor.oauth_app_name ?? ''} />
  84. </FormItemLayout>
  85. )}
  86. {selectedLog?.actor.app_name && (
  87. <FormItemLayout label="App" isReactForm={false}>
  88. <Input readOnly size="small" value={selectedLog?.actor.app_name ?? ''} />
  89. </FormItemLayout>
  90. )}
  91. </FormSectionContent>
  92. </FormSection>
  93. <SidePanel.Separator />
  94. <FormSection header={<FormSectionLabel>Action</FormSectionLabel>}>
  95. <FormSectionContent loading={false}>
  96. <FormItemLayout label="Name" isReactForm={false}>
  97. <Input readOnly size="small" value={selectedLog?.action.name ?? ''} />
  98. </FormItemLayout>
  99. <FormItemLayout label="Method" isReactForm={false}>
  100. <Input readOnly size="small" value={selectedLog?.action.method ?? ''} />
  101. </FormItemLayout>
  102. <FormItemLayout label="Route" isReactForm={false}>
  103. <Input readOnly size="small" value={selectedLog?.action.route ?? ''} />
  104. </FormItemLayout>
  105. <FormItemLayout label="Status" isReactForm={false}>
  106. <Input readOnly size="small" value={String(selectedLog?.action.status ?? '')} />
  107. </FormItemLayout>
  108. {selectedLog?.action.metadata && (
  109. <FormItemLayout label="Metadata" isReactForm={false}>
  110. <TextArea
  111. readOnly
  112. rows={5}
  113. className="font-mono input-xs"
  114. value={JSON.stringify(selectedLog.action.metadata, null, 2)}
  115. />
  116. </FormItemLayout>
  117. )}
  118. </FormSectionContent>
  119. </FormSection>
  120. </SidePanel>
  121. )
  122. }