refactor(ui,docs): Job terimini Test olarak güncelle #2

Merged
wisecolt merged 1 commits from deployment-dev into master 2026-01-18 13:42:59 +00:00
5 changed files with 40 additions and 40 deletions

View File

@@ -21,7 +21,7 @@
- **Korumalı Endpoint'ler**: JWT middleware ile korunan API endpoint'leri - **Korumalı Endpoint'ler**: JWT middleware ile korunan API endpoint'leri
- **Environment Security**: Hassas bilgilerin güvenli .env dosyasında saklanması - **Environment Security**: Hassas bilgilerin güvenli .env dosyasında saklanması
### 📊 Job Yönetim Sistemi ### 🧪 Test Yönetim Sistemi
- **Repository Otomasyonu**: Otomatik git clone/pull işlemleri - **Repository Otomasyonu**: Otomatik git clone/pull işlemleri
- **Zaman Tabanlı Çalıştırma**: Dakika/saat/gün bazında otomatik test çalıştırma - **Zaman Tabanlı Çalıştırma**: Dakika/saat/gün bazında otomatik test çalıştırma
- **Real-time Durum Güncellemesi**: Socket.io ile anlık durum takibi - **Real-time Durum Güncellemesi**: Socket.io ile anlık durum takibi
@@ -38,7 +38,7 @@
### ⚡ Gerçek Zamanlı İletişim ### ⚡ Gerçek Zamanlı İletişim
- **WebSocket Bağlantısı**: Socket.io ile sürekli iletişim - **WebSocket Bağlantısı**: Socket.io ile sürekli iletişim
- **Sayaç Yayınınlaması**: Global sayaç ve işlemler - **Sayaç Yayınınlaması**: Global sayaç ve işlemler
- **Canlı Güncellemeler**: Job durumlarının anlık bildirilmesi - **Canlı Güncellemeler**: Test durumlarının anlık bildirilmesi
- **Ping/Pong**: Bağlantı kontrolü - **Ping/Pong**: Bağlantı kontrolü
### 🎨 Modern Arayüz ### 🎨 Modern Arayüz
@@ -202,24 +202,24 @@ docker compose up -d --build
- **Şifre**: `supersecret` - **Şifre**: `supersecret`
3. Giriş yap butonuna tıklayın 3. Giriş yap butonuna tıklayın
### Job Yönetimi ### Test Yönetimi
#### Yeni Job Oluşturma #### Yeni Test Oluşturma
1. **Dashboard** menüsünden **Jobs** sayfasına gidin 1. **Dashboard** menüsünden **Tests** sayfasına gidin
2. **Yeni Job** butonuna tıklayın 2. **Yeni Test** butonuna tıklayın
3. Job bilgilerini girin: 3. Test bilgilerini girin:
- **Job Adı**: Tanımlayıcı bir isim - **Test Adı**: Tanımlayıcı bir isim
- **Repository URL**: GitHub repository adresi - **Repository URL**: GitHub repository adresi
- **Test Komutu**: Çalıştırılacak komut (örn: `npm test`) - **Test Komutu**: Çalıştırılacak komut (örn: `npm test`)
- **Kontrol Aralığı**: Test sıklığı (dakika/saat/gün) - **Kontrol Aralığı**: Test sıklığı (dakika/saat/gün)
- **Kontrol Değeri**: Sayısal değer - **Kontrol Değeri**: Sayısal değer
4. Kaydet butonuna tıklayın 4. Kaydet butonuna tıklayın
#### Job İzleme #### Test İzleme
- **Jobs Listesi**: Tüm job'ların durumunu gösterir - **Tests Listesi**: Tüm test'lerin durumunu gösterir
- **Real-time Durum**: Socket.io ile anlık güncellemeler - **Real-time Durum**: Socket.io ile anlık güncellemeler
- **Log Akışı**: Test çıktılarını canlı izleme - **Log Akışı**: Test çıktılarını canlı izleme
- **Manuel Çalıştırma**: Job'u anında tetikleme - **Manuel Çalıştırma**: Test'i anında tetikleme
### Deployment Yönetimi ### Deployment Yönetimi
1. **Deployments** sayfasına gidin 1. **Deployments** sayfasına gidin
@@ -250,7 +250,7 @@ docker compose up -d --build
### 📖 API Referansı ### 📖 API Referansı
- **Authentication API'leri**: `/auth/login`, `/auth/me` - **Authentication API'leri**: `/auth/login`, `/auth/me`
- **Job Yönetim API'leri**: CRUD operasyonları, manuel çalıştırma - **Test Yönetim API'leri**: CRUD operasyonları, manuel çalıştırma
- **Deployment API'leri**: `/deployments`, `/deployments/:id`, `/deployments/scan`, `/deployments/branches` - **Deployment API'leri**: `/deployments`, `/deployments/:id`, `/deployments/scan`, `/deployments/branches`
- **Webhook Endpoint**: `/api/deployments/webhook/:token` - **Webhook Endpoint**: `/api/deployments/webhook/:token`
- **WebSocket Olayları**: Real-time iletişim ve durum güncellemeleri - **WebSocket Olayları**: Real-time iletişim ve durum güncellemeleri
@@ -393,12 +393,12 @@ docker compose logs mongo
### Mevcut Durum (v1.0) ### Mevcut Durum (v1.0)
- ✅ Temel CI/CD platformu - ✅ Temel CI/CD platformu
- ✅ Real-time job yönetimi - ✅ Real-time test yönetimi
- ✅ Modern web arayüzü - ✅ Modern web arayüzü
- ✅ Konteyner orkestrasyonu - ✅ Konteyner orkestrasyonu
### Gelecek Planlar ### Gelecek Planlar
- 🔄 **Multi-branch Support**: Farklı branch'ler için job yönetimi - 🔄 **Multi-branch Support**: Farklı branch'ler için test yönetimi
- 🔔 **Bildirim Sistemi**: E-posta ve Slack bildirimleri - 🔔 **Bildirim Sistemi**: E-posta ve Slack bildirimleri
- 📊 **Dashboard İstatistikleri**: Performans ve kullanım metrikleri - 📊 **Dashboard İstatistikleri**: Performans ve kullanım metrikleri
- 🛡️ **Güvenlik İyileştirmeleri**: 2FA ve rate limiting - 🛡️ **Güvenlik İyileştirmeleri**: 2FA ve rate limiting
@@ -406,7 +406,7 @@ docker compose logs mongo
- 📝 **Custom Test Commands**: Esnek test komutu yapılandırması - 📝 **Custom Test Commands**: Esnek test komutu yapılandırması
### E-post Listesi ### E-post Listesi
- 📊 **Dashboard İstatistikleri**: Job performans grafikleri - 📊 **Dashboard İstatistikleri**: Test performans grafikleri
- 🔔 **Bildirim Kanalları**: Slack, Discord, Teams entegrasyonu - 🔔 **Bildirim Kanalları**: Slack, Discord, Teams entegrasyonu
- 🔄 **Pipeline Integration**: GitHub Actions, GitLab CI entegrasyonu - 🔄 **Pipeline Integration**: GitHub Actions, GitLab CI entegrasyonu
- 🏗️ **Template System**: Hazır proje şablonları - 🏗️ **Template System**: Hazır proje şablonları

