|
|
|
@@ -1,7 +1,7 @@
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import SelectMenu from "./SelectMenu.svelte";
|
|
|
|
|
import { onMount } from "svelte";
|
|
|
|
|
import { GitPullRequest, X, LoaderCircle, ArrowRight, Sparkles } from "@lucide/svelte";
|
|
|
|
|
import { GitBranch, GitPullRequest, LockKeyhole, X, LoaderCircle, ArrowRight, Sparkles } from "@lucide/svelte";
|
|
|
|
|
import { credLoad, pullRequestAiGenerate, createIntegrationReviewRequest, listIntegrationRepositories, listIntegrationRepositoryBranches, listRemotes, listBranches } from "../git";
|
|
|
|
|
import { integrationCredentialKey } from "../integrations";
|
|
|
|
|
import type { AiSettings, GitIntegrationSource, GitIntegrationRepository, IntegrationReviewRequest, StoredCredential } from "../types";
|
|
|
|
@@ -15,6 +15,26 @@
|
|
|
|
|
let dialog: HTMLDialogElement;
|
|
|
|
|
let titleInput: HTMLInputElement;
|
|
|
|
|
let repositories = $state<GitIntegrationRepository[]>([]);
|
|
|
|
|
|
|
|
|
|
/** Repository options grouped by owner, like the clone dialog's list. */
|
|
|
|
|
const repositoryOptions = $derived(repositories.map((repository) => {
|
|
|
|
|
const separator = repository.fullName.lastIndexOf("/");
|
|
|
|
|
return {
|
|
|
|
|
value: repository.id,
|
|
|
|
|
label: separator > 0 ? repository.fullName.slice(separator + 1) : repository.fullName,
|
|
|
|
|
group: separator > 0 ? repository.fullName.slice(0, separator) : source.label,
|
|
|
|
|
};
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
function repositoryById(id: string): GitIntegrationRepository | undefined {
|
|
|
|
|
return repositories.find((repository) => repository.id === id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatUpdatedAt(value: string): string {
|
|
|
|
|
if (!value) return "";
|
|
|
|
|
const date = new Date(value);
|
|
|
|
|
return Number.isNaN(date.getTime()) ? "" : new Intl.DateTimeFormat(de ? "de-DE" : "en-US", { dateStyle: "medium" }).format(date);
|
|
|
|
|
}
|
|
|
|
|
let repositoryId = $state("");
|
|
|
|
|
let sourceBranch = $state("");
|
|
|
|
|
let targetBranch = $state("");
|
|
|
|
@@ -129,7 +149,14 @@
|
|
|
|
|
<div class="body">
|
|
|
|
|
{#if error}<div class="error" role="alert">{error}{#if !repositories.length && !loading}<button type="button" onclick={loadRepositories}>{de ? "Erneut laden" : "Retry"}</button>{/if}</div>{/if}
|
|
|
|
|
<div class="repository-field"><div class="field-heading"><span>Repository</span><small>{loading ? "…" : `${repositories.length} ${de ? "verfügbar" : "available"}`}</small></div>
|
|
|
|
|
<SelectMenu value={repositoryId} options={repositories.map(repository => ({value:repository.id,label:repository.fullName}))} disabled={loading || busy} ariaLabel="Repository" placeholder={loading ? (de ? "Repositories werden geladen …" : "Loading repositories…") : (de ? "Repository auswählen" : "Select repository")} searchable searchPlaceholder={de ? "Repositories durchsuchen …" : "Search repositories…"} emptyText={de ? "Keine passenden Repositories" : "No matching repositories"} onChange={value => repositoryId = value}/>
|
|
|
|
|
<SelectMenu value={repositoryId} options={repositoryOptions} disabled={loading || busy} ariaLabel="Repository" placeholder={loading ? (de ? "Repositories werden geladen …" : "Loading repositories…") : (de ? "Repository auswählen" : "Select repository")} searchable searchPlaceholder={de ? "Repositories durchsuchen …" : "Search repositories…"} emptyText={de ? "Keine passenden Repositories" : "No matching repositories"} showSelectedGroup onChange={value => repositoryId = value}>
|
|
|
|
|
{#snippet optionIcon()}<GitBranch size={14} aria-hidden="true" />{/snippet}
|
|
|
|
|
{#snippet optionMeta(option)}
|
|
|
|
|
{@const repository = repositoryById(option.value)}
|
|
|
|
|
{#if repository?.private}<LockKeyhole size={11} aria-label={de ? "Privat" : "Private"} />{/if}
|
|
|
|
|
{formatUpdatedAt(repository?.updatedAt ?? "")}
|
|
|
|
|
{/snippet}
|
|
|
|
|
</SelectMenu>
|
|
|
|
|
</div>
|
|
|
|
|
{#if !loading && !error && !repositories.length}<p>{de ? "Keine Repositories für diese Integration gefunden." : "No repositories found for this integration."}</p>{/if}
|
|
|
|
|
<div class="branches">
|
|
|
|
|