diff --git a/.gitea/workflows/deploy-prod.yaml b/.gitea/workflows/deploy-prod.yaml new file mode 100644 index 0000000..0bb9c60 --- /dev/null +++ b/.gitea/workflows/deploy-prod.yaml @@ -0,0 +1,26 @@ +name: Deploiement API Prod Docker + +on: + push: + branches: + - dev + +jobs: + deploy: + name: Build et DĂ©ploiement + runs-on: ubuntu-latest + + steps: + - name: đŸ“„ RĂ©cupĂ©ration du code source + uses: actions/checkout@v4 + + - name: 🔐 Injection des variables d'environnement + run: | + echo "PGSQL_CONNECTION=${{ secrets.PGSQL_CONNECTION }}" > .env + + - name: 🐳 RedĂ©marrage Docker + run: | + echo "🚀 DĂ©marrage du dĂ©ploiement Docker sur api-prod..." + docker compose down + docker compose up -d --build + echo "✅ DĂ©ploiement terminĂ© !" \ No newline at end of file diff --git a/.gitea/workflows/pr-endpoint-check.yml b/.gitea/workflows/pr-endpoint-check.yml index 1aba34b..9cd7435 100644 --- a/.gitea/workflows/pr-endpoint-check.yml +++ b/.gitea/workflows/pr-endpoint-check.yml @@ -74,7 +74,6 @@ jobs: run: | chmod +x scripts/test-endpoints.sh bash scripts/test-endpoints.sh http://localhost:5038 1000 2>&1 | tee /tmp/webzine_endpoint_output.txt - EXIT_CODE=${PIPESTATUS[0]} FAIL_COUNT=$(grep -cE "^\[ÉCHEC\]" /tmp/webzine_endpoint_output.txt 2>/dev/null || echo 0) SLOW_COUNT=$(grep -cE "^\[LENT\]" /tmp/webzine_endpoint_output.txt 2>/dev/null || echo 0) @@ -137,10 +136,4 @@ jobs: -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg body "$BODY" '{body: $body}')" \ - "$GITEA_SERVER_URL/api/v1/repos/$REPO/issues/$PR_NUMBER/comments" - - - name: Fail job if performance issues detected - if: steps.perf_test.outputs.failed > 0 || steps.perf_test.outputs.slow > 0 - run: | - echo "❌ Job failed due to performance issues" - exit 1 \ No newline at end of file + "$GITEA_SERVER_URL/api/v1/repos/$REPO/issues/$PR_NUMBER/comments" \ No newline at end of file diff --git a/Webzine.WebApplication/Areas/Administration/ViewModels/DashboardViewModel.cs b/Webzine.Business.Contracts/Dto/DashboardDTO.cs similarity index 90% rename from Webzine.WebApplication/Areas/Administration/ViewModels/DashboardViewModel.cs rename to Webzine.Business.Contracts/Dto/DashboardDTO.cs index 106779d..9509c6c 100644 --- a/Webzine.WebApplication/Areas/Administration/ViewModels/DashboardViewModel.cs +++ b/Webzine.Business.Contracts/Dto/DashboardDTO.cs @@ -1,9 +1,9 @@ -namespace Webzine.WebApplication.Areas.Administration.ViewModels; +namespace Webzine.Business.Contracts.Dto; /// -/// ViewModel pour le tableau de bord de l'administration du webzine. +/// DTO pour le tableau de bord de l'administration du webzine. /// -public class DashboardViewModel +public class DashboardDTO { /// /// DĂ©finit le nombre total d'artistes chroniquĂ©s dans le webzine. diff --git a/Webzine.Business.Contracts/Dto/TitreAdminDTO.cs b/Webzine.Business.Contracts/Dto/TitreAdminDTO.cs new file mode 100644 index 0000000..2c2454b --- /dev/null +++ b/Webzine.Business.Contracts/Dto/TitreAdminDTO.cs @@ -0,0 +1,57 @@ +namespace Webzine.Business.Contracts.Dto; + +/// +/// Dto transportant les donnĂ©es mĂ©tier d'un titre saisi en administration. +/// +public class TitreAdminDTO +{ + /// + /// Identifiant du titre (0 lors d'une crĂ©ation). + /// + public int Id { get; set; } + + /// + /// Identifiant de l'artiste sĂ©lectionnĂ©. + /// + public int IdArtiste { get; set; } + + /// + /// LibellĂ© du titre. + /// + public string Libelle { get; set; } = string.Empty; + + /// + /// Nom de l'album. + /// + public string Album { get; set; } = string.Empty; + + /// + /// Texte de la chronique. + /// + public string Chronique { get; set; } = string.Empty; + + /// + /// Date de sortie du titre. + /// + public DateTime DateSortie { get; set; } + + /// + /// DurĂ©e en secondes. + /// + public int Duree { get; set; } + + /// + /// URL de la jaquette. + /// + public string UrlJaquette { get; set; } = string.Empty; + + /// + /// URL d'Ă©coute. + /// + public string? UrlEcoute { get; set; } + + /// + /// Identifiants des styles sĂ©lectionnĂ©s. + /// + public List Styles { get; set; } = new (); +} \ No newline at end of file diff --git a/Webzine.Business.Contracts/IDashboardService.cs b/Webzine.Business.Contracts/IDashboardService.cs new file mode 100644 index 0000000..423880f --- /dev/null +++ b/Webzine.Business.Contracts/IDashboardService.cs @@ -0,0 +1,16 @@ +namespace Webzine.Business.Contracts; + +using Webzine.Business.Contracts.Dto; + +/// +/// Service responsable du calcul des statistiques affichĂ©es sur le tableau de bord d'administration. +/// AgrĂšge les donnĂ©es provenant de plusieurs repositories pour produire un rĂ©sumĂ© cohĂ©rent. +/// +public interface IDashboardService +{ + /// + /// Calcule et retourne toutes les statistiques du tableau de bord en une seule passe. + /// + /// Un contenant les agrĂ©gats calculĂ©s. + DashboardDTO GetDashboardData(); +} \ No newline at end of file diff --git a/Webzine.Business.Contracts/ITitreAdminService.cs b/Webzine.Business.Contracts/ITitreAdminService.cs new file mode 100644 index 0000000..e14a7a7 --- /dev/null +++ b/Webzine.Business.Contracts/ITitreAdminService.cs @@ -0,0 +1,22 @@ +namespace Webzine.Business.Contracts; + +using Webzine.Business.Contracts.Dto; + +/// +/// Service responsable des opĂ©rations d'administration sur les titres. +/// Orchestre la rĂ©solution des dĂ©pendances (artiste, styles) et la persistance. +/// +public interface ITitreAdminService +{ + /// + /// CrĂ©e un nouveau titre Ă  partir des donnĂ©es du formulaire d'administration. + /// + /// Les donnĂ©es saisies dans le formulaire de crĂ©ation. + void CreerTitre(TitreAdminDTO commande); + + /// + /// Met Ă  jour un titre existant Ă  partir des donnĂ©es du formulaire d'administration. + /// + /// Les donnĂ©es saisies dans le formulaire de modification. + void ModifierTitre(TitreAdminDTO commande); +} \ No newline at end of file diff --git a/Webzine.Business/DashboardService.cs b/Webzine.Business/DashboardService.cs new file mode 100644 index 0000000..f1b566d --- /dev/null +++ b/Webzine.Business/DashboardService.cs @@ -0,0 +1,70 @@ +namespace Webzine.Business; + +using Webzine.Business.Contracts; +using Webzine.Business.Contracts.Dto; +using Webzine.Entity; +using Webzine.Repository.Contracts; + +/// +/// ImplĂ©mentation de . +/// Orchestre plusieurs appels aux repositories pour produire les statistiques du tableau de bord. +/// +public class DashboardService : IDashboardService +{ + private readonly IArtisteRepository artisteRepository; + private readonly ITitreRepository titreRepository; + private readonly IStyleRepository styleRepository; + + /// + /// Initializes a new instance of the class. + /// + /// Repository des artistes. + /// Repository des titres. + /// Repository des styles. + public DashboardService( + IArtisteRepository artisteRepository, + ITitreRepository titreRepository, + IStyleRepository styleRepository) + { + this.artisteRepository = artisteRepository; + this.titreRepository = titreRepository; + this.styleRepository = styleRepository; + } + + /// + public DashboardDTO GetDashboardData() + { + IEnumerable titres = this.titreRepository.FindAll(); + + Artiste? artisteLePlusChronique = titres + .GroupBy(t => t.Artiste) + .OrderByDescending(g => g.Count()) + .FirstOrDefault() + ?.Key; + + Artiste? albumLePlusChronique = titres + .GroupBy(t => (t.Artiste, t.Album)) + .GroupBy(g => g.Key.Artiste) + .OrderByDescending(g => g.Count()) + .FirstOrDefault() + ?.Key; + + Titre? musiqueLaPlusJouee = titres + .OrderByDescending(t => t.NbLectures) + .FirstOrDefault(); + + return new DashboardDTO + { + NombreArtistes = this.artisteRepository.Count(), + ArtisteLePlusChronique = artisteLePlusChronique.Nom, + AlbumLePlusChronique = albumLePlusChronique.Nom, + NombreBiographies = this.artisteRepository.Count(a => !string.IsNullOrEmpty(a.Biographie)), + IdMusiqueLaPlusJouee = musiqueLaPlusJouee.IdTitre, + MusiqueLaPlusJouee = musiqueLaPlusJouee.Libelle, + NombreTitres = this.titreRepository.Count(), + NombreGenres = this.styleRepository.Count(), + NombreLectures = titres.Sum(t => t.NbLectures), + NombreLikes = titres.Sum(t => t.NbLikes), + }; + } +} \ No newline at end of file diff --git a/Webzine.Business/TitreAdminService.cs b/Webzine.Business/TitreAdminService.cs new file mode 100644 index 0000000..e23af11 --- /dev/null +++ b/Webzine.Business/TitreAdminService.cs @@ -0,0 +1,124 @@ +namespace Webzine.Business; + +using Microsoft.Extensions.Logging; + +using Webzine.Business.Contracts; +using Webzine.Business.Contracts.Dto; +using Webzine.Entity; +using Webzine.Repository.Contracts; + +/// +/// ImplĂ©mentation de . +/// Orchestre la rĂ©solution des styles, la construction de l'entitĂ© +/// et la dĂ©lĂ©gation au repository. +/// +public class TitreAdminService : ITitreAdminService +{ + private readonly ITitreRepository titreRepository; + private readonly IArtisteRepository artisteRepository; + private readonly IStyleRepository styleRepository; + private readonly ILogger logger; + + /// + /// Initializes a new instance of the class. + /// + /// Repository des titres. + /// Repository des artistes. + /// Repository des styles. + /// Service de journalisation. + public TitreAdminService( + ITitreRepository titreRepository, + IArtisteRepository artisteRepository, + IStyleRepository styleRepository, + ILogger logger) + { + this.titreRepository = titreRepository; + this.artisteRepository = artisteRepository; + this.styleRepository = styleRepository; + this.logger = logger; + } + + /// + public void CreerTitre(TitreAdminDTO commande) + { + this.logger.LogInformation( + "CrĂ©ation d'un nouveau titre '{Libelle}' pour l'artiste ID {IdArtiste}.", + commande.Libelle, + commande.IdArtiste); + + Artiste artiste = this.artisteRepository.Find(commande.IdArtiste); + List