utils.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import {Location} from 'history';
  2. import pick from 'lodash/pick';
  3. import MarkLine from 'app/components/charts/components/markLine';
  4. import {URL_PARAM} from 'app/constants/globalSelectionHeader';
  5. import {t} from 'app/locale';
  6. import {
  7. Commit,
  8. CommitFile,
  9. FilesByRepository,
  10. GlobalSelection,
  11. LightWeightOrganization,
  12. ReleaseComparisonChartType,
  13. Repository,
  14. } from 'app/types';
  15. import {getUtcDateString} from 'app/utils/dates';
  16. import EventView from 'app/utils/discover/eventView';
  17. import {Theme} from 'app/utils/theme';
  18. import {QueryResults} from 'app/utils/tokenizeSearch';
  19. import {commonTermsDescription, SessionTerm} from '../utils/sessionTerm';
  20. export type CommitsByRepository = {
  21. [key: string]: Commit[];
  22. };
  23. /**
  24. * Convert list of individual file changes into a per-file summary grouped by repository
  25. */
  26. export function getFilesByRepository(fileList: CommitFile[]) {
  27. return fileList.reduce<FilesByRepository>((filesByRepository, file) => {
  28. const {filename, repoName, author, type} = file;
  29. if (!filesByRepository.hasOwnProperty(repoName)) {
  30. filesByRepository[repoName] = {};
  31. }
  32. if (!filesByRepository[repoName].hasOwnProperty(filename)) {
  33. filesByRepository[repoName][filename] = {
  34. authors: {},
  35. types: new Set(),
  36. };
  37. }
  38. if (author.email) {
  39. filesByRepository[repoName][filename].authors[author.email] = author;
  40. }
  41. filesByRepository[repoName][filename].types.add(type);
  42. return filesByRepository;
  43. }, {});
  44. }
  45. /**
  46. * Convert list of individual commits into a summary grouped by repository
  47. */
  48. export function getCommitsByRepository(commitList: Commit[]): CommitsByRepository {
  49. return commitList.reduce((commitsByRepository, commit) => {
  50. const repositoryName = commit.repository?.name ?? t('unknown');
  51. if (!commitsByRepository.hasOwnProperty(repositoryName)) {
  52. commitsByRepository[repositoryName] = [];
  53. }
  54. commitsByRepository[repositoryName].push(commit);
  55. return commitsByRepository;
  56. }, {});
  57. }
  58. /**
  59. * Get request query according to the url params and active repository
  60. */
  61. type GetQueryProps = {
  62. location: Location;
  63. perPage?: number;
  64. activeRepository?: Repository;
  65. };
  66. export function getQuery({location, perPage = 40, activeRepository}: GetQueryProps) {
  67. const query = {
  68. ...pick(location.query, [...Object.values(URL_PARAM), 'cursor']),
  69. per_page: perPage,
  70. };
  71. if (!activeRepository) {
  72. return query;
  73. }
  74. return {...query, repo_name: activeRepository.name};
  75. }
  76. /**
  77. * Get repositories to render according to the activeRepository
  78. */
  79. export function getReposToRender(repos: Array<string>, activeRepository?: Repository) {
  80. if (!activeRepository) {
  81. return repos;
  82. }
  83. return [activeRepository.name];
  84. }
  85. /**
  86. * Get high level transaction information for this release
  87. */
  88. export function getReleaseEventView(
  89. selection: GlobalSelection,
  90. version: string,
  91. organization: LightWeightOrganization
  92. ): EventView {
  93. const {projects, environments, datetime} = selection;
  94. const {start, end, period} = datetime;
  95. const apdexField = organization.features.includes('project-transaction-threshold')
  96. ? 'apdex()'
  97. : `apdex(${organization.apdexThreshold})`;
  98. const discoverQuery = {
  99. id: undefined,
  100. version: 2,
  101. name: `${t('Release Apdex')}`,
  102. fields: [apdexField],
  103. query: new QueryResults([
  104. `release:${version}`,
  105. 'event.type:transaction',
  106. 'count():>0',
  107. ]).formatString(),
  108. range: period,
  109. environment: environments,
  110. projects,
  111. start: start ? getUtcDateString(start) : undefined,
  112. end: end ? getUtcDateString(end) : undefined,
  113. } as const;
  114. return EventView.fromSavedQuery(discoverQuery);
  115. }
  116. export const releaseComparisonChartLabels = {
  117. [ReleaseComparisonChartType.CRASH_FREE_SESSIONS]: t('Crash Free Sessions'),
  118. [ReleaseComparisonChartType.CRASH_FREE_USERS]: t('Crash Free Users'),
  119. [ReleaseComparisonChartType.SESSION_COUNT]: t('Session Count'),
  120. [ReleaseComparisonChartType.USER_COUNT]: t('User Count'),
  121. };
  122. export const releaseComparisonChartHelp = {
  123. [ReleaseComparisonChartType.CRASH_FREE_SESSIONS]:
  124. commonTermsDescription[SessionTerm.CRASH_FREE_SESSIONS],
  125. [ReleaseComparisonChartType.CRASH_FREE_USERS]:
  126. commonTermsDescription[SessionTerm.CRASH_FREE_USERS],
  127. [ReleaseComparisonChartType.SESSION_COUNT]: t(
  128. 'The number of sessions in a given period.'
  129. ),
  130. [ReleaseComparisonChartType.USER_COUNT]: t('The number of users in a given period.'),
  131. };
  132. export function generateReleaseMarkLine(title: string, position: number, theme: Theme) {
  133. return {
  134. seriesName: title,
  135. type: 'line',
  136. data: [],
  137. markLine: MarkLine({
  138. silent: true,
  139. lineStyle: {color: theme.gray300, type: 'solid'},
  140. label: {
  141. position: 'insideEndBottom',
  142. formatter: title,
  143. font: 'Rubik',
  144. fontSize: 11,
  145. } as any, // TODO(ts): weird echart types,
  146. data: [
  147. {
  148. xAxis: position,
  149. },
  150. ] as any, // TODO(ts): weird echart types
  151. }),
  152. };
  153. }