feat(integrations): add create integration review request API and UI
Add a new Tauri command and front-end flow to create PRs/MRs. The backend builds and validates provider-specific payloads and endpoints, sends creation requests, and parses responses into the app's review model. A Svelte dialog and a JS wrapper wire the UI to the command so users can create requests from the Review Center. - Implement provider payload and endpoint logic with unit tests - Expose create_integration_review_request as a Tauri command - Add CreateReviewDialog UI and integrate a creation button in Review Center
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import CreateReviewDialog from "./CreateReviewDialog.svelte";
|
||||
import SelectMenu from "./SelectMenu.svelte";
|
||||
import { cubicOut } from "svelte/easing";
|
||||
import { fly } from "svelte/transition";
|
||||
@@ -32,6 +33,7 @@
|
||||
}
|
||||
|
||||
let { language = "en", integrations, initialQuery = "", initialSourceId = "", localResolutionRequestId = "", localResolutionPhase = "idle", localResolutionMessage = "", loadCredential, onOpenSettings = () => {}, onStartLocalResolution = () => {}, onOpenLocalResolver = () => {}, onContinueLocalResolution = () => {}, onAbortLocalResolution = () => {}, onPushLocalResolution = () => {} }: Props = $props();
|
||||
let createOpen = $state(false);
|
||||
let requests = $state<IntegrationReviewRequest[]>([]);
|
||||
let loading = $state(false);
|
||||
let errors = $state<Array<{ source: string; message: string }>>([]);
|
||||
@@ -398,9 +400,24 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if createOpen && activeSource}
|
||||
<CreateReviewDialog source={activeSource} {de} {loadCredential} onClose={() => createOpen = false} onCreated={(request) => {
|
||||
++loadGeneration;
|
||||
loading = false;
|
||||
requests = [request, ...requests.filter(item => item.id !== request.id)];
|
||||
stateFilter = request.state;
|
||||
query = "";
|
||||
collapsedRepositories = new Set();
|
||||
errors = [];
|
||||
createOpen = false;
|
||||
selectRequest(request, true);
|
||||
}}/>
|
||||
{/if}
|
||||
|
||||
<section class:has-inspector={detailOpen && !!selected} class="review-center" aria-label="Review Center">
|
||||
<header class="review-header">
|
||||
<div class="review-heading"><GitPullRequest size={17} /><h1>Review Center</h1></div>
|
||||
{#if activeSource}<button class="create-review" type="button" disabled={loading} onclick={() => { detailOpen = false; createOpen = true; }}><GitPullRequest size={14}/>{activeSource.provider.startsWith("gitlab") ? (de ? "MR erstellen" : "Create MR") : (de ? "PR erstellen" : "Create PR")}</button>{/if}
|
||||
</header>
|
||||
|
||||
{#if sources.length === 0}
|
||||
@@ -528,6 +545,7 @@
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.create-review{margin-left:auto;display:flex;align-items:center;gap:7px;padding:7px 11px;border:1px solid var(--color-border-subtle);border-radius:7px;background:var(--color-accent);color:white;cursor:pointer}.create-review:disabled{opacity:.5;cursor:default}
|
||||
.review-center{display:flex;min-height:0;flex:1;flex-direction:column;overflow:hidden;color:var(--color-ink);background:var(--app-bg);font-size:12px}.review-center button,.review-center input{font:inherit}.review-header{display:flex;min-height:48px;align-items:center;padding:0 18px;border-bottom:1px solid var(--color-border-subtle);background:var(--color-surface)}.review-heading{display:flex;align-items:center;gap:9px}.review-heading>:global(svg){color:var(--color-accent)}.review-heading h1{margin:0;font-size:16px;font-weight:650}
|
||||
.state-tabs{display:flex;min-height:42px;align-items:stretch;gap:18px;padding:0 18px;border-bottom:1px solid var(--color-border-subtle);background:var(--color-surface)}.state-tabs button{position:relative;display:flex;align-items:center;gap:7px;padding:0 5px;border:0;color:var(--color-ink-muted);background:transparent;font-size:11px}.state-tabs button:hover{color:var(--color-ink)}.state-tabs button.active{color:var(--color-accent)}.state-tabs button.active:after{position:absolute;right:0;bottom:0;left:0;height:2px;background:var(--color-accent);content:""}.state-tabs span,.group-header>span{display:grid;min-width:18px;height:18px;place-items:center;padding:0 5px;border-radius:9px;color:var(--color-ink-muted);background:var(--color-surface-raised);font-size:9.5px}
|
||||
.review-toolbar{display:flex;min-height:48px;align-items:center;gap:10px;padding:7px 18px;border-bottom:1px solid var(--color-border-subtle)}.group-actions{display:flex;align-items:center;gap:2px}.group-actions button,.icon-button{display:inline-flex;height:30px;align-items:center;gap:5px;padding:0 7px;border:1px solid transparent;color:var(--color-ink-muted);background:transparent}.group-actions button:hover,.icon-button:hover{border-color:var(--color-border);color:var(--color-ink);background:var(--color-surface-hover)}.group-actions .icon-button{width:30px;justify-content:center;padding:0;border-color:var(--color-border-subtle);margin-left:3px}.review-search{display:flex;min-width:180px;height:30px;align-items:center;gap:7px;flex:1;padding:0 9px;border:1px solid var(--color-border-input);color:var(--color-ink-faint);background:var(--app-input-bg)}.review-search:focus-within{border-color:var(--color-accent)}.review-search input{width:100%;min-width:0;height:100%;padding:0;border:0;outline:0;color:var(--color-ink);background:transparent}
|
||||
|
||||
Reference in New Issue
Block a user