columnEditModal.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import {Fragment, useEffect, useState} from 'react';
  2. import {css} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import {ModalRenderProps} from 'sentry/actionCreators/modal';
  5. import Button from 'sentry/components/button';
  6. import ButtonBar from 'sentry/components/buttonBar';
  7. import ExternalLink from 'sentry/components/links/externalLink';
  8. import {DISCOVER2_DOCS_URL} from 'sentry/constants';
  9. import {t, tct} from 'sentry/locale';
  10. import space from 'sentry/styles/space';
  11. import {Organization} from 'sentry/types';
  12. import {trackAnalyticsEvent} from 'sentry/utils/analytics';
  13. import {Column} from 'sentry/utils/discover/fields';
  14. import theme from 'sentry/utils/theme';
  15. import useTags from 'sentry/utils/useTags';
  16. import {generateFieldOptions} from 'sentry/views/eventsV2/utils';
  17. import ColumnEditCollection from './columnEditCollection';
  18. type Props = {
  19. columns: Column[];
  20. measurementKeys: null | string[];
  21. // Fired when column selections have been applied.
  22. onApply: (columns: Column[]) => void;
  23. organization: Organization;
  24. spanOperationBreakdownKeys?: string[];
  25. } & ModalRenderProps;
  26. function ColumnEditModal(props: Props) {
  27. const {
  28. Header,
  29. Body,
  30. Footer,
  31. measurementKeys,
  32. spanOperationBreakdownKeys,
  33. organization,
  34. onApply,
  35. closeModal,
  36. } = props;
  37. // Only run once for each organization.id.
  38. useEffect(() => {
  39. trackAnalyticsEvent({
  40. eventKey: 'discover_v2.column_editor.open',
  41. eventName: 'Discoverv2: Open column editor',
  42. organization_id: parseInt(organization.id, 10),
  43. });
  44. }, [organization.id]);
  45. const {tags} = useTags();
  46. const tagKeys = Object.values(tags).map(({key}) => key);
  47. const [columns, setColumns] = useState<Column[]>(props.columns);
  48. function handleApply() {
  49. onApply(columns);
  50. closeModal();
  51. }
  52. const fieldOptions = generateFieldOptions({
  53. organization,
  54. tagKeys,
  55. measurementKeys,
  56. spanOperationBreakdownKeys,
  57. });
  58. return (
  59. <Fragment>
  60. <Header closeButton>
  61. <h4>{t('Edit Columns')}</h4>
  62. </Header>
  63. <Body>
  64. <Instruction>
  65. {tct(
  66. 'To group events, add [functionLink: functions] f(x) that may take in additional parameters. [fieldTagLink: Tag and field] columns will help you view more details about the events (i.e. title).',
  67. {
  68. functionLink: (
  69. <ExternalLink href="https://docs.sentry.io/product/discover-queries/query-builder/#filter-by-table-columns" />
  70. ),
  71. fieldTagLink: (
  72. <ExternalLink href="https://docs.sentry.io/product/sentry-basics/search/searchable-properties/#event-properties" />
  73. ),
  74. }
  75. )}
  76. </Instruction>
  77. <ColumnEditCollection
  78. columns={columns}
  79. fieldOptions={fieldOptions}
  80. onChange={setColumns}
  81. organization={organization}
  82. />
  83. </Body>
  84. <Footer>
  85. <ButtonBar gap={1}>
  86. <Button priority="default" href={DISCOVER2_DOCS_URL} external>
  87. {t('Read the Docs')}
  88. </Button>
  89. <Button aria-label={t('Apply')} priority="primary" onClick={handleApply}>
  90. {t('Apply')}
  91. </Button>
  92. </ButtonBar>
  93. </Footer>
  94. </Fragment>
  95. );
  96. }
  97. const Instruction = styled('div')`
  98. margin-bottom: ${space(4)};
  99. `;
  100. const modalCss = css`
  101. @media (min-width: ${theme.breakpoints.medium}) {
  102. width: auto;
  103. max-width: 900px;
  104. }
  105. `;
  106. export default ColumnEditModal;
  107. export {modalCss};