groupListBody.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import type {IndexedMembersByProject} from 'sentry/actionCreators/members';
  2. import type {GroupListColumn} from 'sentry/components/issues/groupList';
  3. import LoadingError from 'sentry/components/loadingError';
  4. import LoadingIndicator from 'sentry/components/loadingIndicator';
  5. import PanelBody from 'sentry/components/panels/panelBody';
  6. import StreamGroup from 'sentry/components/stream/group';
  7. import GroupStore from 'sentry/stores/groupStore';
  8. import type {Group} from 'sentry/types/group';
  9. import theme from 'sentry/utils/theme';
  10. import useApi from 'sentry/utils/useApi';
  11. import useMedia from 'sentry/utils/useMedia';
  12. import useOrganization from 'sentry/utils/useOrganization';
  13. import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';
  14. import type {IssueUpdateData} from 'sentry/views/issueList/types';
  15. import NoGroupsHandler from './noGroupsHandler';
  16. import {SAVED_SEARCHES_SIDEBAR_OPEN_LOCALSTORAGE_KEY} from './utils';
  17. type GroupListBodyProps = {
  18. displayReprocessingLayout: boolean;
  19. error: string | null;
  20. groupIds: string[];
  21. groupStatsPeriod: string;
  22. loading: boolean;
  23. memberList: IndexedMembersByProject;
  24. onActionTaken: (itemIds: string[], data: IssueUpdateData) => void;
  25. query: string;
  26. refetchGroups: () => void;
  27. selectedProjectIds: number[];
  28. };
  29. type GroupListProps = {
  30. displayReprocessingLayout: boolean;
  31. groupIds: string[];
  32. groupStatsPeriod: string;
  33. memberList: IndexedMembersByProject;
  34. onActionTaken: (itemIds: string[], data: IssueUpdateData) => void;
  35. query: string;
  36. };
  37. function GroupListBody({
  38. groupIds,
  39. memberList,
  40. query,
  41. displayReprocessingLayout,
  42. groupStatsPeriod,
  43. loading,
  44. error,
  45. refetchGroups,
  46. selectedProjectIds,
  47. onActionTaken,
  48. }: GroupListBodyProps) {
  49. const api = useApi();
  50. const organization = useOrganization();
  51. if (loading) {
  52. return <LoadingIndicator hideMessage />;
  53. }
  54. if (error) {
  55. return <LoadingError message={error} onRetry={refetchGroups} />;
  56. }
  57. if (!groupIds.length) {
  58. return (
  59. <NoGroupsHandler
  60. api={api}
  61. organization={organization}
  62. query={query}
  63. selectedProjectIds={selectedProjectIds}
  64. groupIds={groupIds}
  65. />
  66. );
  67. }
  68. return (
  69. <GroupList
  70. groupIds={groupIds}
  71. memberList={memberList}
  72. query={query}
  73. displayReprocessingLayout={displayReprocessingLayout}
  74. groupStatsPeriod={groupStatsPeriod}
  75. onActionTaken={onActionTaken}
  76. />
  77. );
  78. }
  79. function GroupList({
  80. groupIds,
  81. memberList,
  82. query,
  83. displayReprocessingLayout,
  84. groupStatsPeriod,
  85. onActionTaken,
  86. }: GroupListProps) {
  87. const organization = useOrganization();
  88. const [isSavedSearchesOpen] = useSyncedLocalStorageState(
  89. SAVED_SEARCHES_SIDEBAR_OPEN_LOCALSTORAGE_KEY,
  90. false
  91. );
  92. const topIssue = groupIds[0];
  93. const canSelect = !useMedia(
  94. `(max-width: ${
  95. isSavedSearchesOpen ? theme.breakpoints.xlarge : theme.breakpoints.medium
  96. })`
  97. );
  98. const columns: GroupListColumn[] = [
  99. 'graph',
  100. ...(organization.features.includes('issue-stream-table-layout')
  101. ? ['firstSeen' as const, 'lastSeen' as const]
  102. : []),
  103. 'event',
  104. 'users',
  105. 'priority',
  106. 'assignee',
  107. 'lastTriggered',
  108. ];
  109. return (
  110. <PanelBody>
  111. {groupIds.map((id, index) => {
  112. const hasGuideAnchor = id === topIssue;
  113. const group = GroupStore.get(id) as Group | undefined;
  114. return (
  115. <StreamGroup
  116. index={index}
  117. key={id}
  118. id={id}
  119. statsPeriod={groupStatsPeriod}
  120. query={query}
  121. hasGuideAnchor={hasGuideAnchor}
  122. memberList={group?.project ? memberList[group.project.slug] : undefined}
  123. displayReprocessingLayout={displayReprocessingLayout}
  124. useFilteredStats
  125. canSelect={canSelect}
  126. narrowGroups={isSavedSearchesOpen}
  127. onPriorityChange={priority => onActionTaken([id], {priority})}
  128. withColumns={columns}
  129. />
  130. );
  131. })}
  132. </PanelBody>
  133. );
  134. }
  135. export default GroupListBody;