Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ import {SimpleTable} from 'sentry/components/tables/simpleTable';
import {IconSearch} from 'sentry/icons/iconSearch';
import {t, tct} from 'sentry/locale';
import {ProjectsStore} from 'sentry/stores/projectsStore';
import type {Project} from 'sentry/types/project';
import {useFetchAllPages} from 'sentry/utils/api/apiFetch';
import type {Sort} from 'sentry/utils/discover/fields';
import {ListItemCheckboxProvider} from 'sentry/utils/list/useListItemCheckboxState';
import {useInfiniteQuery, useQuery, useQueryClient} from 'sentry/utils/queryClient';
import type {ApiQueryKey} from 'sentry/utils/queryClient';
Expand Down Expand Up @@ -193,166 +191,89 @@ export function SeerProjectTable() {
return filtered;
}, [sortedProjects, searchTerm, agentFilter, autofixSettingsByProjectId]);

if (fetching) {
return (
<ProjectTable
agentFilter={agentFilter}
codingAgentCompactSelectOptions={codingAgentCompactSelectOptions.data ?? []}
projects={filteredProjects}
onSortClick={setSort}
setAgentFilter={setAgentFilter}
sort={sort}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
updateBulkAutofixAutomationSettings={updateBulkAutofixAutomationSettings}
>
<SimpleTable.Empty>
<LoadingIndicator />
</SimpleTable.Empty>
</ProjectTable>
);
}

if (fetchError) {
return (
<ProjectTable
agentFilter={agentFilter}
codingAgentCompactSelectOptions={codingAgentCompactSelectOptions.data ?? []}
projects={filteredProjects}
onSortClick={setSort}
setAgentFilter={setAgentFilter}
sort={sort}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
updateBulkAutofixAutomationSettings={updateBulkAutofixAutomationSettings}
>
<SimpleTable.Empty>
<LoadingError />
</SimpleTable.Empty>
</ProjectTable>
);
}

return (
<ListItemCheckboxProvider
hits={filteredProjects.length}
knownIds={filteredProjects.map(project => project.id)}
queryKey={queryKey}
>
<ProjectTable
agentFilter={agentFilter}
codingAgentCompactSelectOptions={codingAgentCompactSelectOptions.data ?? []}
projects={filteredProjects}
onSortClick={setSort}
setAgentFilter={setAgentFilter}
sort={sort}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
updateBulkAutofixAutomationSettings={updateBulkAutofixAutomationSettings}
>
{filteredProjects.length === 0 ? (
<SimpleTable.Empty>
{searchTerm
? agentFilter
? tct('No projects found matching [searchTerm] with [agentFilter]', {
searchTerm: <code>{searchTerm}</code>,
agentFilter: <code>{getFilteredCodingAgentName(agentFilter)}</code>,
})
: tct('No projects found matching [searchTerm]', {
searchTerm: <code>{searchTerm}</code>,
})
: agentFilter
? tct('No projects found with [agentFilter]', {
agentFilter: <code>{getFilteredCodingAgentName(agentFilter)}</code>,
})
: t('No projects found')}
</SimpleTable.Empty>
) : (
filteredProjects.map(project => (
<SeerProjectTableRow
key={project.id}
autofixSettings={autofixSettingsByProjectId.get(project.id)}
integrations={integrations ?? []}
isPendingIntegrations={isPendingIntegrations}
project={project}
agentOptions={agentOptions}
<Stack gap="lg">
<Flex gap="md">
{codingAgentCompactSelectOptions.data?.length ? (
<CompactSelect<'' | PreferredAgentProvider>
trigger={triggerProps => (
<OverlayTrigger.Button {...triggerProps} size="md" prefix={t('Agent')}>
{agentFilter ? triggerProps.children : t('All')}
</OverlayTrigger.Button>
)}
options={codingAgentCompactSelectOptions.data ?? []}
onChange={option => setAgentFilter(option.value || null)}
value={agentFilter ?? ''}
/>
))
)}
</ProjectTable>
</ListItemCheckboxProvider>
);
}
) : null}

