Merge remote-tracking branch 'origin/j2/refactor/controler-style-titre' into j2/ajout_repo
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Webzine.Entity;
|
||||
using Webzine.Entity.Fixtures;
|
||||
using Webzine.Repository.Contracts;
|
||||
using Webzine.WebApplication.Areas.Administration.ViewModels.Artiste;
|
||||
|
||||
namespace Webzine.WebApplication.Areas.Administration.Controllers;
|
||||
@@ -10,16 +11,17 @@ public class ArtisteController : Controller
|
||||
{
|
||||
// Injection du logger via le constructeur
|
||||
private readonly ILogger<ArtisteController> _logger;
|
||||
private readonly List<Artiste> _artistes;
|
||||
private readonly IArtisteRepository _artisteRepository;
|
||||
private readonly List<Artiste> _artistes = new List<Artiste>();
|
||||
|
||||
|
||||
public ArtisteController(ILogger<ArtisteController> logger)
|
||||
public ArtisteController(ILogger<ArtisteController> logger,
|
||||
IArtisteRepository artisteRepository)
|
||||
{
|
||||
this._logger = logger;
|
||||
this._logger.LogDebug(1, "initialisation du ArtisteController d'administration");
|
||||
var factory = new DataFactory();
|
||||
|
||||
_artistes = factory.GenerateArtists(10);
|
||||
this._artisteRepository = artisteRepository;
|
||||
this._artistes.AddRange(this._artisteRepository.FindAll());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -30,9 +32,7 @@ public class ArtisteController : Controller
|
||||
public IActionResult Index()
|
||||
{
|
||||
|
||||
var _artistes_ordre = _artistes.OrderBy(t => t.Nom).ToList();
|
||||
|
||||
this._logger.LogInformation("Initialisation du contrôleur TitreController pour l'Administration.");
|
||||
var _artistes_ordre = this._artistes.OrderBy(t => t.Nom).ToList();
|
||||
|
||||
return View(_artistes_ordre);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public class ArtisteController : Controller
|
||||
/// <returns>Redirection.</returns>
|
||||
public IActionResult Edit(int id)
|
||||
{
|
||||
var artiste = _artistes.First(t => t.IdArtiste == id);
|
||||
var artiste = this._artistes.First(t => t.IdArtiste == id);
|
||||
|
||||
var model = new AdminArtisteForm
|
||||
{
|
||||
@@ -79,7 +79,7 @@ public class ArtisteController : Controller
|
||||
/// <returns>Redirection.></returns>
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
var artiste = _artistes.First(t => t.IdArtiste == id);
|
||||
var artiste = this._artistes.First(t => t.IdArtiste == id);
|
||||
var model = new AdminArtisteForm
|
||||
{
|
||||
Id = id,
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers
|
||||
private readonly List<Commentaire> _commentaires;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance de la classe <see cref="CommentaireController"/>.
|
||||
/// Initialise une nouvelle instance du <see cref="CommentaireController"/>.
|
||||
/// Les données sont générées dynamiquement via <see cref="DataFactory"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Webzine.Entity;
|
||||
using Webzine.Entity.Fixtures;
|
||||
using Webzine.Repository.Contracts;
|
||||
using Webzine.WebApplication.Areas.Administration.ViewModels;
|
||||
|
||||
namespace Webzine.WebApplication.Areas.Administration.Controllers;
|
||||
@@ -8,31 +10,24 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers;
|
||||
[Area("Administration")]
|
||||
public class DashboardController : Controller
|
||||
{
|
||||
private readonly ILogger<DashboardController> _logger;
|
||||
private readonly List<Titre> _titres;
|
||||
private readonly List<Style> _styles;
|
||||
private readonly List<Artiste> _artistes;
|
||||
private readonly ILogger<DashboardController> logger;
|
||||
private readonly IStyleRepository styleRepository;
|
||||
private readonly IArtisteRepository artisteRepository;
|
||||
private readonly ITitreRepository titreRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="DashboardController"/>.
|
||||
/// Les données sont générées dynamiquement via <see cref="DataFactory"/>.
|
||||
/// Initialise une nouvelle instance de la classe <see cref="DashboardController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecté.</param>
|
||||
public DashboardController(ILogger<DashboardController> logger)
|
||||
/// <param name="styleRepository">Repository des styles injecté.</param>
|
||||
public DashboardController(ILogger<DashboardController> logger, IStyleRepository styleRepository, IArtisteRepository artisteRepository, ITitreRepository titreRepository)
|
||||
{
|
||||
this._logger = logger;
|
||||
this.logger = logger;
|
||||
this.styleRepository = styleRepository;
|
||||
this.artisteRepository = artisteRepository;
|
||||
this.titreRepository = titreRepository;
|
||||
|
||||
this._logger.LogInformation("Initialisation du contrôleur TitreController.");
|
||||
|
||||
var factory = new DataFactory();
|
||||
|
||||
_artistes = factory.GenerateArtists(10);
|
||||
_styles = factory.GenerateStyles(10);
|
||||
_titres = factory.GenerateTitres(30, _artistes, _styles);
|
||||
|
||||
factory.GenerateCommentaires(50, _titres);
|
||||
|
||||
this._logger.LogInformation("Données fictives générées avec succès.");
|
||||
this.logger.LogInformation("Initialisation du contrôleur TitreController.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -41,42 +36,42 @@ public class DashboardController : Controller
|
||||
/// <returns>La vue Index du tableau de bord.</returns>
|
||||
public IActionResult Index()
|
||||
{
|
||||
var artisteLePlusChronique = _titres
|
||||
var artisteLePlusChronique = this.titreRepository.FindAll()
|
||||
.GroupBy(t => t.Artiste)
|
||||
.OrderByDescending(g => g.Count())
|
||||
.FirstOrDefault();
|
||||
.First();
|
||||
|
||||
var albumLePlusChronique = _titres
|
||||
var albumLePlusChronique = this.titreRepository.FindAll()
|
||||
.GroupBy(t => t.Artiste)
|
||||
.OrderByDescending(g => g.Select(t => t.Album).Distinct().Count())
|
||||
.FirstOrDefault();
|
||||
.First();
|
||||
|
||||
var musiqueLaPlusJouee = _titres
|
||||
var musiqueLaPlusJouee = this.titreRepository.FindAll()
|
||||
.OrderByDescending(t => t.NbLectures)
|
||||
.FirstOrDefault();
|
||||
.First();
|
||||
|
||||
var model = new DashboardViewModel
|
||||
{
|
||||
NombreArtistes = _artistes.Count,
|
||||
NombreArtistes = this.artisteRepository.FindAll().Count(),
|
||||
|
||||
ArtisteLePlusChronique = artisteLePlusChronique?.Key.Nom,
|
||||
ArtisteLePlusChronique = artisteLePlusChronique.Key.Nom,
|
||||
|
||||
AlbumLePlusChronique = albumLePlusChronique?.Key.Nom,
|
||||
AlbumLePlusChronique = albumLePlusChronique.Key.Nom,
|
||||
|
||||
NombreBiographies = _artistes.Count(a => !string.IsNullOrEmpty(a.Biographie)),
|
||||
NombreBiographies = this.artisteRepository.FindAll().Count(a => !string.IsNullOrEmpty(a.Biographie)),
|
||||
|
||||
IdMusiqueLaPlusJouee = musiqueLaPlusJouee?.IdTitre ?? 0,
|
||||
MusiqueLaPlusJouee = musiqueLaPlusJouee?.Libelle,
|
||||
IdMusiqueLaPlusJouee = musiqueLaPlusJouee.IdTitre,
|
||||
MusiqueLaPlusJouee = musiqueLaPlusJouee.Libelle,
|
||||
|
||||
NombreTitres = _titres.Count,
|
||||
NombreTitres = this.titreRepository.Count(),
|
||||
|
||||
NombreGenres = _styles.Count,
|
||||
NombreGenres = this.styleRepository.FindAll().Count(),
|
||||
|
||||
NombreLectures = _titres.Sum(t => t.NbLectures),
|
||||
NombreLectures = this.titreRepository.FindAll().Sum(t => t.NbLectures),
|
||||
|
||||
NombreLikes = _titres.Sum(t => t.NbLikes)
|
||||
NombreLikes = this.titreRepository.FindAll().Sum(t => t.NbLikes),
|
||||
};
|
||||
|
||||
return View(model);
|
||||
return this.View(model);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Webzine.Entity;
|
||||
using Webzine.Entity.Fixtures;
|
||||
using Webzine.Repository.Contracts;
|
||||
using Webzine.WebApplication.Areas.Administration.ViewModels.Style;
|
||||
|
||||
namespace Webzine.WebApplication.Areas.Administration.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Contrôleur pour la gestion des styles dans l'administration du webzine.
|
||||
/// </summary>
|
||||
[Area("Administration")]
|
||||
public class StyleController : Controller
|
||||
{
|
||||
private readonly ILogger<StyleController> _logger;
|
||||
private readonly List<Style> _styles;
|
||||
private readonly ILogger<StyleController> logger;
|
||||
private readonly IStyleRepository styles;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="StyleController"/>.
|
||||
/// Les données sont générées dynamiquement via <see cref="DataFactory"/>.
|
||||
/// Initialise une nouvelle instance de la classe <see cref="StyleController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecté.</param>
|
||||
public StyleController(ILogger<StyleController> logger)
|
||||
/// <param name="styles">Repository des styles injecté.</param>
|
||||
public StyleController(ILogger<StyleController> logger, IStyleRepository styles)
|
||||
{
|
||||
this._logger = logger;
|
||||
this.logger = logger;
|
||||
|
||||
this._logger.LogInformation("Initialisation du contrôleur StyleController.");
|
||||
this.logger.LogInformation("Initialisation du contrôleur StyleController.");
|
||||
|
||||
var factory = new DataFactory();
|
||||
|
||||
_styles = factory.GenerateStyles(10);
|
||||
|
||||
this._logger.LogInformation("Données fictives générées avec succès.");
|
||||
this.styles = styles;
|
||||
}
|
||||
|
||||
// GET: Administration/Styles
|
||||
/// <summary>
|
||||
/// Affiche la liste des styles dans la vue Index.
|
||||
/// </summary>
|
||||
/// <returns>La vue Index avec le ViewModel contenant la liste des styles.</returns>
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Création de données "bouchon" (mock) pour tester l'affichage
|
||||
var listeStyles = this._styles;
|
||||
var listeStyles = this.styles.FindAll().Take(10);
|
||||
|
||||
// Initialisation du ViewModel
|
||||
var viewModel = new StyleViewModel
|
||||
{
|
||||
Styles = listeStyles,
|
||||
};
|
||||
|
||||
return View(viewModel);
|
||||
return this.View(listeStyles);
|
||||
}
|
||||
|
||||
// GET: Administration/Styles/Create
|
||||
/// <summary>
|
||||
/// Affiche la vue de création d'un nouveau style.
|
||||
/// </summary>
|
||||
/// <returns>La vue Create pour ajouter un nouveau style.</returns>
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
return this.View();
|
||||
}
|
||||
|
||||
// GET: Administration/Styles/Delete/5
|
||||
/// <summary>
|
||||
/// Affiche la vue de confirmation de suppression d'un style, en récupérant les détails du style à supprimer à partir de l'identifiant fourni.
|
||||
/// </summary>
|
||||
/// <param name="id">L'identifiant du style à supprimer.</param>
|
||||
/// <returns>La vue de confirmation de suppression avec le ViewModel contenant les détails du style à supprimer, ou une redirection vers l'index si le style n'existe pas.</returns>
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
var style = this._styles
|
||||
.FirstOrDefault(c => c.IdStyle == id);
|
||||
|
||||
if (style == null)
|
||||
{
|
||||
this._logger.LogWarning("Style avec ID {Id} introuvable pour suppression.", id);
|
||||
return RedirectToAction("Index");
|
||||
|
||||
}
|
||||
var style = this.styles.Find(id);
|
||||
|
||||
var vm = new StyleDeleteViewModel
|
||||
{
|
||||
@@ -72,30 +64,26 @@ namespace Webzine.WebApplication.Areas.Administration.Controllers
|
||||
Libelle = style.Libelle,
|
||||
};
|
||||
|
||||
return View(vm);
|
||||
return this.View(vm);
|
||||
}
|
||||
|
||||
// GET: Administration/Styles/Edit/5
|
||||
/// <summary>
|
||||
/// Affiche la vue d'édition d'un style existant, en récupérant les détails du style à éditer à partir de l'identifiant fourni.
|
||||
/// </summary>
|
||||
/// <param name="id">L'identifiant du style à éditer.</param>
|
||||
/// <returns>La vue d'édition avec le ViewModel contenant les détails du style à éditer, ou une redirection vers l'index si le style n'existe pas.</returns>
|
||||
[HttpGet]
|
||||
public IActionResult Edit(int id)
|
||||
{
|
||||
// Recherche du style (simulation avec la liste _styles)
|
||||
var style = _styles.FirstOrDefault(s => s.IdStyle == id);
|
||||
var style = styles.Find(id);
|
||||
|
||||
if (style == null)
|
||||
{
|
||||
this._logger.LogWarning("Style avec ID {Id} introuvable pour style.", id);
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
// Mapping vers le ViewModel
|
||||
var model = new StyleEditViewModel
|
||||
{
|
||||
IdStyle = style.IdStyle,
|
||||
Libelle = style.Libelle
|
||||
Libelle = style.Libelle,
|
||||
};
|
||||
|
||||
return View(model);
|
||||
return this.View(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,39 +2,39 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Webzine.Entity;
|
||||
using Webzine.Entity.Fixtures;
|
||||
using Webzine.Repository.Contracts;
|
||||
using Webzine.WebApplication.Areas.Administration.ViewModels.Titre;
|
||||
|
||||
namespace Webzine.WebApplication.Areas.Administration.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Contrôleur pour la gestion des titres en administration. Ce contrôleur gère les opérations de création, modification, suppression et affichage des titres dans l'interface d'administration du webzine. Les données sont générées dynamiquement à l'aide de la classe <see cref="DataFactory"/> pour simuler un environnement de développement sans accès à une base de données réelle. Chaque action du contrôleur prépare un ViewModel spécifique pour la vue correspondante, permettant ainsi une séparation claire entre la logique métier et la présentation des données.
|
||||
/// </summary>
|
||||
[Area("Administration")]
|
||||
public class TitreController : Controller
|
||||
{
|
||||
private readonly ILogger<TitreController> _logger;
|
||||
private readonly List<Titre> _titres;
|
||||
private readonly List<Style> _styles;
|
||||
private readonly List<Artiste> _artistes;
|
||||
private readonly ILogger<TitreController> logger;
|
||||
private readonly ITitreRepository titreRepository;
|
||||
private readonly IArtisteRepository artisteRepository;
|
||||
private readonly IStyleRepository styleRepository;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="TitreController"/>.
|
||||
/// Les données sont générées dynamiquement via <see cref="DataFactory"/>.
|
||||
/// Initialise une nouvelle instance de la classe <see cref="TitreController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecté.</param>
|
||||
public TitreController(ILogger<TitreController> logger)
|
||||
/// <param name="titreRepository">Repository des titres injecté pour accéder aux données des titres.</param>
|
||||
/// <param name="artisteRepository">Repository des artistes injecté pour accéder aux données des artistes, nécessaires pour les associations avec les titres.</param>
|
||||
/// <param name="styleRepository">Repository des styles injecté pour accéder aux données des styles, nécessaires pour les associations avec les titres.</param>
|
||||
public TitreController(ILogger<TitreController> logger, ITitreRepository titreRepository, IArtisteRepository artisteRepository, IStyleRepository styleRepository)
|
||||
{
|
||||
this._logger = logger;
|
||||
this.logger = logger;
|
||||
|
||||
this._logger.LogInformation("Initialisation du contrôleur TitreController pour l'Administration.");
|
||||
this.logger.LogInformation("Initialisation du contrôleur TitreController pour l'Administration.");
|
||||
|
||||
var factory = new DataFactory();
|
||||
|
||||
_artistes = factory.GenerateArtists(10);
|
||||
_styles = factory.GenerateStyles(10);
|
||||
_titres = factory.GenerateTitres(30, _artistes, _styles);
|
||||
|
||||
factory.GenerateCommentaires(50, _titres);
|
||||
|
||||
this._logger.LogInformation("Données fictives générées avec succès.");
|
||||
this.titreRepository = titreRepository;
|
||||
this.artisteRepository = artisteRepository;
|
||||
this.styleRepository = styleRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,19 +43,19 @@ public class TitreController : Controller
|
||||
/// <returns>La vue Index avec le ViewModel contenant la liste des titres.</returns>
|
||||
public IActionResult Index()
|
||||
{
|
||||
var model = _titres.Select(t => new AdminTitreList
|
||||
var model = this.titreRepository.FindAll().Take(10).Select(t => new AdminTitreList
|
||||
{
|
||||
Id = t.IdTitre,
|
||||
Artiste = t.Artiste?.Nom,
|
||||
Artiste = t.Artiste.Nom,
|
||||
Titre = t.Libelle,
|
||||
Duree = TimeSpan.FromSeconds(t.Duree).ToString(@"mm\:ss"),
|
||||
DateSortie = t.DateSortie,
|
||||
NbLectures = t.NbLectures,
|
||||
NbLikes = t.NbLikes,
|
||||
NbCommentaires = t.Commentaires?.Count ?? 0
|
||||
NbCommentaires = t.Commentaires.Count,
|
||||
}).ToList();
|
||||
|
||||
return View(model);
|
||||
return this.View(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,20 +66,20 @@ public class TitreController : Controller
|
||||
{
|
||||
var model = new AdminTitreForm
|
||||
{
|
||||
Artistes = _artistes.Select(a => new SelectListItem
|
||||
Artistes = this.artisteRepository.FindAll().Select(a => new SelectListItem
|
||||
{
|
||||
Value = a.IdArtiste.ToString(),
|
||||
Text = a.Nom
|
||||
Text = a.Nom,
|
||||
}).ToList(),
|
||||
|
||||
AllStyles = _styles.Select(s => new SelectListItem
|
||||
AllStyles = this.styleRepository.FindAll().Select(s => new SelectListItem
|
||||
{
|
||||
Value = s.IdStyle.ToString(),
|
||||
Text = s.Libelle
|
||||
}).ToList()
|
||||
Text = s.Libelle,
|
||||
}).ToList(),
|
||||
};
|
||||
|
||||
return View(model);
|
||||
return this.View(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -89,7 +89,7 @@ public class TitreController : Controller
|
||||
/// <returns>La vue Edit avec le ViewModel contenant les données du titre à modifier, ainsi que les listes déroulantes pour les artistes et les styles. </returns>
|
||||
public IActionResult Edit(int id)
|
||||
{
|
||||
var titre = _titres.First(t => t.IdTitre == id);
|
||||
var titre = this.titreRepository.Find(id);
|
||||
|
||||
var model = new AdminTitreForm
|
||||
{
|
||||
@@ -106,20 +106,20 @@ public class TitreController : Controller
|
||||
NbLikes = titre.NbLikes,
|
||||
Styles = titre.Styles.Select(s => s.IdStyle).ToList(),
|
||||
|
||||
Artistes = _artistes.Select(a => new SelectListItem
|
||||
Artistes = this.artisteRepository.FindAll().Select(a => new SelectListItem
|
||||
{
|
||||
Value = a.IdArtiste.ToString(),
|
||||
Text = a.Nom
|
||||
Text = a.Nom,
|
||||
}).ToList(),
|
||||
|
||||
AllStyles = _styles.Select(s => new SelectListItem
|
||||
AllStyles = this.styleRepository.FindAll().Select(s => new SelectListItem
|
||||
{
|
||||
Value = s.IdStyle.ToString(),
|
||||
Text = s.Libelle
|
||||
}).ToList()
|
||||
Text = s.Libelle,
|
||||
}).ToList(),
|
||||
};
|
||||
|
||||
return View(model);
|
||||
return this.View(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -129,15 +129,15 @@ public class TitreController : Controller
|
||||
/// <returns>La vue de confirmation de suppression avec le ViewModel contenant les détails du titre à supprimer.</returns>
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
var titre = _titres.First(t => t.IdTitre == id);
|
||||
var titre = this.titreRepository.Find(id);
|
||||
|
||||
var model = new AdminTitreDelete
|
||||
{
|
||||
Id = titre.IdTitre,
|
||||
Titre = titre.Libelle,
|
||||
Artiste = titre.Artiste?.Nom
|
||||
Artiste = titre.Artiste.Nom,
|
||||
};
|
||||
|
||||
return View(model);
|
||||
return this.View(model);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// <copyright file="StyleViewModel.cs" company="Webzine">
|
||||
// Copyright (c) Webzine. Tout droit réservé.
|
||||
// </copyright>
|
||||
|
||||
namespace Webzine.WebApplication.Areas.Administration.ViewModels.Style
|
||||
{
|
||||
/// <summary>
|
||||
/// ViewModel pour afficher la liste des commentaires en administration.
|
||||
/// </summary>
|
||||
public class StyleViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Obtient ou définit la liste des commentaires.
|
||||
/// </summary>
|
||||
public IEnumerable<Entity.Style> Styles { get; set; } = new List<Entity.Style>();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@model Webzine.WebApplication.Areas.Administration.ViewModels.Style.StyleViewModel
|
||||
@model IEnumerable<Webzine.Entity.Style>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Styles";
|
||||
@@ -24,9 +24,9 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Model.Styles != null && Model.Styles.Any())
|
||||
@if ( Model.Any())
|
||||
{
|
||||
@foreach (Webzine.Entity.Style style in Model.Styles)
|
||||
@foreach (Webzine.Entity.Style style in Model)
|
||||
{
|
||||
<tr class="align-middle">
|
||||
<td class="p-2">
|
||||
@@ -36,7 +36,7 @@
|
||||
<a asp-action="Edit" asp-route-id="@style.IdStyle" class="text-primary me-2" title="Éditer">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a asp-action="Delete" asp-route-id="@style.IdStyle" title="Supprimer">
|
||||
<a asp-action="Delete" asp-route-id="@style.IdStyle" title="Supprimer">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Copyright (c) Equipe 1 - . All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using Webzine.Repository.Contracts;
|
||||
|
||||
namespace Webzine.WebApplication.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -30,6 +32,7 @@ namespace Webzine.WebApplication.Controllers
|
||||
{
|
||||
this.logger = logger;
|
||||
this.configuration = configuration;
|
||||
this.titreRepository = titreRepository;
|
||||
this.logger.LogDebug(1, "initialisation du AccueilController");
|
||||
this.titreRepository = titreRepository;
|
||||
}
|
||||
|
||||
@@ -4,26 +4,16 @@ namespace Webzine.WebApplication.Controllers;
|
||||
|
||||
public class ApiController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<ApiController> _logger;
|
||||
private readonly ILogger<ApiController> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="ApiController"/> avec un service de journalisation injecté.
|
||||
/// Initialise une nouvelle instance de la classe <see cref="ApiController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecté pour enregistrer les événements et les erreurs.</param>
|
||||
public ApiController(ILogger<ApiController> logger)
|
||||
{
|
||||
this._logger = logger;
|
||||
this._logger.LogDebug(1, "initialisation du ApiController");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Endpoint de test pour vérifier que l'API fonctionne correctement. Retourne une chaîne de caractères "Hello World !".
|
||||
/// </summary>
|
||||
/// <returns>Une chaîne de caractères "Hello World !".</returns>
|
||||
[HttpGet]
|
||||
public string HelloWorld()
|
||||
{
|
||||
return "Hello World !";
|
||||
this.logger = logger;
|
||||
this.logger.LogDebug(1, "initialisation du ApiController");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -33,7 +23,7 @@ public class ApiController : ControllerBase
|
||||
[HttpGet]
|
||||
public IActionResult Version()
|
||||
{
|
||||
this._logger.LogInformation("Get Version was called");
|
||||
this.logger.LogInformation("Get Version was called");
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Webzine.Entity.Fixtures;
|
||||
|
||||
namespace Webzine.WebApplication.Controllers
|
||||
namespace Webzine.WebApplication.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Webzine.Entity.Fixtures;
|
||||
using Webzine.Repository.Contracts;
|
||||
using Webzine.WebApplication.ViewModels.Artiste;
|
||||
|
||||
public class ArtisteController : Controller
|
||||
{
|
||||
// Injection du logger via le constructeur
|
||||
private readonly ILogger<ArtisteController> _logger;
|
||||
private readonly IArtisteRepository _artisteRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="ArtisteController"/> avec un service de journalisation injecté.
|
||||
/// Initialise une nouvelle instance du <see cref="ArtisteController"/>. avec un service de journalisation injecté.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecté pour enregistrer les événements et les erreurs.</param>
|
||||
public ArtisteController(ILogger<ArtisteController> logger)
|
||||
public ArtisteController(ILogger<ArtisteController> logger,
|
||||
IArtisteRepository artisteRepository)
|
||||
{
|
||||
this._logger = logger;
|
||||
this._logger.LogDebug(1, "initialisation du ArtisteController");
|
||||
this._logger.LogDebug("Initialisation du ArtisteController");
|
||||
this._artisteRepository = artisteRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,12 +31,12 @@ namespace Webzine.WebApplication.Controllers
|
||||
[HttpGet("/artiste/{nom}")]
|
||||
public IActionResult Index(string nom)
|
||||
{
|
||||
this._logger.LogInformation("Tentative d'accès à l'artiste avec le nom : {NomArtiste}", nom);
|
||||
this.logger.LogInformation("Tentative d'accès à l'artiste avec le nom : {NomArtiste}", nom);
|
||||
|
||||
if (string.IsNullOrEmpty(nom))
|
||||
{
|
||||
this._logger.LogWarning("Nom de l'artiste manquant dans la requête.");
|
||||
return RedirectToAction("Index", "Accueil");
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
// On transforme "fatal-bazooka" en "Fatal Bazooka" pour la factory
|
||||
@@ -39,17 +44,28 @@ namespace Webzine.WebApplication.Controllers
|
||||
.ToTitleCase(nom.Replace("-", " "));
|
||||
|
||||
// On appelle la factory pour obtenir l'artiste unique
|
||||
var artiste = ArtisteFactory.SeedArtisteByName(nomPropre);
|
||||
var artiste = this._artisteRepository.FindByName(nomPropre);
|
||||
|
||||
if (artiste == null)
|
||||
{
|
||||
this._logger.LogWarning("Artiste non trouvé pour le nom : {NomArtiste}", nomPropre);
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
var viewModel = new ArtisteDetailsViewModel
|
||||
{
|
||||
IdArtiste = artiste.IdArtiste,
|
||||
Nom = artiste.Nom,
|
||||
Biographie = artiste.Biographie,
|
||||
// On effectue le groupement ici une bonne fois pour toutes
|
||||
AlbumsGroupes = artiste.Titres
|
||||
.OrderBy(t => t.Libelle)
|
||||
.GroupBy(t => t.Album)
|
||||
.OrderBy(g => g.Key),
|
||||
};
|
||||
|
||||
this._logger.LogInformation("Artiste trouvé : {NomArtiste}", nom);
|
||||
|
||||
return View(artiste);
|
||||
return View(viewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,16 @@ namespace Webzine.WebApplication.Controllers
|
||||
public class ContactController : Controller
|
||||
{
|
||||
// Injection du logger via le constructeur
|
||||
private readonly ILogger<ContactController> _logger;
|
||||
private readonly ILogger<ContactController> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="ContactController"/> avec un service de journalisation injecté.
|
||||
/// Initialise une nouvelle instance de la classe <see cref="ContactController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecté pour enregistrer les événements et les erreurs.</param>
|
||||
public ContactController(ILogger<ContactController> logger)
|
||||
{
|
||||
this._logger = logger;
|
||||
this._logger.LogDebug(1, "initialisation du ContactController");
|
||||
this.logger = logger;
|
||||
this.logger.LogDebug(1, "initialisation du ContactController");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,7 +26,7 @@ namespace Webzine.WebApplication.Controllers
|
||||
/// <returns>La vue Index de la page de contact.</returns>
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
return this.View();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class TitreController : Controller
|
||||
private readonly ITitreRepository titreRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise une nouvelle instance du <see cref="TitreController"/>.
|
||||
/// Initialise une nouvelle instance de la classe <see cref="TitreController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Service de journalisation injecte.</param>
|
||||
/// <param name="titreRepository">Repository des titres injecte.</param>
|
||||
@@ -58,7 +58,7 @@ public class TitreController : Controller
|
||||
NbLikes = titre.NbLikes,
|
||||
UrlJaquette = titre.UrlJaquette,
|
||||
UrlEcoute = titre.UrlEcoute,
|
||||
ArtisteNom = titre.Artiste?.Nom,
|
||||
ArtisteNom = titre.Artiste.Nom,
|
||||
Styles = titre.Styles,
|
||||
Commentaires = titre.Commentaires,
|
||||
},
|
||||
@@ -81,7 +81,11 @@ public class TitreController : Controller
|
||||
{
|
||||
this.logger.LogInformation("Recherche des titres pour le style : {Style}.", style);
|
||||
|
||||
<<<<<<< HEAD
|
||||
var titresFiltres = this.titreRepository.SearchByStyle(style).ToList();
|
||||
=======
|
||||
var titresFiltres = this._titreRepository.SearchByStyle(style).ToList();
|
||||
>>>>>>> origin/j2/refactor/controler-style-titre
|
||||
|
||||
var vm = new TitreStyle
|
||||
{
|
||||
@@ -106,7 +110,11 @@ public class TitreController : Controller
|
||||
|
||||
if (titre == null)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
this.logger.LogWarning("Impossible d'ajouter un like. Titre ID {Id} introuvable.", model.IdTitre);
|
||||
=======
|
||||
this._logger.LogWarning("Impossible d'ajouter un like. Titre ID {Id} introuvable.", model.IdTitre);
|
||||
>>>>>>> origin/j2/refactor/controler-style-titre
|
||||
return this.RedirectToAction("Index");
|
||||
}
|
||||
|
||||
@@ -125,7 +133,11 @@ public class TitreController : Controller
|
||||
{
|
||||
if (!this.ModelState.IsValid)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
this.logger.LogWarning("Echec de validation du modele de commentaire pour le titre ID {Id}.", model.IdTitre);
|
||||
=======
|
||||
this._logger.LogWarning("Echec de validation du modele de commentaire pour le titre ID {Id}.", model.IdTitre);
|
||||
>>>>>>> origin/j2/refactor/controler-style-titre
|
||||
return this.RedirectToAction("Details", new { id = model.IdTitre });
|
||||
}
|
||||
|
||||
@@ -133,7 +145,11 @@ public class TitreController : Controller
|
||||
|
||||
if (titre == null)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
this.logger.LogWarning("Impossible d'ajouter le commentaire. Titre ID {Id} introuvable.", model.IdTitre);
|
||||
=======
|
||||
this._logger.LogWarning("Impossible d'ajouter le commentaire. Titre ID {Id} introuvable.", model.IdTitre);
|
||||
>>>>>>> origin/j2/refactor/controler-style-titre
|
||||
return this.RedirectToAction("Index");
|
||||
}
|
||||
|
||||
|
||||
@@ -31,18 +31,49 @@ try
|
||||
builder.Services.AddDbContext<WebzineDbContext>(options =>
|
||||
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
// Ajout d'un seeder pour la base de données
|
||||
// Ajout d'un seeder pour la base de donn<EFBFBD>es
|
||||
builder.Services.AddScoped<DbEntityRepository>();
|
||||
|
||||
// NLog: Setup NLog for Dependency injection
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Host.UseNLog();
|
||||
|
||||
// En fonction de la configuration, utilise soit les repositories basés sur une base de données, soit les repositories basés sur des listes locales.
|
||||
bool useDatabase = builder.Configuration.GetValue<bool>("UseDatabase");
|
||||
if (useDatabase)
|
||||
{
|
||||
builder.Services.AddScoped<ITitreRepository, DbTitreRepository>();
|
||||
builder.Services.AddScoped<IStyleRepository, DbStyleRepository>();
|
||||
builder.Services.AddScoped<IArtisteRepository, DbArtisteRepository>();
|
||||
//builder.Services.AddScoped<ICommentaireRepository, DbCommentaireRepository>();
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Services.AddScoped<ITitreRepository, LocalTitreRepository>();
|
||||
builder.Services.AddScoped<IStyleRepository, LocalStyleRepository>();
|
||||
builder.Services.AddScoped<IArtisteRepository, LocalArtisteRepository>();
|
||||
//builder.Services.AddScoped<ICommentaireRepository, LocalCommentaireRepository>();
|
||||
}
|
||||
|
||||
|
||||
// https://learn.microsoft.com/fr-fr/aspnet/core/performance/response-compression?view=aspnetcore-10.0#configuration
|
||||
// Ajoute le service de compression des réponses HTTP pour réduire la taille des données envoyées au client et améliorer les performances de l'application.
|
||||
builder.Services.AddResponseCompression();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseResponseCompression();
|
||||
|
||||
// Active la possibilite de servir des fichiers statiques presents dans
|
||||
// le dossier wwwroot.
|
||||
app.UseStaticFiles();
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
OnPrepareResponse = ctx =>
|
||||
{
|
||||
// https://learn.microsoft.com/fr-fr/aspnet/core/fundamentals/static-files?view=aspnetcore-10.0#set-http-response-headers
|
||||
ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=31536000");
|
||||
},
|
||||
});
|
||||
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
@@ -71,12 +102,12 @@ try
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// NLog: attrape les exceptions non gerees et les logge.
|
||||
// NLog: attrape les exceptions non gerees et les logger.
|
||||
logger.Error(exception, "Stopped program because of exception");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Assure que NLog flush tous les messages de log avant de fermer l'application.
|
||||
NLog.LogManager.Shutdown();
|
||||
LogManager.Shutdown();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Webzine.WebApplication.ViewModels.Artiste
|
||||
{
|
||||
using Webzine.Entity;
|
||||
/// <summary>
|
||||
/// ViewModel pour afficher les informations d'un artiste et ses titres groupés par album.
|
||||
/// </summary>
|
||||
public class ArtisteDetailsViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Obtient ou définit l'identifiant de l'artiste.
|
||||
/// </summary>
|
||||
public int IdArtiste { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Obtient ou définit le nom de l'artiste.
|
||||
/// </summary>
|
||||
public string Nom { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Obtient ou définit la biographie de l'artiste.
|
||||
/// </summary>
|
||||
public string Biographie { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Obtient ou définit défini la liste des titres de l'artiste groupés par nom d'Album.
|
||||
/// </summary>
|
||||
public IEnumerable<IGrouping<string?, Titre>> AlbumsGroupes { get; set; }
|
||||
= Enumerable.Empty<IGrouping<string?, Titre>>();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@
|
||||
<div class="col-12 col-md-3 text-center mb-3 mb-md-0">
|
||||
<img class="img-fluid img-thumbnail"
|
||||
src="@titre.UrlJaquette"
|
||||
alt="@titre.Libelle" />
|
||||
alt="@titre.Libelle"
|
||||
loading="lazy" />
|
||||
</div>
|
||||
|
||||
<!-- Contenu -->
|
||||
@@ -82,7 +83,7 @@
|
||||
{
|
||||
<div class="col-12 col-md-6 col-lg-4">
|
||||
<div class="card h-100">
|
||||
<img class="card-img-top" src="@titre.UrlJaquette" alt="@titre.Album" />
|
||||
<img class="card-img-top" src="@titre.UrlJaquette" alt="@titre.Album" loading="lazy" />
|
||||
|
||||
<div class="card-body">
|
||||
<a asp-controller="Titre" asp-action="Details" asp-route-id="@titre.IdTitre" class="card-link">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@model Webzine.Entity.Artiste
|
||||
@model Webzine.WebApplication.ViewModels.Artiste.ArtisteDetailsViewModel;
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Artiste";
|
||||
@@ -8,22 +8,20 @@
|
||||
<div class="container">
|
||||
<h1>@Model.Nom</h1>
|
||||
|
||||
<hr class="mb-5" />
|
||||
<hr/>
|
||||
|
||||
<p class="lead">@Model.Biographie</p>
|
||||
|
||||
<h2 class="mt-5 mb-4">Albums</h2>
|
||||
<hr class="mb-5" />
|
||||
<hr/>
|
||||
|
||||
@* On groupe les titres par nom d'album *@
|
||||
@{
|
||||
var albumsGroupes = Model.Titres
|
||||
.OrderBy(t => t.Libelle) // Trie les titres par ordre alphabétique au sein de chaque groupe futur
|
||||
.GroupBy(t => t.Album) // Groupe par nom d'album
|
||||
.OrderBy(g => g.Key); // Trie les albums par ordre alphabétique (la clé du groupe)
|
||||
}
|
||||
|
||||
@foreach (var groupe in albumsGroupes)
|
||||
@if (!Model.AlbumsGroupes.Any())
|
||||
{
|
||||
<p>Cet artiste n'a pas encore de titres répertoriés.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var groupe in Model.AlbumsGroupes)
|
||||
{
|
||||
// On récupère le premier titre du groupe pour afficher l'image de l'album
|
||||
var premierTitre = groupe.First();
|
||||
@@ -32,7 +30,8 @@
|
||||
<div class="col-md-3 mb-3">
|
||||
<img src="@premierTitre.UrlJaquette"
|
||||
class="img-fluid shadow-sm rounded border"
|
||||
alt="Pochette de @groupe.Key" />
|
||||
alt="Pochette de @groupe.Key"
|
||||
loading="lazy" />
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
@@ -70,4 +69,5 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@@ -53,7 +53,7 @@
|
||||
asp-action="Details"
|
||||
asp-route-id="@titre.IdTitre"
|
||||
class="me-3 text-black">
|
||||
<img src="@titre.UrlJaquette" alt="@titre.Libelle" width="70" height="70" class="object-fit-cover" />
|
||||
<img src="@titre.UrlJaquette" alt="@titre.Libelle" width="70" height="70" class="object-fit-cover" loading="lazy"/>
|
||||
</a>
|
||||
|
||||
<div class="justify-content-center d-flex flex-column">
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
<link rel="stylesheet" href="~/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="~/css/all.min.css">
|
||||
<link rel="stylesheet" href="~/css/app.css">
|
||||
|
||||
<script src="~/js/bootstrap.bundle.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<partial name="_Header"/>
|
||||
@@ -28,3 +26,5 @@
|
||||
<partial name="_Footer" />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script src="~/js/bootstrap.bundle.min.js" defer></script>
|
||||
@@ -86,7 +86,9 @@
|
||||
<div class="col-md-4 text-center">
|
||||
<img src="@Model.Details.UrlJaquette"
|
||||
class="img-fluid rounded shadow"
|
||||
alt="Jaquette" />
|
||||
alt="Jaquette"
|
||||
loading="lazy"
|
||||
fetchpriority="high" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a asp-action="Details"
|
||||
asp-route-id="@titre.IdTitre"
|
||||
class="me-3 text-black">
|
||||
<img src="@titre.UrlJaquette" alt="@titre.Libelle" width="70px" height="70px" class="object-fit-cover"/>
|
||||
<img src="@titre.UrlJaquette" alt="@titre.Libelle" width="70px" height="70px" class="object-fit-cover" loading="lazy"/>
|
||||
</a>
|
||||
|
||||
<!-- Infos -->
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\" />
|
||||
<Folder Include="wwwroot\data\" />
|
||||
<Folder Include="wwwroot\lib\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"NombreDerniereChronique": 3,
|
||||
"NombreDeTopTitres": 3
|
||||
},
|
||||
"UseDatabase": true,
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Data Source=Data/webzine.sqlite"
|
||||
},
|
||||
|
||||
6
Webzine.WebApplication/wwwroot/js/all.min.js
vendored
6
Webzine.WebApplication/wwwroot/js/all.min.js
vendored
File diff suppressed because one or more lines are too long
6312
Webzine.WebApplication/wwwroot/js/bootstrap.bundle.js
vendored
6312
Webzine.WebApplication/wwwroot/js/bootstrap.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
7
Webzine.WebApplication/wwwroot/js/bootstrap.bundle.min.js
vendored
Normal file
7
Webzine.WebApplication/wwwroot/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user