index.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import {Fragment, useCallback, useEffect, useState} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  4. import {CursorHandler} from 'sentry/components/pagination';
  5. import {AuditLog, Organization} from 'sentry/types';
  6. import useApi from 'sentry/utils/useApi';
  7. import withOrganization from 'sentry/utils/withOrganization';
  8. import AuditLogList from './auditLogList';
  9. type Props = {
  10. organization: Organization;
  11. };
  12. type State = {
  13. entryList: AuditLog[] | null;
  14. entryListPageLinks: string | null;
  15. eventTypes: string[] | null;
  16. isLoading: boolean;
  17. currentCursor?: string;
  18. eventType?: string;
  19. };
  20. function OrganizationAuditLog({organization}: Props) {
  21. const [state, setState] = useState<State>({
  22. entryList: [],
  23. entryListPageLinks: null,
  24. eventTypes: [],
  25. isLoading: true,
  26. });
  27. const api = useApi();
  28. const handleCursor: CursorHandler = resultsCursor => {
  29. setState(prevState => ({
  30. ...prevState,
  31. currentCursor: resultsCursor,
  32. }));
  33. };
  34. const fetchAuditLogData = useCallback(async () => {
  35. try {
  36. const payload = {cursor: state.currentCursor, event: state.eventType, version: '2'};
  37. if (!payload.cursor) {
  38. delete payload.cursor;
  39. }
  40. if (!payload.event) {
  41. delete payload.event;
  42. }
  43. const [data, _, response] = await api.requestPromise(
  44. `/organizations/${organization.slug}/audit-logs/`,
  45. {
  46. method: 'GET',
  47. includeAllArgs: true,
  48. query: payload,
  49. }
  50. );
  51. setState(prevState => ({
  52. ...prevState,
  53. entryList: data.rows,
  54. eventTypes: data.options.sort(),
  55. isLoading: false,
  56. entryListPageLinks: response?.getResponseHeader('Link') ?? null,
  57. }));
  58. } catch (err) {
  59. if (err.status !== 401 && err.status !== 403) {
  60. Sentry.captureException(err);
  61. }
  62. setState(prevState => ({
  63. ...prevState,
  64. isLoading: false,
  65. }));
  66. addErrorMessage('Unable to load audit logs.');
  67. }
  68. }, [api, organization.slug, state.currentCursor, state.eventType]);
  69. useEffect(() => {
  70. fetchAuditLogData();
  71. }, [fetchAuditLogData]);
  72. const handleEventSelect = (value: string | undefined) => {
  73. setState(prevState => ({
  74. ...prevState,
  75. eventType: value,
  76. }));
  77. };
  78. return (
  79. <Fragment>
  80. <AuditLogList
  81. entries={state.entryList}
  82. pageLinks={state.entryListPageLinks}
  83. eventType={state.eventType}
  84. eventTypes={state.eventTypes}
  85. onEventSelect={handleEventSelect}
  86. isLoading={state.isLoading}
  87. onCursor={handleCursor}
  88. />
  89. </Fragment>
  90. );
  91. }
  92. export default withOrganization(OrganizationAuditLog);