function ProjectTable({
agentFilter,
codingAgentCompactSelectOptions,
children,
onSortClick,
projects,
searchTerm,
setAgentFilter,
setSearchTerm,
sort,
updateBulkAutofixAutomationSettings,
}: {
agentFilter: null | PreferredAgentProvider;
children: React.ReactNode;
codingAgentCompactSelectOptions: Array<{
label: React.ReactNode;
value: '' | PreferredAgentProvider;
}>;
onSortClick: (sort: Sort) => void;
projects: Project[];
searchTerm: string;
setAgentFilter: ReturnType<typeof useQueryState<PreferredAgentProvider>>[1];
setSearchTerm: ReturnType<typeof useQueryState<string>>[1];
sort: Sort;
updateBulkAutofixAutomationSettings: ReturnType<
typeof useUpdateBulkAutofixAutomationSettings
>['mutate'];
}) {
return (
<Stack gap="lg">
<Flex gap="md">
{codingAgentCompactSelectOptions.length ? (
<CompactSelect<'' | PreferredAgentProvider>
trigger={triggerProps => (
<OverlayTrigger.Button {...triggerProps} size="md" prefix={t('Agent')}>
{agentFilter ? triggerProps.children : t('All')}
</OverlayTrigger.Button>
)}
options={codingAgentCompactSelectOptions}
onChange={option => setAgentFilter(option.value || null)}
value={agentFilter ?? ''}
/>
) : null}

<InputGroup style={{width: '100%'}}>
<InputGroup.LeadingItems disablePointerEvents>
<IconSearch />
</InputGroup.LeadingItems>
<InputGroup.Input
size="md"
placeholder={t('Search')}
value={searchTerm ?? ''}
onChange={e =>
setSearchTerm(e.target.value, {limitUrlUpdates: debounce(125)})
}
<InputGroup style={{width: '100%'}}>
<InputGroup.LeadingItems disablePointerEvents>
<IconSearch />
</InputGroup.LeadingItems>
<InputGroup.Input
size="md"
placeholder={t('Search')}
value={searchTerm ?? ''}
onChange={e =>
setSearchTerm(e.target.value, {limitUrlUpdates: debounce(125)})
}
/>
</InputGroup>
</Flex>
<SimpleTableWithColumns>
<ProjectTableHeader
projects={filteredProjects}
onSortClick={setSort}
sort={sort}
updateBulkAutofixAutomationSettings={updateBulkAutofixAutomationSettings}
/>
</InputGroup>
</Flex>

<SimpleTableWithColumns>
<ProjectTableHeader
projects={projects}
onSortClick={onSortClick}
sort={sort}
updateBulkAutofixAutomationSettings={updateBulkAutofixAutomationSettings}
/>
{children}
</SimpleTableWithColumns>
</Stack>
{fetching ? (
<SimpleTable.Empty>
<LoadingIndicator />
</SimpleTable.Empty>
) : fetchError ? (
<SimpleTable.Empty>
<LoadingError />
</SimpleTable.Empty>
) : filteredProjects.length === 0 ? (
<SimpleTable.Empty>
{searchTerm
? agentFilter
? tct('No projects found matching [searchTerm] with [agentFilter]', {
searchTerm: <code>{searchTerm}</code>,
agentFilter: <code>{getFilteredCodingAgentName(agentFilter)}</code>,
})
: tct('No projects found matching [searchTerm]', {
searchTerm: <code>{searchTerm}</code>,
})
: agentFilter
? tct('No projects found with [agentFilter]', {
agentFilter: <code>{getFilteredCodingAgentName(agentFilter)}</code>,
})
: t('No projects found')}
</SimpleTable.Empty>
) : (
filteredProjects.map(project => (
<SeerProjectTableRow
key={project.id}
autofixSettings={autofixSettingsByProjectId.get(project.id)}
integrations={integrations ?? []}
isPendingIntegrations={isPendingIntegrations}
project={project}
agentOptions={agentOptions}
/>
))
)}
</SimpleTableWithColumns>
</Stack>
</ListItemCheckboxProvider>
);
}

Expand Down
Loading