Files
console/src/lib/components/git/connectRepoModal.svelte
T
Abhi Varde 372b1100f9 fix: prevent duplicate repository connection notifications (#2474)
- Add isConnecting flag to prevent race condition
- Disable submit button during connection process
- Ensure notification appears only once
- Use finally block for proper cleanup

Fixes #2472
2025-11-12 16:29:49 -08:00

139 lines
5.0 KiB
Svelte

<script lang="ts">
import { Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { Icon, Layout } from '@appwrite.io/pink-svelte';
import { installation, repository } from '$lib/stores/vcs';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { IconArrowSmRight } from '@appwrite.io/pink-icons-svelte';
import { Link } from '$lib/elements';
import { NewRepository, Repositories } from '$lib/components/git';
import ConnectGit from '$lib/components/git/connectGit.svelte';
import { addNotification } from '$lib/stores/notifications';
import { Click, trackEvent } from '$lib/actions/analytics';
import RepositoryBehaviour from '$lib/components/git/repositoryBehaviour.svelte';
import { page } from '$app/state';
import { connectGitHub } from '$lib/stores/git';
let {
show = $bindable(false),
product,
callbackState = null,
onlyExisting = false,
connect = async () => {}
}: {
show?: boolean;
product: 'functions' | 'sites';
callbackState?: Record<string, string>;
onlyExisting?: boolean;
connect?: (installationId: string, repositoryId: string) => Promise<void>;
} = $props();
let repositoryBehaviour: 'new' | 'existing' | undefined = $state(
onlyExisting ? 'existing' : undefined
);
let repositoryName = $state('');
let repositoryPrivate = $state(true);
let selectedInstallationId = $state('');
let selectedRepository = $state('');
let installations = $state({ installations: [], total: 0 });
let error = $state('');
onMount(async () => {
installations = await sdk
.forProject(page.params.region, page.params.project)
.vcs.listInstallations();
if (!$installation?.$id && installations?.total) {
$installation = installations.installations[0];
}
selectedInstallationId = installations.total ? installations.installations[0]?.$id : '';
if (installations?.total) {
repositoryBehaviour = 'existing';
}
});
async function connectRepo() {
try {
if (repositoryBehaviour === 'new') {
const repo = await sdk
.forProject(page.params.region, page.params.project)
.vcs.createRepository({
installationId: $installation.$id,
name: repositoryName,
xprivate: repositoryPrivate
});
repository.set(repo);
selectedRepository = repo.id;
}
await connect(selectedInstallationId, selectedRepository);
show = false;
addNotification({
type: 'success',
message: 'Repository connected successfully'
});
} catch (e) {
error = e.message;
}
}
</script>
<Modal
title="Connect repository"
bind:show
hideFooter={!repositoryBehaviour}
onSubmit={connectRepo}
bind:error>
<span slot="description">
Connect your {product === 'functions' ? 'function' : 'site'} to an existing repository or create
a new one.
</span>
{#if !!installations?.total}
<Layout.Stack gap="xl">
{#if !onlyExisting}
<RepositoryBehaviour bind:repositoryBehaviour />
{/if}
{#if repositoryBehaviour === 'new'}
<NewRepository
bind:repositoryName
bind:repositoryPrivate
bind:selectedInstallationId
{installations} />
{:else}
<Repositories
bind:selectedRepository
{product}
action="button"
{callbackState}
connect={(e) => {
trackEvent(Click.ConnectRepositoryClick, {
from: product
});
repository.set(e);
repositoryName = e.name;
selectedRepository = e.id;
}} />
{/if}
</Layout.Stack>
{:else}
<ConnectGit {callbackState} />
{/if}
<svelte:fragment slot="footer">
{#if repositoryBehaviour === 'existing'}
<Layout.Stack>
<Link variant="quiet" href={connectGitHub(callbackState).toString()}>
<Layout.Stack direction="row" gap="xs">
Missing a repository? check your permissions <Icon
icon={IconArrowSmRight} />
</Layout.Stack>
</Link>
</Layout.Stack>
{:else if repositoryBehaviour === 'new'}
<Button text size="s" on:click={() => (show = false)}>Cancel</Button>
<Button size="s" submit disabled={!repositoryName || !$installation?.$id}>
Create
</Button>
{/if}
</svelte:fragment>
</Modal>