selectorItem.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import styled from '@emotion/styled';
  2. import Feature from 'sentry/components/acl/feature';
  3. import FeatureDisabled from 'sentry/components/acl/featureDisabled';
  4. import Button from 'sentry/components/button';
  5. import Highlight from 'sentry/components/highlight';
  6. import {Hovercard} from 'sentry/components/hovercard';
  7. import IdBadge from 'sentry/components/idBadge';
  8. import PageFilterRow from 'sentry/components/organizations/pageFilterRow';
  9. import BookmarkStar from 'sentry/components/projects/bookmarkStar';
  10. import {IconOpen, IconSettings} from 'sentry/icons';
  11. import {t} from 'sentry/locale';
  12. import space from 'sentry/styles/space';
  13. import {Organization, Project} from 'sentry/types';
  14. import {analytics} from 'sentry/utils/analytics';
  15. type Props = {
  16. inputValue: string;
  17. isChecked: boolean;
  18. multi: boolean;
  19. organization: Organization;
  20. project: Project;
  21. onMultiSelect?: (project: Project, event: React.MouseEvent) => void;
  22. };
  23. function ProjectSelectorItem({
  24. project,
  25. organization,
  26. onMultiSelect,
  27. multi = false,
  28. inputValue = '',
  29. isChecked = false,
  30. }: Props) {
  31. const handleClick = (event: React.MouseEvent) => {
  32. event.stopPropagation();
  33. onMultiSelect?.(project, event);
  34. };
  35. const handleBookmarkToggle = (isBookmarked: boolean) => {
  36. analytics('projectselector.bookmark_toggle', {
  37. org_id: parseInt(organization.id, 10),
  38. bookmarked: isBookmarked,
  39. });
  40. };
  41. const renderDisabledCheckbox = ({
  42. children,
  43. features,
  44. }: {
  45. children: React.ReactNode;
  46. features: string[];
  47. }) => {
  48. return (
  49. <Hovercard
  50. body={
  51. <FeatureDisabled
  52. features={features}
  53. hideHelpToggle
  54. featureName={t('Multiple Project Selection')}
  55. />
  56. }
  57. >
  58. {children}
  59. </Hovercard>
  60. );
  61. };
  62. return (
  63. <ProjectFilterRow
  64. checked={isChecked}
  65. onCheckClick={handleClick}
  66. multi={multi}
  67. renderCheckbox={({checkbox}) => (
  68. <Feature
  69. features={['organizations:global-views']}
  70. hookName="feature-disabled:project-selector-checkbox"
  71. renderDisabled={renderDisabledCheckbox}
  72. >
  73. {checkbox}
  74. </Feature>
  75. )}
  76. >
  77. <BadgeWrapper>
  78. <IdBadge
  79. project={project}
  80. avatarSize={16}
  81. displayName={<Highlight text={inputValue}>{project.slug}</Highlight>}
  82. avatarProps={{consistentWidth: true}}
  83. disableLink
  84. />
  85. </BadgeWrapper>
  86. <ActionBookmark
  87. project={project}
  88. organization={organization}
  89. onToggle={handleBookmarkToggle}
  90. />
  91. <ActionButton
  92. to={`/organizations/${organization.slug}/projects/${project.slug}/?project=${project.id}`}
  93. size="zero"
  94. priority="link"
  95. aria-label="Project Details"
  96. icon={<IconOpen />}
  97. />
  98. <ActionButton
  99. to={`/settings/${organization.slug}/projects/${project.slug}/`}
  100. size="zero"
  101. priority="link"
  102. aria-label="Project Settings"
  103. icon={<IconSettings />}
  104. />
  105. </ProjectFilterRow>
  106. );
  107. }
  108. export default ProjectSelectorItem;
  109. const BadgeWrapper = styled('div')`
  110. display: flex;
  111. flex: 1;
  112. white-space: nowrap;
  113. overflow: hidden;
  114. `;
  115. const ActionButton = styled(Button)`
  116. color: ${p => p.theme.subText};
  117. padding: ${space(1)} ${space(0.25)} ${space(1)} ${space(1)};
  118. opacity: 0.33;
  119. :hover {
  120. color: ${p => p.theme.textColor};
  121. }
  122. `;
  123. const ActionBookmark = styled(BookmarkStar)`
  124. ${p => !p.project.isBookmarked && 'opacity: 0.33'};
  125. `;
  126. const ProjectFilterRow = styled(PageFilterRow)`
  127. :hover ${ActionButton}, :hover ${ActionBookmark} {
  128. opacity: 1;
  129. }
  130. `;