From c84ee86ed48c1ba39caecb67857bbfc85084ddda Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Fri, 3 Oct 2025 09:06:24 +0200 Subject: [PATCH] feat: add maxSyncPeriod configuration to TFS settings - Introduced maxSyncPeriod option in TfsConfigForm for user-defined synchronization duration. - Updated TfsService to filter pull requests based on the configured maxSyncPeriod. - Enhanced TfsPullRequest type to include 'rejected' status for better PR management. - Set default maxSyncPeriod to '90d' in user preferences and TFS configuration. --- src/components/settings/tfs/TfsConfigForm.tsx | 35 +++++++++- src/lib/types.ts | 2 +- src/services/core/user-preferences.ts | 1 + src/services/integrations/tfs/tfs.ts | 69 +++++++++++++++---- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/src/components/settings/tfs/TfsConfigForm.tsx b/src/components/settings/tfs/TfsConfigForm.tsx index 559e2d2..5a04cd0 100644 --- a/src/components/settings/tfs/TfsConfigForm.tsx +++ b/src/components/settings/tfs/TfsConfigForm.tsx @@ -15,6 +15,7 @@ export function TfsConfigForm() { personalAccessToken: '', repositories: [], ignoredRepositories: [], + maxSyncPeriod: '90d', }); const [isPending, startTransition] = useTransition(); const [message, setMessage] = useState<{ @@ -94,13 +95,14 @@ export function TfsConfigForm() { startTransition(async () => { setMessage(null); // Réinitialiser la config - const resetConfig = { + const resetConfig: TfsConfig = { enabled: false, organizationUrl: '', projectName: '', personalAccessToken: '', repositories: [], ignoredRepositories: [], + maxSyncPeriod: '90d', }; const result = await saveTfsConfig(resetConfig); @@ -275,6 +277,14 @@ export function TfsConfigForm() { Aucun )} +
+ + Période max de sync: + {' '} + + {config?.maxSyncPeriod || '90d'} + +
)} @@ -475,6 +485,29 @@ export function TfsConfigForm() { )} + +
+ + +

+ Définit la période maximale pour récupérer les Pull Requests. + Les PRs plus anciennes seront ignorées lors de la synchronisation. +

+
)} diff --git a/src/lib/types.ts b/src/lib/types.ts index d073d96..8a2a211 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -221,7 +221,7 @@ export interface TfsPullRequest { pullRequestId: number; title: string; description?: string; - status: 'active' | 'completed' | 'abandoned'; + status: 'active' | 'completed' | 'abandoned' | 'rejected'; createdBy: { displayName: string; uniqueName: string; // email diff --git a/src/services/core/user-preferences.ts b/src/services/core/user-preferences.ts index bf3f476..5561c08 100644 --- a/src/services/core/user-preferences.ts +++ b/src/services/core/user-preferences.ts @@ -53,6 +53,7 @@ const DEFAULT_PREFERENCES: UserPreferences = { personalAccessToken: '', repositories: [], ignoredRepositories: [], + maxSyncPeriod: '90d', // Par défaut 90 jours }, tfsAutoSync: false, tfsSyncInterval: 'daily', diff --git a/src/services/integrations/tfs/tfs.ts b/src/services/integrations/tfs/tfs.ts index 1f88a4e..9870408 100644 --- a/src/services/integrations/tfs/tfs.ts +++ b/src/services/integrations/tfs/tfs.ts @@ -16,6 +16,7 @@ export interface TfsConfig { personalAccessToken?: string; repositories?: string[]; // Liste des repos à surveiller ignoredRepositories?: string[]; // Liste des repos à ignorer + maxSyncPeriod?: '7d' | '30d' | '90d' | '180d' | '1y' | '2y' | '3y'; // Période maximale de synchronisation } export interface TfsSyncAction { @@ -375,10 +376,10 @@ export class TfsService { /** * Filtre les PRs par statut pertinent - * - Garde toutes les PRs actives créées dans les 90 derniers jours + * - Garde toutes les PRs actives créées dans la période configurée * - Garde les PRs completed récentes (moins de 30 jours) - * - Exclut les PRs abandoned - * - Exclut les PRs trop anciennes + * - Exclut les PRs abandoned et rejected + * - Exclut les PRs trop anciennes selon la configuration * - Exclut les PRs automatiques (Renovate, etc.) */ private filterByRelevantStatus( @@ -386,6 +387,11 @@ export class TfsService { ): TfsPullRequest[] { const now = new Date(); const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); + + // Calculer la période maximale selon la configuration + const maxSyncPeriod = this.config.maxSyncPeriod || '90d'; + const maxSyncPeriodMs = this.getMaxSyncPeriodMs(maxSyncPeriod); + const maxSyncDate = new Date(now.getTime() - maxSyncPeriodMs); return pullRequests.filter((pr) => { // Exclure les PRs automatiques (Renovate, Dependabot, etc.) @@ -396,20 +402,20 @@ export class TfsService { return false; } - // Filtrer d'abord par âge - exclure les PRs trop anciennes - // const createdDate = parseDate(pr.creationDate); - // if (createdDate < ninetyDaysAgo) { - // console.log( - // `🗺 PR ${pr.pullRequestId} (${pr.title}): Trop ancienne (${formatDateForDisplay(createdDate)}) - EXCLUE` - // ); - // return false; - // } + // Filtrer par âge selon la configuration + const createdDate = parseDate(pr.creationDate); + if (createdDate < maxSyncDate) { + console.log( + `🗺 PR ${pr.pullRequestId} (${pr.title}): Trop ancienne (${formatDateForDisplay(createdDate)}, limite: ${maxSyncPeriod}) - EXCLUE` + ); + return false; + } switch (pr.status.toLowerCase()) { case 'active': - // PRs actives récentes + // PRs actives dans la période configurée console.log( - `✅ PR ${pr.pullRequestId} (${pr.title}): Active récente - INCLUSE` + `✅ PR ${pr.pullRequestId} (${pr.title}): Active récente (${maxSyncPeriod}) - INCLUSE` ); return true; @@ -426,15 +432,52 @@ export class TfsService { case 'abandoned': // PRs abandonnées ne sont pas pertinentes + console.log( + `❌ PR ${pr.pullRequestId} (${pr.title}): Abandonnée - EXCLUE` + ); + return false; + + case 'rejected': + // PRs rejetées ne sont pas pertinentes + console.log( + `❌ PR ${pr.pullRequestId} (${pr.title}): Rejetée - EXCLUE` + ); return false; default: // Statut inconnu, on l'inclut par précaution + console.log( + `⚠️ PR ${pr.pullRequestId} (${pr.title}): Statut inconnu "${pr.status}" - INCLUSE par précaution` + ); return true; } }); } + /** + * Convertit une période de synchronisation en millisecondes + */ + private getMaxSyncPeriodMs(period: string): number { + switch (period) { + case '7d': + return 7 * 24 * 60 * 60 * 1000; // 7 jours + case '30d': + return 30 * 24 * 60 * 60 * 1000; // 30 jours + case '90d': + return 90 * 24 * 60 * 60 * 1000; // 90 jours + case '180d': + return 180 * 24 * 60 * 60 * 1000; // 180 jours + case '1y': + return 365 * 24 * 60 * 60 * 1000; // 1 an + case '2y': + return 2 * 365 * 24 * 60 * 60 * 1000; // 2 ans + case '3y': + return 3 * 365 * 24 * 60 * 60 * 1000; // 3 ans + default: + return 90 * 24 * 60 * 60 * 1000; // Par défaut 90 jours + } + } + /** * Détermine si une PR est automatique (bot, renovate, dependabot, etc.) */