From 14af05ca0ae99052daa1bc3925a382ba6e673e69 Mon Sep 17 00:00:00 2001 From: Scott Cooper Date: Fri, 13 Dec 2024 16:08:50 -0800 Subject: [PATCH] feat(projects): Allow viewing all projects Currently the most projects you can see is "my teams". Allows you to clear or unselect "my teams" similar to the alerts page filters --- .../views/alerts/list/rules/teamFilter.tsx | 40 +++++++++---------- static/app/views/projectsDashboard/index.tsx | 36 ++++++++++------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/static/app/views/alerts/list/rules/teamFilter.tsx b/static/app/views/alerts/list/rules/teamFilter.tsx index a0552245bcd783..5816188ef76bb7 100644 --- a/static/app/views/alerts/list/rules/teamFilter.tsx +++ b/static/app/views/alerts/list/rules/teamFilter.tsx @@ -16,17 +16,13 @@ interface Props { handleChangeFilter: (activeFilters: string[]) => void; selectedTeams: string[]; /** - * only show teams user is a member of + * hide other teams suggestion */ - showIsMemberTeams?: boolean; + hideOtherTeams?: boolean; /** - * show My Teams as the default dropdown description + * hide unassigned suggestion */ - showMyTeamsDescription?: boolean; - /** - * show suggested options (My Teams and Unassigned) - */ - showSuggestedOptions?: boolean; + hideUnassigned?: boolean; } const suggestedOptions = [ @@ -49,11 +45,10 @@ const makeTeamOption = (team: Team) => ({ function TeamFilter({ selectedTeams, handleChangeFilter, - showIsMemberTeams = false, - showSuggestedOptions = true, - showMyTeamsDescription = false, + hideUnassigned = false, + hideOtherTeams = false, }: Props) { - const {teams, onSearch, fetching} = useTeams({provideUserTeams: showIsMemberTeams}); + const {teams, onSearch, fetching} = useTeams(); const [myTeams, otherTeams] = partition(teams, team => team.isMember); const myTeamOptions = myTeams.map(makeTeamOption); @@ -77,11 +72,8 @@ function TeamFilter({ ]; } - return [ - , - showMyTeamsDescription ? t('My Teams') : t('All Teams'), - ]; - }, [selectedTeams, teams, showMyTeamsDescription]); + return [, t('All Teams')]; + }, [selectedTeams, teams]); return ( !hideUnassigned || opt.value !== 'unassigned' + ), + }, {value: '_my_teams', label: t('My Teams'), options: myTeamOptions}, - {value: '_teams', label: t('Other Teams'), options: otherTeamOptions}, + ...(hideOtherTeams + ? [] + : [{value: '_teams', label: t('Other Teams'), options: otherTeamOptions}]), ]} value={selectedTeams} onSearch={debounce(val => void onSearch(val), DEFAULT_DEBOUNCE_DURATION)} diff --git a/static/app/views/projectsDashboard/index.tsx b/static/app/views/projectsDashboard/index.tsx index 2badaf5891b4cf..b9e2298881c7d4 100644 --- a/static/app/views/projectsDashboard/index.tsx +++ b/static/app/views/projectsDashboard/index.tsx @@ -31,6 +31,7 @@ import { } from 'sentry/utils/performanceForSentry'; import {sortProjects} from 'sentry/utils/project/sortProjects'; import useOrganization from 'sentry/utils/useOrganization'; +import useProjects from 'sentry/utils/useProjects'; import withApi from 'sentry/utils/withApi'; import withOrganization from 'sentry/utils/withOrganization'; import withTeamsForUser from 'sentry/utils/withTeamsForUser'; @@ -90,31 +91,39 @@ function Dashboard({teams, organization, loadingTeams, error, router, location}: () => debounce(handleSearch, DEFAULT_DEBOUNCE_DURATION), [] ); + const {projects, fetching, fetchError} = useProjects(); const canUserCreateProject = canCreateProject(organization); - if (loadingTeams) { + if (loadingTeams || fetching) { return ; } - if (error) { + if (error || fetchError) { return ; } const canJoinTeam = organization.access.includes('team:read'); - const selectedTeams = getTeamParams(location ? location.query.team : ''); - const filteredTeams = teams.filter(team => selectedTeams.includes(team.id)); + const selectedTeams = getTeamParams(location.query.team ?? 'myteams'); + const filteredTeams = + selectedTeams[0] === 'myteams' + ? teams + : teams.filter(team => selectedTeams.includes(team.id)); const filteredTeamProjects = uniqBy( (filteredTeams ?? teams).flatMap(team => team.projects), 'id' ); - const projects = uniqBy( - teams.flatMap(teamObj => teamObj.projects), - 'id' - ); setGroupedEntityTag('projects.total', 1000, projects.length); - const currentProjects = selectedTeams.length === 0 ? projects : filteredTeamProjects; + const currentProjects = + // No teams are specifically selected and query parameter is present + // Use all projects + location.query.team === '' + ? projects + : // No teams are specifically selected - Use "myteams" + selectedTeams.length === 0 + ? projects + : filteredTeamProjects; const filteredProjects = (currentProjects ?? projects).filter(project => project.slug.includes(projectQuery) ); @@ -126,12 +135,10 @@ function Dashboard({teams, organization, loadingTeams, error, router, location}: } function handleChangeFilter(activeFilters: string[]) { - const {...currentQuery} = location.query; - router.push({ pathname: location.pathname, query: { - ...currentQuery, + ...location.query, team: activeFilters.length > 0 ? activeFilters : '', }, }); @@ -190,9 +197,8 @@ function Dashboard({teams, organization, loadingTeams, error, router, location}: