feat: jira and synchro
This commit is contained in:
38
src/app/api/jira/logs/route.ts
Normal file
38
src/app/api/jira/logs/route.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/services/database';
|
||||
|
||||
/**
|
||||
* Route GET /api/jira/logs
|
||||
* Récupère les logs de synchronisation Jira
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const limit = parseInt(searchParams.get('limit') || '10');
|
||||
|
||||
const logs = await prisma.syncLog.findMany({
|
||||
where: {
|
||||
source: 'jira'
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc'
|
||||
},
|
||||
take: limit
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
data: logs
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur récupération logs Jira:', error);
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Erreur lors de la récupération des logs',
|
||||
details: error instanceof Error ? error.message : 'Erreur inconnue'
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
96
src/app/api/jira/sync/route.ts
Normal file
96
src/app/api/jira/sync/route.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { createJiraService } from '@/services/jira';
|
||||
|
||||
/**
|
||||
* Route POST /api/jira/sync
|
||||
* Synchronise les tickets Jira avec la base locale
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const jiraService = createJiraService();
|
||||
|
||||
if (!jiraService) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Configuration Jira manquante. Vérifiez les variables d\'environnement JIRA_BASE_URL, JIRA_EMAIL et JIRA_API_TOKEN.' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
console.log('🔄 Début de la synchronisation Jira...');
|
||||
|
||||
// Tester la connexion d'abord
|
||||
const connectionOk = await jiraService.testConnection();
|
||||
if (!connectionOk) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Impossible de se connecter à Jira. Vérifiez la configuration.' },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
// Effectuer la synchronisation
|
||||
const result = await jiraService.syncTasks();
|
||||
|
||||
if (result.success) {
|
||||
return NextResponse.json({
|
||||
message: 'Synchronisation Jira terminée avec succès',
|
||||
data: result
|
||||
});
|
||||
} else {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Synchronisation Jira terminée avec des erreurs',
|
||||
data: result
|
||||
},
|
||||
{ status: 207 } // Multi-Status
|
||||
);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur API sync Jira:', error);
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Erreur interne lors de la synchronisation',
|
||||
details: error instanceof Error ? error.message : 'Erreur inconnue'
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Route GET /api/jira/sync
|
||||
* Teste la connexion Jira
|
||||
*/
|
||||
export async function GET() {
|
||||
try {
|
||||
const jiraService = createJiraService();
|
||||
|
||||
if (!jiraService) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
connected: false,
|
||||
message: 'Configuration Jira manquante'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const connected = await jiraService.testConnection();
|
||||
|
||||
return NextResponse.json({
|
||||
connected,
|
||||
message: connected ? 'Connexion Jira OK' : 'Impossible de se connecter à Jira'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Erreur test connexion Jira:', error);
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
connected: false,
|
||||
message: 'Erreur lors du test de connexion',
|
||||
details: error instanceof Error ? error.message : 'Erreur inconnue'
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { Card } from '@/components/ui/Card';
|
||||
import { DailyCalendar } from '@/components/daily/DailyCalendar';
|
||||
import { DailySection } from '@/components/daily/DailySection';
|
||||
import { dailyClient } from '@/clients/daily-client';
|
||||
import { SimpleHeader } from '@/components/ui/SimpleHeader';
|
||||
import { Header } from '@/components/ui/Header';
|
||||
|
||||
interface DailyPageClientProps {
|
||||
initialDailyView?: DailyView;
|
||||
@@ -151,7 +151,7 @@ export function DailyPageClient({
|
||||
return (
|
||||
<div className="min-h-screen bg-[var(--background)]">
|
||||
{/* Header uniforme */}
|
||||
<SimpleHeader
|
||||
<Header
|
||||
title="TowerControl"
|
||||
subtitle="Daily - Gestion quotidienne"
|
||||
syncing={saving}
|
||||
|
||||
15
src/app/settings/page.tsx
Normal file
15
src/app/settings/page.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { SettingsPageClient } from '@/components/settings/SettingsPageClient';
|
||||
import { getConfig } from '@/lib/config';
|
||||
|
||||
// Force dynamic rendering (no static generation)
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export default async function SettingsPage() {
|
||||
const config = getConfig();
|
||||
|
||||
return (
|
||||
<SettingsPageClient
|
||||
config={config}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { CreateTagData } from '@/clients/tags-client';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { TagForm } from '@/components/forms/TagForm';
|
||||
import { SimpleHeader } from '@/components/ui/SimpleHeader';
|
||||
import { Header } from '@/components/ui/Header';
|
||||
|
||||
interface TagsPageClientProps {
|
||||
initialTags: Tag[];
|
||||
@@ -83,7 +83,7 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
return (
|
||||
<div className="min-h-screen bg-[var(--background)]">
|
||||
{/* Header uniforme */}
|
||||
<SimpleHeader
|
||||
<Header
|
||||
title="TowerControl"
|
||||
subtitle="Tags - Gestion des étiquettes"
|
||||
syncing={loading}
|
||||
|
||||
Reference in New Issue
Block a user