starfishProjectSelector.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import {useMemo, useState} from 'react';
  2. import {updateProjects} from 'sentry/actionCreators/pageFilters';
  3. import {CompactSelect} from 'sentry/components/compactSelect';
  4. import ProjectBadge from 'sentry/components/idBadge/projectBadge';
  5. import {t} from 'sentry/locale';
  6. import type {Project} from 'sentry/types';
  7. import useOrganization from 'sentry/utils/useOrganization';
  8. import usePageFilters from 'sentry/utils/usePageFilters';
  9. import useProjects from 'sentry/utils/useProjects';
  10. import useRouter from 'sentry/utils/useRouter';
  11. import {ALLOWED_PROJECT_IDS_FOR_ORG_SLUG} from 'sentry/views/starfish/allowedProjects';
  12. export function StarfishProjectSelector() {
  13. const {projects, initiallyLoaded: projectsLoaded, fetchError} = useProjects();
  14. const organization = useOrganization();
  15. const router = useRouter();
  16. const {selection} = usePageFilters();
  17. const allowedProjectIDs: string[] = useMemo(
  18. () => ALLOWED_PROJECT_IDS_FOR_ORG_SLUG[organization.slug] ?? [],
  19. [organization.slug]
  20. );
  21. const [selectedProjectId, setSelectedProjectId] = useState(
  22. selection.projects[0] ?? allowedProjectIDs[0]
  23. );
  24. const currentProject = selection.projects[0] ?? allowedProjectIDs[0];
  25. if (selectedProjectId !== currentProject) {
  26. setSelectedProjectId(currentProject);
  27. }
  28. if (!projectsLoaded) {
  29. return (
  30. <CompactSelect
  31. disabled
  32. options={[{label: t('Loading\u2026'), value: 'loading'}]}
  33. defaultValue="loading"
  34. />
  35. );
  36. }
  37. if (fetchError) {
  38. throw new Error('Failed to fetch projects');
  39. }
  40. const projectOptions = projects
  41. .filter(project => allowedProjectIDs.includes(project.id))
  42. .map(project => ({
  43. label: <ProjectOptionLabel project={project} />,
  44. value: project.id,
  45. }))
  46. .sort((projectA, projectB) => Number(projectA.value) - Number(projectB.value));
  47. const handleProjectChange = option =>
  48. updateProjects([parseInt(option.value, 10)], router, {
  49. storageNamespace: 'starfish',
  50. save: true,
  51. });
  52. return (
  53. <CompactSelect
  54. menuWidth={250}
  55. options={projectOptions}
  56. value={String(selectedProjectId)}
  57. onChange={handleProjectChange}
  58. />
  59. );
  60. }
  61. function ProjectOptionLabel({project}: {project: Project}) {
  62. return <ProjectBadge project={project} avatarSize={20} disableLink />;
  63. }