View File

@@ -22,7 +22,7 @@ export function DashboardLayout() {
const navigation = useMemo( const navigation = useMemo(
() => [ () => [
{ label: "Home", to: "/home", icon: faHouse }, { label: "Home", to: "/home", icon: faHouse },
{ label: "Jobs", to: "/jobs", icon: faFlaskVial }, { label: "Tests", to: "/jobs", icon: faFlaskVial },
{ label: "Deployments", to: "/deployments", icon: faRocket }, { label: "Deployments", to: "/deployments", icon: faRocket },
{ label: "Settings", to: "/settings", icon: faGear } { label: "Settings", to: "/settings", icon: faGear }
], ],

View File

@@ -54,7 +54,7 @@ export function HomePage() {
recentRuns: [], recentRuns: [],
totals: { successRate: 0, totalRuns: 0 } totals: { successRate: 0, totalRuns: 0 }
}); });
setError("Job metrikleri alınamadı"); setError("Test metrikleri alınamadı");
} }
if (deployResult.status === "fulfilled") { if (deployResult.status === "fulfilled") {

View File

@@ -79,7 +79,7 @@ export function JobDetailPage() {
checkUnit: data.job.checkUnit checkUnit: data.job.checkUnit
}); });
}) })
.catch(() => setError("Job bulunamadı")) .catch(() => setError("Test bulunamadı"))
.finally(() => setLoading(false)); .finally(() => setLoading(false));
}, [id]); }, [id]);
@@ -174,14 +174,14 @@ export function JobDetailPage() {
const handleDelete = async () => { const handleDelete = async () => {
if (!job?._id) return; if (!job?._id) return;
const ok = window.confirm("Bu job'ı silmek istediğinize emin misiniz?"); const ok = window.confirm("Bu testi silmek istediğinize emin misiniz?");
if (!ok) return; if (!ok) return;
try { try {
await deleteJob(job._id); await deleteJob(job._id);
toast.success("Job silindi"); toast.success("Test silindi");
navigate("/jobs", { replace: true }); navigate("/jobs", { replace: true });
} catch (err) { } catch (err) {
toast.error("Job silinemedi"); toast.error("Test silinemedi");
} }
}; };
@@ -203,7 +203,7 @@ export function JobDetailPage() {
return; return;
} }
await updateJob(job._id, payload); await updateJob(job._id, payload);
toast.success("Job güncellendi"); toast.success("Test güncellendi");
setJob((prev) => setJob((prev) =>
prev prev
? { ? {
@@ -281,8 +281,8 @@ export function JobDetailPage() {
className="h-10 w-10 transition hover:bg-emerald-100" className="h-10 w-10 transition hover:bg-emerald-100"
onClick={handleEdit} onClick={handleEdit}
disabled={!job} disabled={!job}
title="Job'ı düzenle" title="Testi düzenle"
aria-label="Job'ı düzenle" aria-label="Testi düzenle"
> >
<FontAwesomeIcon icon={faPen} className="h-4 w-4 text-foreground" /> <FontAwesomeIcon icon={faPen} className="h-4 w-4 text-foreground" />
</Button> </Button>
@@ -292,8 +292,8 @@ export function JobDetailPage() {
className="h-10 w-10 transition hover:bg-red-100" className="h-10 w-10 transition hover:bg-red-100"
onClick={handleDelete} onClick={handleDelete}
disabled={!job} disabled={!job}
title="Job'ı sil" title="Testi sil"
aria-label="Job'ı sil" aria-label="Testi sil"
> >
<FontAwesomeIcon icon={faTrash} className="h-4 w-4 text-foreground" /> <FontAwesomeIcon icon={faTrash} className="h-4 w-4 text-foreground" />
</Button> </Button>
@@ -317,7 +317,7 @@ export function JobDetailPage() {
</div> </div>
)} )}
<div className="flex w-full items-center gap-2"> <div className="flex w-full items-center gap-2">
<CardTitle>{job?.name || "Job Detayı"}</CardTitle> <CardTitle>{job?.name || "Test Detayı"}</CardTitle>
<span className="inline-flex items-center gap-2 rounded-full border border-border bg-muted/50 px-3 py-1 text-xs font-semibold text-foreground"> <span className="inline-flex items-center gap-2 rounded-full border border-border bg-muted/50 px-3 py-1 text-xs font-semibold text-foreground">
<FontAwesomeIcon icon={faRepeat} className="h-3.5 w-3.5 text-foreground/80" /> <FontAwesomeIcon icon={faRepeat} className="h-3.5 w-3.5 text-foreground/80" />
{runCount} test {runCount} test
@@ -368,7 +368,7 @@ export function JobDetailPage() {
<div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow"> <div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow">
<div className="flex items-center justify-between border-b border-border px-5 py-4"> <div className="flex items-center justify-between border-b border-border px-5 py-4">
<div className="space-y-1"> <div className="space-y-1">
<div className="text-lg font-semibold text-foreground">Job Güncelle</div> <div className="text-lg font-semibold text-foreground">Test Güncelle</div>
<div className="text-sm text-muted-foreground">Değişiklikler kaydedildiğinde test yeniden tetiklenecek.</div> <div className="text-sm text-muted-foreground">Değişiklikler kaydedildiğinde test yeniden tetiklenecek.</div>
</div> </div>
<Button variant="ghost" size="icon" onClick={() => setEditOpen(false)}> <Button variant="ghost" size="icon" onClick={() => setEditOpen(false)}>
@@ -377,7 +377,7 @@ export function JobDetailPage() {
</div> </div>
<div className="space-y-4 px-5 py-4"> <div className="space-y-4 px-5 py-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="name">Job Name</Label> <Label htmlFor="name">Test Name</Label>
<Input <Input
id="name" id="name"
value={form.name} value={form.name}

View File

@@ -58,7 +58,7 @@ export function JobsPage() {
const data = await fetchJobs(); const data = await fetchJobs();
setJobs(data); setJobs(data);
} catch (err) { } catch (err) {
toast.error("Jobs alınamadı"); toast.error("Testler alınamadı");
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -145,11 +145,11 @@ export function JobsPage() {
j._id === updated._id ? { ...updated, runCount: j.runCount ?? updated.runCount } : j j._id === updated._id ? { ...updated, runCount: j.runCount ?? updated.runCount } : j
) )
); );
toast.success("Job güncellendi"); toast.success("Test güncellendi");
} else { } else {
const created = await createJob(payload); const created = await createJob(payload);
setJobs((prev) => [{ ...created, runCount: created.runCount ?? 0 }, ...prev]); setJobs((prev) => [{ ...created, runCount: created.runCount ?? 0 }, ...prev]);
toast.success("Job oluşturuldu"); toast.success("Test oluşturuldu");
} }
setModalOpen(false); setModalOpen(false);
} catch (err) { } catch (err) {
@@ -163,9 +163,9 @@ export function JobsPage() {
setRunningId(id); setRunningId(id);
try { try {
await runJob(id); await runJob(id);
toast.success("Job çalıştırılıyor"); toast.success("Test çalıştırılıyor");
} catch { } catch {
toast.error("Job çalıştırılamadı"); toast.error("Test çalıştırılamadı");
} finally { } finally {
setRunningId(null); setRunningId(null);
} }
@@ -185,18 +185,18 @@ export function JobsPage() {
<> <>
<div className="flex items-center justify-between gap-4"> <div className="flex items-center justify-between gap-4">
<div> <div>
<h2 className="text-xl font-semibold text-foreground">Jobs</h2> <h2 className="text-xl font-semibold text-foreground">Tests</h2>
</div> </div>
<Button onClick={handleOpenNew} className="gap-2"> <Button onClick={handleOpenNew} className="gap-2">
<FontAwesomeIcon icon={faPlus} className="h-4 w-4" /> <FontAwesomeIcon icon={faPlus} className="h-4 w-4" />
New Job New Test
</Button> </Button>
</div> </div>
<div className="grid gap-4"> <div className="grid gap-4">
{loading && ( {loading && (
<div className="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground"> <div className="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
Jobs yükleniyor... Testler yükleniyor...
</div> </div>
)} )}
{!loading && jobs.length === 0 && ( {!loading && jobs.length === 0 && (
@@ -280,9 +280,9 @@ export function JobsPage() {
<div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow"> <div className="w-full max-w-lg rounded-lg border border-border bg-card card-shadow">
<div className="flex items-center justify-between border-b border-border px-5 py-4"> <div className="flex items-center justify-between border-b border-border px-5 py-4">
<div className="space-y-1"> <div className="space-y-1">
<div className="text-lg font-semibold text-foreground">{isEdit ? "Job Güncelle" : "Yeni Job"}</div> <div className="text-lg font-semibold text-foreground">{isEdit ? "Test Güncelle" : "Yeni Test"}</div>
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
Detayları girin, Jobs listesi canlı olarak güncellenecek. Detayları girin, Tests listesi canlı olarak güncellenecek.
</div> </div>
</div> </div>
<Button variant="ghost" size="icon" onClick={handleClose}> <Button variant="ghost" size="icon" onClick={handleClose}>
@@ -291,7 +291,7 @@ export function JobsPage() {
</div> </div>
<div className="space-y-4 px-5 py-4"> <div className="space-y-4 px-5 py-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="name">Job Name</Label> <Label htmlFor="name">Test Name</Label>
<Input <Input
id="name" id="name"
value={form.name} value={form.name}