123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- import {Fragment, useState} from 'react';
- import {Alert} from 'sentry/components/alert';
- import {LinkButton} from 'sentry/components/button';
- import EmptyMessage from 'sentry/components/emptyMessage';
- import LoadingError from 'sentry/components/loadingError';
- import LoadingIndicator from 'sentry/components/loadingIndicator';
- import Pagination from 'sentry/components/pagination';
- import Panel from 'sentry/components/panels/panel';
- import PanelBody from 'sentry/components/panels/panelBody';
- import PanelHeader from 'sentry/components/panels/panelHeader';
- import RepositoryRow from 'sentry/components/repositoryRow';
- import {IconCommit} from 'sentry/icons';
- import {t} from 'sentry/locale';
- import RepositoryStore from 'sentry/stores/repositoryStore';
- import type {Integration, Repository} from 'sentry/types/integrations';
- import {useApiQuery} from 'sentry/utils/queryClient';
- import useOrganization from 'sentry/utils/useOrganization';
- import {IntegrationReposAddRepository} from './integrationReposAddRepository';
- type Props = {
- integration: Integration;
- };
- function IntegrationRepos(props: Props) {
- const [integrationReposErrorStatus, setIntegrationReposeErrorStatus] = useState<
- number | null | undefined
- >(null);
- const {integration} = props;
- const organization = useOrganization();
- const ENDPOINT = `/organizations/${organization.slug}/repos/`;
- const {
- data: fetchedItemList,
- isPending,
- isError,
- refetch,
- getResponseHeader,
- } = useApiQuery<Repository[]>(
- [ENDPOINT, {query: {status: 'active', integration_id: integration.id}}],
- {
- staleTime: 0,
- }
- );
- const [itemListState, setItemList] = useState<Repository[]>([]);
- if (isPending) {
- return <LoadingIndicator />;
- }
- if (isError) {
- return <LoadingError onRetry={refetch} />;
- }
- const itemList = itemListState.length ? itemListState : fetchedItemList;
- // Called by row to signal repository change.
- const onRepositoryChange = (data: Repository) => {
- const newItemList = itemList.map(item => {
- if (item.id === data.id) {
- item.status = data.status;
- // allow for custom scm repositories to be updated, and
- // url is optional and therefore can be an empty string
- item.url = data.url === undefined ? item.url : data.url;
- item.name = data.name || item.name;
- }
- return item;
- });
- setItemList(newItemList);
- RepositoryStore.resetRepositories();
- };
- const handleAddRepository = (repo: Repository) => {
- setItemList([...itemList, repo]);
- };
- const itemListPageLinks = getResponseHeader?.('Link') ?? undefined;
- return (
- <Fragment>
- {integrationReposErrorStatus === 400 && (
- <Alert type="error" showIcon>
- {t(
- 'We were unable to fetch repositories for this integration. Try again later. If this error continues, please reconnect this integration by uninstalling and then reinstalling.'
- )}
- </Alert>
- )}
- <Panel>
- <PanelHeader hasButtons>
- <div>{t('Repositories')}</div>
- <IntegrationReposAddRepository
- integration={integration}
- currentRepositories={itemList}
- onSearchError={setIntegrationReposeErrorStatus}
- onAddRepository={handleAddRepository}
- />
- </PanelHeader>
- <PanelBody>
- {itemList.length === 0 && (
- <EmptyMessage
- icon={<IconCommit />}
- title={t('Sentry is better with commit data')}
- description={t(
- 'Add a repository to begin tracking its commit data. Then, set up release tracking to unlock features like suspect commits, suggested issue owners, and deploy emails.'
- )}
- action={
- <LinkButton href="https://docs.sentry.io/product/releases/" external>
- {t('Learn More')}
- </LinkButton>
- }
- />
- )}
- {itemList.map(repo => (
- <RepositoryRow
- key={repo.id}
- repository={repo}
- orgSlug={organization.slug}
- onRepositoryChange={onRepositoryChange}
- />
- ))}
- </PanelBody>
- </Panel>
- <Pagination pageLinks={itemListPageLinks} />
- </Fragment>
- );
- }
- export default IntegrationRepos;
|