182 lines
7.0 KiB
Svelte
182 lines
7.0 KiB
Svelte
<!-- [DEF:GitSettingsPage:Component] -->
|
|
<!--
|
|
@SEMANTICS: git, settings, configuration, integration
|
|
@PURPOSE: Manage Git server configurations for dashboard versioning.
|
|
@LAYER: Page
|
|
@RELATION: USES -> gitService
|
|
@RELATION: USES -> Button, Input, Card, PageHeader, Select
|
|
|
|
@INVARIANT: All configurations must be validated via connection test.
|
|
-->
|
|
|
|
<script lang="ts">
|
|
// [SECTION: IMPORTS]
|
|
import { onMount } from 'svelte';
|
|
import { gitService } from '../../../services/gitService';
|
|
import { addToast as toast } from '../../../lib/toasts.js';
|
|
import { t } from '$lib/i18n';
|
|
import { Button, Input, Card, PageHeader, Select } from '$lib/ui';
|
|
// [/SECTION: IMPORTS]
|
|
|
|
// [SECTION: STATE]
|
|
let configs = [];
|
|
let newConfig = {
|
|
name: '',
|
|
provider: 'GITHUB',
|
|
url: 'https://github.com',
|
|
pat: '',
|
|
default_repository: ''
|
|
};
|
|
let testing = false;
|
|
// [/SECTION: STATE]
|
|
|
|
// [DEF:loadConfigs:Function]
|
|
/**
|
|
* @purpose Fetches existing git configurations.
|
|
* @pre Component is mounted.
|
|
* @post configs state is populated.
|
|
*/
|
|
async function loadConfigs() {
|
|
try {
|
|
configs = await gitService.getConfigs();
|
|
} catch (e) {
|
|
toast(e.message, 'error');
|
|
}
|
|
}
|
|
// [/DEF:loadConfigs:Function]
|
|
|
|
onMount(loadConfigs);
|
|
|
|
// [DEF:handleTest:Function]
|
|
/**
|
|
* @purpose Tests connection to a git server with current form data.
|
|
* @pre newConfig contains valid provider, url, and pat.
|
|
* @post testing state is managed; toast shown with result.
|
|
*/
|
|
async function handleTest() {
|
|
testing = true;
|
|
try {
|
|
const result = await gitService.testConnection(newConfig);
|
|
if (result.status === 'success') {
|
|
toast('Connection successful', 'success');
|
|
} else {
|
|
toast(result.message || 'Connection failed', 'error');
|
|
}
|
|
} catch (e) {
|
|
toast('Connection failed', 'error');
|
|
} finally {
|
|
testing = false;
|
|
}
|
|
}
|
|
// [/DEF:handleTest:Function]
|
|
|
|
// [DEF:handleSave:Function]
|
|
/**
|
|
* @purpose Saves a new git configuration.
|
|
* @pre newConfig is valid and tested.
|
|
* @post New config is saved to DB and added to configs list.
|
|
*/
|
|
async function handleSave() {
|
|
try {
|
|
const saved = await gitService.createConfig(newConfig);
|
|
configs = [...configs, saved];
|
|
toast('Configuration saved', 'success');
|
|
newConfig = { name: '', provider: 'GITHUB', url: 'https://github.com', pat: '', default_repository: '' };
|
|
} catch (e) {
|
|
toast(e.message, 'error');
|
|
}
|
|
}
|
|
// [/DEF:handleSave:Function]
|
|
|
|
// [DEF:handleDelete:Function]
|
|
/**
|
|
* @purpose Deletes a git configuration by ID.
|
|
* @param {string} id - Configuration ID.
|
|
* @pre id is valid; user confirmed deletion.
|
|
* @post Configuration is removed from DB and local state.
|
|
*/
|
|
async function handleDelete(id) {
|
|
if (!confirm('Are you sure you want to delete this Git configuration?')) return;
|
|
try {
|
|
await gitService.deleteConfig(id);
|
|
configs = configs.filter(c => c.id !== id);
|
|
toast('Configuration deleted', 'success');
|
|
} catch (e) {
|
|
toast(e.message, 'error');
|
|
}
|
|
}
|
|
// [/DEF:handleDelete:Function]
|
|
</script>
|
|
|
|
<!-- [SECTION: TEMPLATE] -->
|
|
<div class="p-6 max-w-6xl mx-auto">
|
|
<PageHeader title="Git Integration Settings" />
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
<!-- List of Configs -->
|
|
<Card title="Configured Servers">
|
|
{#if configs.length === 0}
|
|
<p class="text-gray-500">No Git servers configured.</p>
|
|
{:else}
|
|
<ul class="divide-y divide-gray-100">
|
|
{#each configs as config}
|
|
<li class="py-4 flex justify-between items-center">
|
|
<div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="font-medium text-gray-900">{config.name}</span>
|
|
<span class="text-xs font-mono bg-gray-50 text-gray-500 px-1.5 py-0.5 rounded">{config.provider}</span>
|
|
</div>
|
|
<div class="text-xs text-gray-400 mt-1">{config.url}</div>
|
|
</div>
|
|
<div class="flex items-center space-x-4">
|
|
<span class="px-2 py-1 text-xs font-medium rounded {config.status === 'CONNECTED' ? 'bg-green-50 text-green-700' : 'bg-red-50 text-red-700'}">
|
|
{config.status}
|
|
</span>
|
|
<button on:click={() => handleDelete(config.id)} class="text-gray-400 hover:text-red-600 transition-colors" title="Delete">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
<path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
{/if}
|
|
</Card>
|
|
|
|
<!-- Add New Config -->
|
|
<Card title="Add Git Server">
|
|
<div class="space-y-6">
|
|
<Input label="Display Name" bind:value={newConfig.name} placeholder="e.g. My GitHub" />
|
|
<Select
|
|
label="Provider"
|
|
bind:value={newConfig.provider}
|
|
options={[
|
|
{ value: 'GITHUB', label: 'GitHub' },
|
|
{ value: 'GITLAB', label: 'GitLab' },
|
|
{ value: 'GITEA', label: 'Gitea' }
|
|
]}
|
|
/>
|
|
<Input label="Server URL" bind:value={newConfig.url} />
|
|
<Input label="Personal Access Token (PAT)" type="password" bind:value={newConfig.pat} />
|
|
<Input label="Default Repository (Optional)" bind:value={newConfig.default_repository} placeholder="org/repo" />
|
|
|
|
<div class="flex gap-3 pt-2">
|
|
<Button variant="secondary" on:click={handleTest} isLoading={testing}>
|
|
Test Connection
|
|
</Button>
|
|
<Button variant="primary" on:click={handleSave}>
|
|
Save Configuration
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
<!-- [/SECTION: TEMPLATE] -->
|
|
|
|
<style>
|
|
/* Styles are handled by Tailwind */
|
|
</style>
|
|
|
|
<!-- [/DEF:GitSettingsPage:Component] --> |