mirror of
https://github.com/grafana/grafana.git
synced 2026-02-03 20:49:50 -05:00
Provisioning: Replace manual GitHub app refresh with real-time watch (#117312)
* Provisioning: Replace manual GitHub app connection refresh with real-time watch - Use useConnectionStatus hook with k8s watch for real-time connection status updates - Remove manual sync/refresh button from connection dropdown - Add creating state feedback to create connection button - Only fetch repos for ready connections to avoid API errors * Use RTK Query loading state instead of manual useState * i18n
This commit is contained in:
parent
37efd9fc8f
commit
23d6e3dba2
5 changed files with 31 additions and 30 deletions
|
|
@ -1,12 +1,10 @@
|
|||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useMemo } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
|
||||
import { t } from '@grafana/i18n';
|
||||
import { Field, RadioButtonGroup, Stack } from '@grafana/ui';
|
||||
|
||||
import { useConnectionList } from '../hooks/useConnectionList';
|
||||
import { isConnectionReady } from '../utils/connectionStatus';
|
||||
import { useConnectionStatus } from '../hooks/useConnectionStatus';
|
||||
|
||||
import { GitHubAppFields } from './GitHubAppFields';
|
||||
import { RepositoryField } from './components/RepositoryField';
|
||||
|
|
@ -55,13 +53,9 @@ export function AuthTypeStep({ onGitHubAppSubmit }: AuthTypeStepProps) {
|
|||
const authTypeOptions = useMemo(() => getAuthTypeOptions(), []);
|
||||
const shouldShowRepositories = githubAuthType !== 'github-app' || githubAppMode !== 'new';
|
||||
|
||||
const shouldFetchConnections = githubAuthType === 'github-app';
|
||||
const [connections] = useConnectionList(shouldFetchConnections ? {} : skipToken);
|
||||
|
||||
const isSelectedConnectionReady = useMemo(() => {
|
||||
const selectedConnection = connections?.find((c) => c.metadata?.name === githubAppConnectionName);
|
||||
return isConnectionReady(selectedConnection?.status);
|
||||
}, [connections, githubAppConnectionName]);
|
||||
const { isConnected: isSelectedConnectionReady } = useConnectionStatus(
|
||||
githubAuthType === 'github-app' ? githubAppConnectionName : undefined
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack direction="column" gap={2}>
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ import { Controller, FormProvider, useForm, useFormContext } from 'react-hook-fo
|
|||
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { isFetchError } from '@grafana/runtime';
|
||||
import { Alert, Combobox, Field, IconButton, RadioButtonGroup, Stack } from '@grafana/ui';
|
||||
import { Alert, Combobox, Field, RadioButtonGroup, Stack } from '@grafana/ui';
|
||||
import { ConnectionSpec } from 'app/api/clients/provisioning/v0alpha1';
|
||||
import { extractErrorMessage } from 'app/api/utils';
|
||||
|
||||
import { ConnectionStatusBadge } from '../Connection/ConnectionStatusBadge';
|
||||
import { GitHubConnectionFields } from '../components/Shared/GitHubConnectionFields';
|
||||
import { useConnectionOptions } from '../hooks/useConnectionOptions';
|
||||
import { useConnectionStatus } from '../hooks/useConnectionStatus';
|
||||
import { useCreateOrUpdateConnection } from '../hooks/useCreateOrUpdateConnection';
|
||||
import { ConnectionFormData } from '../types';
|
||||
import { isConnectionReady } from '../utils/connectionStatus';
|
||||
import { getConnectionFormErrors } from '../utils/getFormErrors';
|
||||
|
||||
import { useStepStatus } from './StepStatusContext';
|
||||
|
|
@ -43,17 +43,17 @@ export function GitHubAppFields({ onGitHubAppSubmit }: GitHubAppFieldsProps) {
|
|||
},
|
||||
});
|
||||
|
||||
const [createConnection] = useCreateOrUpdateConnection();
|
||||
const [createConnection, connectionRequest] = useCreateOrUpdateConnection();
|
||||
const {
|
||||
options: connectionOptions,
|
||||
isLoading,
|
||||
connections: githubConnections,
|
||||
error: connectionListError,
|
||||
refetch: refetchConnections,
|
||||
} = useConnectionOptions(true);
|
||||
|
||||
const [githubAppMode, githubAppConnectionName] = watch(['githubAppMode', 'githubApp.connectionName']);
|
||||
const selectedConnection = githubConnections.find((c) => c.metadata?.name === githubAppConnectionName);
|
||||
const { connection: selectedConnection } = useConnectionStatus(githubAppConnectionName);
|
||||
|
||||
const handleCreateConnection = async () => {
|
||||
// Reset any existing step errors
|
||||
setStepStatusInfo({ status: 'idle' });
|
||||
|
|
@ -191,15 +191,6 @@ export function GitHubAppFields({ onGitHubAppSubmit }: GitHubAppFieldsProps) {
|
|||
<Stack>
|
||||
<Trans i18nKey="provisioning.wizard.github-app-connection-status">Connection status:</Trans>
|
||||
<ConnectionStatusBadge status={selectedConnection.status} />
|
||||
{!isConnectionReady(selectedConnection?.status) && (
|
||||
<IconButton
|
||||
aria-label={t('provisioning.wizard.github-app-sync-connection', 'Sync Connection')}
|
||||
key="syncConnection"
|
||||
name="sync"
|
||||
onClick={refetchConnections}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
@ -211,7 +202,11 @@ export function GitHubAppFields({ onGitHubAppSubmit }: GitHubAppFieldsProps) {
|
|||
|
||||
{githubAppMode === 'new' && (
|
||||
<FormProvider {...credentialForm}>
|
||||
<GitHubConnectionFields required onNewConnectionCreation={handleCreateConnection} />
|
||||
<GitHubConnectionFields
|
||||
required
|
||||
onNewConnectionCreation={handleCreateConnection}
|
||||
isCreating={connectionRequest.isLoading}
|
||||
/>
|
||||
</FormProvider>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@ export interface GitHubConnectionFieldsProps {
|
|||
/** Initial value for whether private key is configured (edit mode) */
|
||||
privateKeyConfigured?: boolean;
|
||||
onNewConnectionCreation?: () => void;
|
||||
/** Whether the connection is currently being created */
|
||||
isCreating?: boolean;
|
||||
}
|
||||
|
||||
export const GitHubConnectionFields = memo<GitHubConnectionFieldsProps>(
|
||||
({ required = true, privateKeyConfigured = false, onNewConnectionCreation }) => {
|
||||
({ required = true, privateKeyConfigured = false, onNewConnectionCreation, isCreating = false }) => {
|
||||
const [isPrivateKeyConfigured, setIsPrivateKeyConfigured] = useState(privateKeyConfigured);
|
||||
const {
|
||||
register,
|
||||
|
|
@ -140,8 +142,12 @@ export const GitHubConnectionFields = memo<GitHubConnectionFieldsProps>(
|
|||
|
||||
{onNewConnectionCreation && (
|
||||
<Stack>
|
||||
<Button onClick={onNewConnectionCreation}>
|
||||
<Trans i18nKey="provisioning.connection-form.create-new-connection-button">Create connection</Trans>
|
||||
<Button onClick={onNewConnectionCreation} disabled={isCreating}>
|
||||
{isCreating ? (
|
||||
<Trans i18nKey="provisioning.connection-form.creating-connection-button">Creating connection...</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="provisioning.connection-form.create-new-connection-button">Create connection</Trans>
|
||||
)}
|
||||
</Button>
|
||||
</Stack>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { t } from '@grafana/i18n';
|
|||
import { useLazyGetConnectionRepositoriesQuery } from 'app/api/clients/provisioning/v0alpha1';
|
||||
|
||||
import { ExternalRepository } from '../types';
|
||||
import { isConnectionReady } from '../utils/connectionStatus';
|
||||
import { formatRepoUrl } from '../utils/git';
|
||||
|
||||
import { useConnectionList } from './useConnectionList';
|
||||
|
|
@ -14,8 +15,13 @@ export function useConnectionOptions(enabled: boolean) {
|
|||
const [connections, connectionsLoading, error, refetch] = useConnectionList(enabled ? {} : skipToken);
|
||||
const githubConnections = useMemo(() => connections?.filter((c) => c.spec?.type === 'github') ?? [], [connections]);
|
||||
|
||||
// Only fetch repos for ready connections
|
||||
const connectionNames = useMemo(
|
||||
() => githubConnections.map((conn) => conn.metadata?.name).filter((name): name is string => Boolean(name)),
|
||||
() =>
|
||||
githubConnections
|
||||
.filter((c) => isConnectionReady(c.status))
|
||||
.map((conn) => conn.metadata?.name)
|
||||
.filter((name): name is string => Boolean(name)),
|
||||
[githubConnections]
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -11939,6 +11939,7 @@
|
|||
"button-save": "Save",
|
||||
"button-saving": "Saving...",
|
||||
"create-new-connection-button": "Create connection",
|
||||
"creating-connection-button": "Creating connection...",
|
||||
"description-app-id": "The ID of your GitHub App",
|
||||
"description-description": "Optional description for this connection",
|
||||
"description-installation-id": "The installation ID of your GitHub App",
|
||||
|
|
@ -12474,7 +12475,6 @@
|
|||
"github-app-no-connections": "No GitHub connections found",
|
||||
"github-app-no-connections-message": "You don't have any existing GitHub app connections. Please select \"Connect to a new app\" to create one.",
|
||||
"github-app-select-connection": "Select a GitHub App connection",
|
||||
"github-app-sync-connection": "Sync Connection",
|
||||
"step-bootstrap": "Choose what to synchronize",
|
||||
"step-configure-repo": "Configure repository",
|
||||
"step-connect": "Connect",
|
||||
|
|
|
|||
Loading…
Reference in a new issue