Merge branch 'dev' into j1/feat/admin_page_commentaire

# Conflicts:
#	Webzine.Entity/Style.cs
#	Webzine.Entity/Titre.cs
#	Webzine.Repository/LocalEntityRepository.cs
#	Webzine.WebApplication/Program.cs
This commit is contained in:
mirage
2026-03-05 16:35:30 +01:00
32 changed files with 999 additions and 242 deletions

View File

@@ -1,6 +1,14 @@
**Loïc Masi** :
04/03 :
- Création de 'AccueilController'
- Création de la fonction Index() -> afficher l'accueil du webzine
- Ajout de la vue 'Views/Accueil/Index.cshtml'
- Mise en place d'un Header dans 'Views/Shared/_Header.cshtml'
- Mise en place de la Sidebar dans 'Views/Shared/_Sidebar.cshtml'
- Mise en place de la Sidebar dans 'Views/Shared/_Sidebar.cshtml'
05/03 :
- Mise en place de fausse données dans 'Webzine.Repository' à l'aide de Faker
- Ajout du ViewModel pour afficher les informations nécessaire sur la page d'accueil
- Adaptation de quelques éléments sur la page (Bootstrap)
- Mise en place du parametrage du nombre d'elements a afficher sur la page dans appsettings

View File

@@ -0,0 +1,54 @@
using Bogus;
namespace Webzine.Entity.Fixtures
{
/// <summary>
/// Factory pour générer des artistes avec des titres associés, à l'aide de la bibliothèque Bogus.
///
/// </summary>
public class ArtisteFactory
{
/// <summary>
/// Récupère un artiste par son nom, en générant des données fictives pour ses titres associés.
/// </summary>
/// <param name="nom"></param>
/// <returns></returns>
public static Artiste SeedArtisteByName(string nom)
{
// On définit nos albums "bouchonnés"
var albumsData = new[]
{
new { Nom = "Bohemian Rhapsody", Image = "https://upload.wikimedia.org/wikipedia/en/9/9f/Bohemian_Rhapsody.png" },
new { Nom = "Born This Way", Image = "https://static.wikia.nocookie.net/ladygaga/images/2/2d/BornThisWay-DeluxeEdition.jpg/revision/latest/scale-to-width-down/3500?cb=20111120030308" }
};
var faker = new Bogus.Faker("fr");
var tousLesTitres = new List<Titre>();
// Pour chaque album, on génère un paquet de titres
foreach (var album in albumsData)
{
var nombreDeTitres = faker.Random.Number(3, 6);
var titresDeLalbum = new Faker<Titre>("fr")
.RuleFor(t => t.IdTitre, f => f.IndexFaker + 1 + tousLesTitres.Count)
.RuleFor(t => t.UrlJaquette, _ => album.Image)
.RuleFor(t => t.Album, _ => album.Nom)
.RuleFor(t => t.Duree, f => f.Random.Number(90, 180))
.RuleFor(t => t.Libelle, f => f.Music.Genre() + " - " + f.Commerce.ProductName())
.Generate(nombreDeTitres);
tousLesTitres.AddRange(titresDeLalbum);
}
// On crée l'artiste final
var artisteFaker = new Faker<Artiste>("fr")
.RuleFor(a => a.IdArtiste, f => f.IndexFaker + 1)
.RuleFor(a => a.Nom, _ => nom)
.RuleFor(a => a.Biographie, f => f.Lorem.Paragraphs(2))
.RuleFor(a => a.Titres, _ => tousLesTitres);
return artisteFaker.Generate();
}
}
}

View File

@@ -18,7 +18,6 @@ namespace Webzine.Entity
[Display(Name = "Libellé")]
public string Libelle { get; set; }
public List<Titre> Titres { get; set; } = new List<Titre>();
}
}

View File

@@ -63,7 +63,6 @@ namespace Webzine.Entity
public List<Commentaire> Commentaires { get; set; }
public List<Style> Styles { get; set; } = new List<Style>();
}
}
}

View File

@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bogus" Version="35.6.5" />
<PackageReference Include="Faker.Net" Version="2.0.163" />
<PackageReference Include="NLog" Version="6.1.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">

View File

@@ -1,12 +0,0 @@
using Webzine.Entity;
namespace Webzine.Repository.Contracts;
public interface ILocalEntityRepository
{
List<Artiste> Artistes { get; set; }
List<Style> Styles { get; set; }
List<Titre> Titres { get; set; }
List<Commentaire> Commentaires { get; set; }
void Seed();
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using Faker;
using Webzine.Entity;
namespace Webzine.Repository.Fake
{
public static class FakeDataFactory
{
//https://cdn-images.dzcdn.net/images/cover/311bba0fc112d15f72c8b5a65f0456c1/1900x1900-000000-80-0-0.jpg",
public static List<Artiste> GetArtistes(int count = 10)
{
var artistes = new List<Artiste>();
for (int i = 1; i <= count; i++)
{
artistes.Add(new Artiste
{
IdArtiste = i,
Nom = Name.FullName(),
Biographie = Lorem.Paragraph(),
Titres = new List<Titre>()
});
}
return artistes;
}
public static List<Titre> GetTitres(int count = 40)
{
var artistes = GetArtistes();
var titres = new List<Titre>();
for (int i = 1; i <= count; i++)
{
var artiste = artistes[RandomNumber.Next(0, artistes.Count - 1)];
var titre = new Titre
{
IdTitre = i,
IdArtiste = artiste.IdArtiste,
Artiste = artiste,
Libelle = Lorem.Sentence(3),
Chronique = Lorem.Paragraph(),
DateCreation = DateTime.Now.AddDays(-RandomNumber.Next(1, 100)),
DateSortie = DateTime.Now.AddYears(-RandomNumber.Next(1, 20)),
Duree = RandomNumber.Next(120, 420),
UrlJaquette = "https://picsum.photos/300",
UrlEcoute = Internet.Url(),
NbLectures = RandomNumber.Next(0, 500),
NbLikes = RandomNumber.Next(0, 200),
Album = Lorem.Sentence(2),
Commentaires = new List<Commentaire>()
};
titres.Add(titre);
artiste.Titres.Add(titre);
}
return titres;
}
}
}

View File

@@ -1,11 +1,7 @@
using Webzine.Repository.Contracts;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
namespace Webzine.Repository;
using Entity;
using Entity.Fixtures;
public class LocalEntityRepository
{
private readonly ILogger<LocalEntityRepository> _logger;
@@ -14,6 +10,4 @@ public class LocalEntityRepository
this._logger = logger;
this._logger.LogDebug(1, "NLog injected into LocalEntityRepository");
}
}

View File

@@ -24,13 +24,6 @@
<ItemGroup>
<ProjectReference Include="..\Webzine.Entity\Webzine.Entity.csproj" />
<ProjectReference Include="..\Webzine.Repository.Contracts\Webzine.Repository.Contracts.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Testing.Platform">
<HintPath>..\..\..\..\..\..\..\.nuget\packages\microsoft.testing.platform\2.0.1\lib\net9.0\Microsoft.Testing.Platform.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@@ -1,83 +1,46 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Webzine.Repository.Fake;
using Webzine.WebApplication.ViewModels.Accueil;
namespace Webzine.WebApplication.Controllers
{
public class AccueilController : Controller
public class AccueilController : Microsoft.AspNetCore.Mvc.Controller
{
// Injection du logger via le constructeur
private readonly ILogger<AccueilController> _logger;
private readonly IConfiguration _configuration;
public AccueilController(ILogger<AccueilController> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}
// GET: AccueilController
public ActionResult Index()
{
return View();
}
_logger.LogInformation("Arrivée sur la page d'accueil");
// GET: AccueilController/Details/5
public ActionResult Details(int id)
{
return View();
}
var derniereChronique = _configuration.GetValue<int>("Webzine:NombreDerniereChronique");
var topTitres = _configuration.GetValue<int>("Webzine:NombreDeTopTitres");
var titres = FakeDataFactory.GetTitres();
// GET: AccueilController/Create
public ActionResult Create()
{
return View();
}
// POST: AccueilController/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(IFormCollection collection)
{
try
var vm = new AccueilIndexViewModel
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
DerniersTitres = titres
.OrderByDescending(t => t.DateCreation)
.Take(derniereChronique)
.ToList(),
// GET: AccueilController/Edit/5
public ActionResult Edit(int id)
{
return View();
}
TopTitres = titres
.OrderByDescending(t => t.NbLikes)
.Take(topTitres)
.ToList()
};
// POST: AccueilController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: AccueilController/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: AccueilController/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
return View(vm);
}
}
}

View File

@@ -0,0 +1,54 @@
using Microsoft.AspNetCore.Mvc;
using Webzine.Entity.Fixtures;
using Webzine.WebApplication.ViewModels;
namespace Webzine.WebApplication.Controllers
{
public class ArtisteController : Controller
{
// Injection du logger via le constructeur
private readonly ILogger<ArtisteController> _logger;
public ArtisteController(ILogger<ArtisteController> logger)
{
_logger = logger;
}
/// <summary>
/// Prend en paramètre le nom de l'artiste (ex: "fatal-bazooka"), utilise la factory pour trouver l'artiste correspondant, et affiche sa page dédiée.
/// </summary>
/// <param name="nom"></param>
/// <returns></returns>
[HttpGet("/artiste/{nom}")]
public IActionResult Index(string nom)
{
_logger.LogInformation("Tentative d'accès à l'artiste avec le nom : {NomArtiste}", nom);
if (string.IsNullOrEmpty(nom)) return RedirectToAction("Index", "Accueil");
// On transforme "fatal-bazooka" en "Fatal Bazooka" pour la factory
string nomPropre = System.Globalization.CultureInfo.CurrentCulture.TextInfo
.ToTitleCase(nom.Replace("-", " "));
// On appelle la factory pour obtenir l'artiste unique
var artiste = ArtisteFactory.SeedArtisteByName(nomPropre);
if (artiste == null)
{
_logger.LogWarning("Artiste non trouvé pour le nom : {NomArtiste}", nomPropre);
return NotFound();
}
_logger.LogInformation("Artiste trouvé : {NomArtiste}", nom);
// On remplit le ViewModel
var viewModel = new ArtisteModel
{
Artiste = artiste,
Titres = artiste.Titres
};
return View(viewModel);
}
}
}

View File

@@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Mvc;
namespace Webzine.WebApplication.Controllers
{
/// <summary>
/// Controller pour la page contact.
/// </summary>
public class ContactController : Controller
{
public IActionResult Index()
{
return View();
}
}
}

View File

@@ -0,0 +1,181 @@
using Microsoft.AspNetCore.Mvc;
using Webzine.Entity;
using Webzine.Entity.Fixtures;
using Webzine.WebApplication.ViewsModels.Titre;
namespace Webzine.WebApplication.Controllers;
/// <summary>
/// Contrôleur responsable de la gestion des titres musicaux :
/// affichage des détails, filtrage par style,
/// ajout de likes et commentaires.
/// </summary>
[Route("titre")]
public class TitreController : Microsoft.AspNetCore.Mvc.Controller
{
private readonly ILogger<TitreController> _logger;
private readonly List<Titre> _titres;
private readonly List<Style> _styles;
private readonly List<Artiste> _artistes;
/// <summary>
/// Initialise une nouvelle instance du <see cref="TitreController"/>.
/// Les données sont générées dynamiquement via <see cref="DataFactory"/>.
/// </summary>
/// <param name="logger">Service de journalisation injecté.</param>
public TitreController(ILogger<TitreController> logger)
{
_logger = logger;
_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);
_logger.LogInformation("Données fictives générées avec succès.");
}
/// <summary>
/// Affiche le détail d'un titre spécifique.
/// </summary>
/// <param name="id">Identifiant du titre.</param>
/// <returns>Vue des détails ou 404 si introuvable.</returns>
[HttpGet("{id}")]
public IActionResult Details(int id)
{
_logger.LogInformation("Demande d'affichage du détail pour le titre ID {Id}.", id);
var titre = _titres.FirstOrDefault(t => t.IdTitre == id);
if (titre == null)
{
_logger.LogWarning("Titre avec ID {Id} introuvable.", id);
return NotFound();
}
var vm = new TitreDetail
{
Details = new TitreContent
{
IdTitre = titre.IdTitre,
Libelle = titre.Libelle,
Chronique = titre.Chronique,
DateSortie = titre.DateSortie,
NbLikes = titre.NbLikes,
UrlJaquette = titre.UrlJaquette,
UrlEcoute = titre.UrlEcoute,
ArtisteNom = titre.Artiste?.Nom,
Styles = titre.Styles,
Commentaires = titre.Commentaires
},
CommentForm = new TitreComment
{
IdTitre = titre.IdTitre
}
};
return View(vm);
}
/// <summary>
/// Affiche les titres correspondant à un style musical donné.
/// </summary>
/// <param name="style">Nom du style musical.</param>
/// <returns>Vue contenant la liste filtrée.</returns>
[HttpGet("style/{style}")]
public IActionResult Style(string style)
{
_logger.LogInformation("Recherche des titres pour le style : {Style}.", style);
var titresFiltres = _titres
.Where(t => t.Styles.Any(s => s.Libelle.Equals(style)))
.OrderBy(t => t.Libelle)
.ToList();
if (!titresFiltres.Any())
{
_logger.LogWarning("Aucun titre trouvé pour le style : {Style}.", style);
return NotFound();
}
var vm = new TitreStyle
{
StyleName = style,
Titres = titresFiltres.Select(t => new TitreStyleItem
{
IdTitre = t.IdTitre,
Libelle = t.Libelle,
ArtisteNom = t.Artiste?.Nom,
UrlJaquette = t.UrlJaquette,
Duree = t.Duree
}).ToList()
};
return View(vm);
}
/// <summary>
/// Ajoute un like à un titre.
/// </summary>
/// <param name="model">Modèle contenant l'identifiant du titre.</param>
/// <returns>Redirection vers la page détail.</returns>
[HttpPost("like")]
public IActionResult Like(TitreLike model)
{
_logger.LogInformation("Ajout d'un like pour le titre ID {Id}.", model.IdTitre);
var titre = _titres.FirstOrDefault(t => t.IdTitre == model.IdTitre);
if (titre == null)
{
_logger.LogWarning("Impossible d'ajouter un like. Titre ID {Id} introuvable.", model.IdTitre);
return NotFound();
}
titre.NbLikes++;
return RedirectToAction("Details", new { id = model.IdTitre });
}
/// <summary>
/// Ajoute un commentaire à un titre.
/// </summary>
/// <param name="model">Données du commentaire.</param>
/// <returns>Redirection vers la page détail.</returns>
[HttpPost("comment")]
public IActionResult Comment(TitreComment model)
{
if (!ModelState.IsValid)
{
_logger.LogWarning("Échec de validation du modèle de commentaire pour le titre ID {Id}.", model.IdTitre);
return RedirectToAction("Details", new { id = model.IdTitre });
}
var titre = _titres.FirstOrDefault(t => t.IdTitre == model.IdTitre);
if (titre == null)
{
_logger.LogWarning("Impossible d'ajouter le commentaire. Titre ID {Id} introuvable.", model.IdTitre);
return NotFound();
}
var commentaire = new Commentaire
{
Auteur = model.Auteur,
Contenu = model.Contenu,
DateCreation = DateTime.Now,
IdTitre = model.IdTitre
};
titre.Commentaires.Add(commentaire);
_logger.LogInformation("Commentaire ajouté avec succès au titre ID {Id}.", model.IdTitre);
return RedirectToAction("Details", new { id = model.IdTitre });
}
}

View File

@@ -1,7 +1,5 @@
using NLog;
using NLog.Web;
using Webzine.Repository;
using Webzine.Repository.Contracts;
// Initiation du logger NLog pour la classe courante afin de pouvoir l'utiliser pour logger des messages d'information, d'erreur, etc avant la construction de l'application.
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
@@ -23,9 +21,6 @@ try
builder.Logging.ClearProviders();
builder.Host.UseNLog();
// Register LocalEntityRepository as a singleton
//builder.Services.AddSingleton<ILocalEntityRepository, LocalEntityRepository>();
var app = builder.Build();
// Active la possibilité de servir des fichiers statiques présents dans
@@ -47,9 +42,6 @@ try
name: "default",
pattern: "{controller=Accueil}/{action=Index}/{id?}");
// Permet de remplir les listes d'entités du repository avec des donn<6E>es de test.
app.Run();
}
catch (Exception exception)

View File

@@ -0,0 +1,10 @@
using Webzine.Entity;
namespace Webzine.WebApplication.ViewModels.Accueil
{
public class AccueilIndexViewModel
{
public IEnumerable<Titre> DerniersTitres { get; set; } = [];
public IEnumerable<Titre> TopTitres { get; set; } = [];
}
}

View File

@@ -0,0 +1,17 @@
using Webzine.Entity;
namespace Webzine.WebApplication.ViewModels
{
public class ArtisteModel
{
/// <summary>
/// Artiste dont on affiche les détails.
/// </summary>
public Artiste Artiste { get; set; }
/// <summary>
/// Liste des titres de l'artiste.
/// </summary>
public List<Titre> Titres { get; set; }
}
}

View File

@@ -1,118 +1,75 @@
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@model Webzine.WebApplication.ViewModels.Accueil.AccueilIndexViewModel
@{
ViewData["Title"] = "Accueil";
}
<h1>Derniers titres chroniqués</h1>
<div class="container">
@* TEMPLATE *@
@* <div class="container">
<div class="container bg-light row p-3 mt-3">
<div class="col-auto">
<img class="img-thumbnail"
src="data:image/png;base64,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" alt="Alternate Text" />
src="" />
</div>
<div class="col">
<a class="text-primary text-decoration-none fw-light h4">Justice - D.A.N.C.E</a>
<p class="mt-2 mb-3 text-muted ">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur, Ut enim ad minim veniam quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo ...
Insérer texte
</p>
<div class="d-flex flex-wrap align-items-center gap-3">
<a class="btn btn-primary btn-sm">Lire la suite</a>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-calendar"></i>
Date :
17/12/2022 11:08:08
</div>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-tags"></i>
<a class="text-decoration-none m-1">Electro disco</a>
<a class="text-decoration-none m-1">Insérer style</a>
</div>
</div>
</div>
</div>
<div class="container bg-light row p-3 mt-3">
<div class="col-auto">
<img class="img-thumbnail"
src="data:image/png;base64,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" alt="Alternate Text" />
</div>
<div class="col">
<a class="text-primary text-decoration-none fw-light h4">Justice - D.A.N.C.E</a>
<p class="mt-2 mb-3 text-muted ">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur, Ut enim ad minim veniam quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo ...
</p>
<div class="d-flex flex-wrap align-items-center gap-3">
<a class="btn btn-primary btn-sm">Lire la suite</a>
</div> *@
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-calendar"></i>
17/12/2022 11:08:08
</div>
<div class="container">
@foreach (var titre in Model.DerniersTitres)
{
<div class="container bg-light row p-3 mt-3">
<div class="col-auto">
<img class="img-thumbnail img-fluid"
style="max-width:200px;"
@* UrlJaquette *@
src="@titre.UrlJaquette" />
</div>
<div class="col">
@* Artiste - Titre @titre.Artiste - @titre.Libelle*@
<a class="text-primary text-decoration-none fw-light h4">@titre.Artiste.Nom - @titre.Libelle</a>
@* Chronique *@
<p class="mt-2 mb-3 text-muted ">
@titre.Chronique
</p>
<div class="d-flex flex-wrap align-items-center gap-3">
<a class="btn btn-primary btn-sm">Lire la suite</a>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-tags"></i>
<a class="text-decoration-none m-1">Electro disco</a>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-calendar me-1"> </i>
@* Date de création *@
@titre.DateCreation
</div>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-tags"></i>
@* Style *@
<a class="text-decoration-none m-1">STYLE</a>
</div>
</div>
</div>
</div>
</div>
<div class="container bg-light row p-3 mt-3">
<div class="col-auto">
<img class="img-thumbnail"
src="data:image/png;base64,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" alt="Alternate Text" />
</div>
<div class="col">
<a class="text-primary text-decoration-none fw-light h4">Justice - D.A.N.C.E</a>
<p class="mt-2 mb-3 text-muted ">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur, Ut enim ad minim veniam quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo ...
</p>
<div class="d-flex flex-wrap align-items-center gap-3">
<a class="btn btn-primary btn-sm">Lire la suite</a>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-calendar"></i>
17/12/2022 11:08:08
</div>
<div class="d-flex align-items-center text-muted small">
<i class="fa-solid fa-tags"></i>
<a class="text-decoration-none m-1">Electro disco</a>
</div>
</div>
</div>
</div>
}
</div>
<div class="row justify-content-end">
@@ -121,53 +78,12 @@
<h1 class="mt-5">Titres les plus populaires</h1>
<div class="container">
@* TEMPLATE *@
@* <div class="container">
<div class="row">
<div class="card col m-1" style="width: 18rem;">
<img class="card-img-top"
src="data:image/png;base64,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" alt="Alternate Text" />
<div class="card-body">
<a class="card-link" href="#">Album</a><br />
par <a class="card-link">Artiste</a>
</div>
</div>
<div class="card col m-1" style="width: 18rem;">
<img class="card-img-top"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAA9lBMVEUJAgkAAAAAAAYAAAgAAAQIAggAAAsGAAk0JxMDAAgKAwoIAA
oIAwfDl0O9lD+UdDJnUibDmUHFnETBlEJeSCEbFQrLnEV6YisvIxiwiT7Fl0O8lEDHnkY+LxkUDQ2NbzVMOxwXDg8oHRFWQiGviTomGxUdFhItJxh7Xy2tgzyVdDVENR08MBihfDpr
TyVxWCcwIRAUEAx8YDaJajGvijg3KxyjhDUzJBtSQx2bej87KRYWEBWpfz0yKhMeGhocEQ5EOBscCxFmTClJNCDCkUoiGw+RdzA+OBZNQByHayqJazpbSx6UbzhvUCNRORlKPSMkFQ1
fSi15fRy6AAAQUklEQVR4nO2dC1ubTBaAYWAYYQaSAUICGHJPuUhIilq1duPqpru1l6/7///MDtG1VnNP/UAfXmtME8jDyQxnzjlz5gzHlZSUlJSUlJSUlJSUlJSUlJSUlJSUlJTsDM
77Al4YjN6khAqBECkc5CAmGDJQ3lf0h8FEgZjDikAUTxkSjiAPkbwv6k+ChEnnpNHuDo8Gg8Z4WiM1YQwm3tvprhB57yuV2O7HwWUYpJexn97G0QHCMO8r+1MgpRkbjqOpqkope9CoQ
9XA/wjfioSYTEzXOe7b/f6xzR4Ytq2plRP5zagb0kkMV+R/48iyzSl5KzeiItWdUx5lyEiWIZKx0HGNpIPfioScFOo+/9srGJzS27ejacAH+7AHfn+Nr1vhm+mkHPhhOF3h99eEM+v4A
LwVEWGV9vknelOYqW5TeCsSSiMn5p/cc1g8Vq+FNzFcQI5MY90XnpihmA+tnvQ2VI1CSHzYFp8a2sA8DCeEvAkZvUbfnTxRNByUGta5Bxae8NogyoVui0/bCnJ8vz9QmM/4+pG9qvNN
fOryQpkP6XjyOr3EXy5D9gROvICOxOeHgcQaEYIeLDcFZjelkjVqse9O+CTSRLyGrTef3oYM0FT7oqcgdnjWvpA8nM/dN3hx5MSYXSaUMWsOhXm7hEOINQ5CnDcBgvgxso1FAx8C7mWz04Gyr
BCBII4MoYIRgYoAYAcSkXXgwhgEhBDlk9QdoCEU/9GddmBH7igKkD963UaXTBM94BedxsduWAXvBpE3OZAGH7rKROyIA+DNvOHPqDnokqKMJZhrjMcnzc+x76fnSZokfttsJ1/T9JufhunID/vO7UIJgU/77nkl0OLz4/Mv52nwjX1C6MdBHAfBt/O015ugIoiIER4Htu0Gal/VqEtVQ3VVQzPUDM3IohbUXKBomIRth73nqJpL54exMw3DpQxVY29oRijIhein5KOpUsuyHMtxVMdxskukVvZrZb+Hh4fWu4UjO+ZdzdXucTV1furhAw51m5MiSAjJMOhfV59hzum121ftK2nxmei3uIbsZdQemBm0JSm52+YYEsW0ejwQnwF+sawl0G/IGcIDYlW3I4XkbfQgbxj1bf4lTBPE96k98/78B295GXLXPzwTXkDlYUUwD+2byZ//5C3xrgKbfxF9ADF/qoYD+SU+e5vLIOHh2cKxYP+PhiCi9DrfgByC0j+PWRO+0EVgPnY+T4U8g/8IzVrW2TPf7499PGjoVpJrI0Lhwj6VEHypcRnztzTMNTBOpMRqL3CM/hiC57jVWX6xDshfW8HLKNJ7MHOTjXFuEhJwc2q1RagwIFSYe45Q5qfPfdjsJ5uuR3tGYoBLqyQ3000y/3XKC8wqE9iDePeEOexy5hEw/1eS2OsiWD2gyfK9tXb/5P7lzIYT2CtI+Hr4ZeDlJKI0CzX/7KzdjJrs31WzeXQVHU3w5KRLMDck5N3RwVEzin6uuDxMajP2kz0MprXZbPbzrs9Db/BzMBhMZ8MG13d7L6bKVoNh1zaqF+0oYmK0L5iYTM4DD0+iyENkCL3xyZi9Yb4Hy41W9C5lDsjIHzEvpHc96rUjIevUCuq2q37im+aVWY1Vs5NPPAMp72I1Yf3w/85A1lkFRKAE0DxtRgbZS9FsReyeSCbPjmGOiJB1ccb8WMghSWTdXmD9nG/RaienXop+xurnO1UKmZqBd8ExnOXOQAzvI2XCGVGWNwCWJxI78T7axoyXu7AF65UEzvUXJKCvXuQ1IhKp59gLIzC/gCCRVnlWcFpbHYtBoqUdgJxuRAVEfePpvOAT0NhcOWDKP/+90mLA4EqNEc4pMg7h1eXhxepZTvCfq5USoMnNSucSiomTvKTVtBKIPsSHI7CykwnVNWOZ0Fs9m8+HtJqf1eYNK1Z9pYRY9BdHoR4Qfqz0cTHfV7srVNVLQ0wnXnkjIqWxRtFLF0erOiESVDvH6D5EDcNYrUgG3pqrE2bJqk4oHFnfvBz9JxAZdLq8k0EsHZA1STNI+CLB5cY5GOnmMMeYKRJiq72qCYbVdSkzUIy9FSMis2jatRxnUbFUt1bpctD8JKxxnoiYHj3N03gEb7vRMEcnH5GeU1nehkS4nq2dWxGqibj0W0CyG2I5z0iU1+yviJYSkCrrLg8KzXj5JwgH1i2fq4SCF7t4qaqRa+HawRpDEiwziyAWq5aZl2MxR4FeaJ0slUK4qK+VEDJV8zSr7+E9zKdOBHPN18BS1TGXS5hEa01KJoXfWxI0VyB/ardJrhISPlHr/LIrENPaBrMOoO0vmxaQJbfvcXlOdUPimdpSuw2J/hrf6u4wYbSspcVPajDLN1WaDA9sd9m8Bar5G/k94PuSLwKCr1bs5Tv5hMWTgC5zDoTR1438HjFd4mRCPqUpyHWeGzI9F+pXi69P4b+tH+8zQPX74m8C8YHewznP5EPiHyaLw4UIxMJG80ZgHIqLtQlwjb/yTqmBYsuqLI5GSQehsFFSE+JtfqEcYKy77bzi3Q+gH7YtZn1RefiHMxQERqPlBudjiBA0slsZPyZb1wZM6zLKWUKM5VngSmAhle5mufiEb/Uy9wI+gmRTPHzd8j/x+d6I7Lseu1b7YBGN1QGOXyDhxy2/kJjW819TK32IVVXXKaXsQVfnf9Qs70t3Pq+JFj+AoPs5jmPbtk9PAzuw/0/f0EcFyARHTEKHznPv2IPjzMVTVc11qptKyPxc1dC0LF/PmGfFUU2bJ/JpQXWFd/w3gb2/etWwkqaVsJX4ZtVspX7YCgNbs8YbR3LBF/blUNc9zlYm0r5LVcd12fdk92q5ZydiiPhG86LRIYo3wR7xCJ52px5u97XVUbjf4Ku6Gr5vf4h+NmqNXhT1ove9tp+YNxMl9wRTnFluEpl4WUo6ITJSJhOACIxc7dlCoOUI3UN6CwTiYS9b6+3JRMR4BtinEi7v4fAehV0IRPP5NdaqHB6YLk03z7PBvEG/NAFm52bfE2FDKgcFCAu6AhNzyGuE1Optns8n8wHt/5jcKRX8ChZAo8nAdvXO5hYlBKnqnJECLT9YA0RjWztebGsuRjizjNFmVmwxEK8MGm48GjK7TR7qqv961ltCJIQO9cXN7yckC65qN14iEfdlUMSWpm+V70bE2Ol3806W3RyhZmt0eaD4OcyNeE+1F80B/KMgb2hTe0PH4h5wZbkX+S892BAkXru0tYWi4bI0S1293dwIyhOFKRrpWrOq23U5JB2rdSnvmMxGKFk2Xkqtg60kxBhUnEqeU6GbwwxKxYupK211T2HmXlj9zsfX0IZZRuVFX906dVhsWkaUX6rsNiBvkmp06WTLMmTiOiFel7lRDMjPRNV7Wxf1AIGeDl7BjaiwRjyJ3WelTNbDpzT49Doq1qBI3Xa85+aDKFV7r2B5PnP2Uc+gSwL9q5DG1DBfwW0IOXkSUJpsLSFBoktj8RUoUyw3Yuqsn79/CsoWr192iy8h5FAt0JxnpUw2QPRpMCi+F6zIHtMY2ysaLsulpar5sfiNKM/YbfhldeLwYoQZpZVp4X1EKNSYhNVdJt8R31cvtx9H/3ZA09b0g13akKkaGnQLXuAMYjy7cTVX2mk+hU+c45t/FFtCNqzNUjWbsdihDaF0RY1kmneFgdUo0JvGqlPfTULsUSMcFty9gHBma9bZbhO3maqJvWLb3gonHGmGPthJIUKFb1F73eqFvIEgcbXj7SIYvxCr1G2+6Lri/UGgQtVtZix+AzR16q9Yj1kAFDKJXZrsWkWCuReqX+yipljp9A0a7Zwhwgf6FzHHVU7rgV7P0NzdlymJKY0HhQ64YemHQe3dg/OCadnTQg8XePJdpa09JOzqxkWRNxWAWKiodCTu3EsxcGmv0Lchx1ynw81ToZ4hM/cimRR4Op+Q9wZdmti+CfNIRmElhJAME0ov9zBKoNA+ND5MCjskIthoUbq4RuJmEKTQftsrbAFlLJ+41HpafH0rIN+3fK+wLiIRbjTNmuyV88p/VsPi9lIZt6i2x3ifwSeO7RVVQkwGgaZW9vN+QPPQMYu6swdGw5gyx2IvCWVR067XFCnICwxJs2/ozf0Ss5Foq9WCdlKODGLDpXDPOiRCqsbNgvZS1B0Zmr3ZUqflANOKC5rghjimSp0Wv+fVSQdW5aSQoX0I5dkttUwxW760zYmPjs6eIWBo5pAUMcObiJGr6V3+UXVd4eHJvFDWXS3d+8MxEmRBvq+fBYD4cBgfO+89WJxi5b8gXs9wtVF1ZFbNdrvd60Xjn3+xJ+2/omwV1MXFQafWrXnenedAvGnjXXd20I1M82hkmvPCyhcXN+OLRksNDwhXvEaEyLum1Kj7aX2UpGFY95OkenZxdNSL6maUSdrzZt3ZdDovfYxmR23TrFdH9TTMDmS/vl+vfq3XK0lI7aP5eoSCAeHQd1x9yGcd7m7l2bzcmiBKvJhVF5R4jO+MFTxPlAbzvsmLvDAvGy3yvMCzw3gxpAknF/FGJHJku3pP2HNJAQI2vd4iRfxvBHFSxXm6Ndf2ZLskjUkxc6PQpO7QmN/TuRPbh8GgqBKSnqa5u2RhPIb3rXBY0KmLecDbGuw5Ec/HagtgXEg3H3pT23V6K8skrgXxLq1KxdOjcwiqBVRN91M1QvfQGe2rrV4KNsa1NO10Tx//2gqGchFtNu5OQsdw95OQT53KpCjrRp9BhKarWbO9XB8+oCkp7NoZBMZ9zTrbQ0IFA1X3J8WV0JsGKk332SkBNK1+r0D7PD3Fa4QOXby302Yg8N2KG8WMYXBzl2HIXMR1dXdXAfmWkyqFlZA5FczNV/XxulKJK+D79LzQ8/hSdiOau+8uKhOLjnbNN/pbELuBRtPdu6lwZV3yuRcVWgXspJSpmp1dH9HXU1RA7/4R5MCm7u7Ta/xn50uhm5BTOO+c6ge7ioj4vr6nb/Li4Jrt0Otdx3xhpveHhTVK70BSoqm7zuQrYs+KO8UMYDyA+RtN7e8mIVT4Oh0VYj/AVeCZTbUdRzQILtVoWOgBnyEOfHXhzrHrgZh3jYiQYmsa7mPHp3p1pwUlUDqw6hAXfU0+gT0jy07c5TIF06oW2mS7R4mpze8U2udTejNBXCEDiY9AuGJoEliwa+fiwoGPCdxB0TVpBrmmNK0/wvfv/ra+PBBWFvFNvTwpfieFMmwHhm5Qh2ab/d5VGKRZWUUn2/F3/qBm5QPnGMb9NsBq9sSw34Oid9EspNi5qtaz6omuRp1MAj3b/dighqq71L3bz5j9R2VfAZOUPfuXTjWqaY7b+t4fT15BG0KIlKuk9d2u+CM/+a+fVC/+22w2TLNXNW+/X/ux74/Slp+c+9WqeXPTS83R7ejcT+L6PyfRIKddj7YCcpAoCtfoDqNhbQJ4SfJ44nlwWvvISQQos6HXeDfwRCDwH4k8Ibgzk0TiSd3OxIMFTfd6CuYI8aA3lYRsHdrdZlyK4hFIsnJ6EsAC8CBCUOGyooiep7A/EApysZcDPSYrnZjJAu8SZLjsCZMuK5vLDILsYZ6soGTliLjspbt3Cce9npp7czAubmC3pKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKRkEf8DQ2thWlWjDVAAAAAASUVORK5CYII=" alt="Alternate Text" />
<div class="card-body">
<a class="card-link" href="#">Album</a><br />
par <a class="card-link">Artiste</a>
</div>
</div>
<div class="card col m-1" style="width: 18rem;">
<img class="card-img-top"
src="data:image/png;base64,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" alt="Alternate Text" />
src="" alt="Alternate Text" />
<div class="card-body">
<a class="card-link" href="#">Album</a><br />
@@ -175,4 +91,21 @@
</div>
</div>
</div>
</div> *@
<div class="container">
<div class="row">
@foreach (var titre in Model.TopTitres)
{
<div class="card col-4 m-1" style="width: 18rem;">
<img class="card-img-top"
src="@titre.UrlJaquette" />
<div class="card-body">
<a class="card-link" href="#">@titre.Album</a><br />
par <a class="card-link">@titre.Artiste.Nom</a>
</div>
</div>
}
</div>
</div>

View File

@@ -0,0 +1,70 @@
@model Webzine.WebApplication.ViewModels.ArtisteModel
@{
ViewData["Title"] = "Artiste";
}
<div class="container">
<h1>@Model.Artiste.Nom</h1>
<hr class="mb-5" />
<p class="lead">@Model.Artiste.Biographie</p>
<h2 class="mt-5 mb-4">Albums</h2>
<hr class="mb-5" />
@* 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)
{
// On récupère le premier titre du groupe pour afficher l'image de l'album
var premierTitre = groupe.First();
<div class="row mb-5 align-items-start">
<div class="col-md-3 mb-3">
<img src="@premierTitre.UrlJaquette"
class="img-fluid shadow-sm rounded border"
alt="Pochette de @groupe.Key" />
</div>
<div class="col-md-9">
<h3 class="h4 pb-2">@groupe.Key</h3>
<table class="table table-hover table-sm mt-3">
<thead class="text-muted">
<tr>
<th style="width: 80px">Durée</th>
<th>Titre</th>
</tr>
</thead>
<tbody>
@foreach (var titre in groupe)
{
// Conversion des secondes en format MM:SS
var minutes = titre.Duree / 60;
var secondes = titre.Duree % 60;
var dureeFormatee = $"{minutes}:{secondes:D2}";
<tr>
<td class="text-secondary font-monospace">@dureeFormatee</td>
<td>
<span class="text-primary fw-bold" style="cursor:pointer">
@titre.Libelle
</span>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
</div>

View File

@@ -0,0 +1,66 @@
@{
ViewData["Title"] = "Contact";
}
<div class="container">
<h1>Contact</h1>
<div>
C.U.C.D.B - DIIAGE <br />
69 Avenue Aristide Briand<br />
21000 Dijon</p>
</div>
<div>
<i class="fa-solid fa-phone"></i> Phone : 03 80 40 50 60<br />
<i class="fa-solid fa-envelope"></i> secretariat@cucdb.fr
</div>
</div>
<div class="container mt-5">
<h2>Suivez-nous</h2>
<div class="row g-4 text-center">
<div class="col-md-4">
<a href="#" class="card h-100 p-4 shadow-sm border-0 bg-light-subtle text-decoration-none">
<i class="fa-solid fa-link fa-3x text-primary mb-3"></i>
<div class="fw-bold text-primary">Site officiel du DIIAGE</div>
</a>
</div>
<div class="col-md-4">
<a href="#" class="card h-100 p-4 shadow-sm border-0 bg-light-subtle text-decoration-none">
<i class="fa-brands fa-facebook fa-3x text-primary mb-3"></i>
<div class="fw-bold text-primary">Facebook</div>
</a>
</div>
<div class="col-md-4">
<a href="#" class="card h-100 p-4 shadow-sm border-0 bg-light-subtle text-decoration-none">
<i class="fa-brands fa-instagram fa-3x text-primary mb-3"></i>
<div class="fw-bold text-primary">Instagram</div>
</a>
</div>
<div class="col-md-4">
<a href="#" class="card h-100 p-4 shadow-sm border-0 bg-light-subtle text-decoration-none">
<i class="fa-brands fa-linkedin fa-3x text-primary mb-3"></i>
<div class="fw-bold text-primary">LinkedIn</div>
</a>
</div>
<div class="col-md-4">
<a href="#" class="card h-100 p-4 shadow-sm border-0 bg-light-subtle text-decoration-none">
<i class="fa-solid fa-map fa-3x text-primary mb-3"></i>
<div class="fw-bold text-primary">Google Maps</div>
</a>
</div>
<div class="col-md-4">
<a href="#" class="card h-100 p-4 shadow-sm border-0 bg-light-subtle text-decoration-none">
<i class="fa-brands fa-twitter fa-3x text-primary mb-3"></i>
<div class="fw-bold text-primary">Twitter</div>
</a>
</div>
</div>
</div>

View File

@@ -6,8 +6,9 @@
<title>@ViewData["Title"] - Webzine</title>
@* Ajout de bootstrap *@
<script src="./js/bootstrap.min.js" defer></script>
<link rel="stylesheet" href="./css/bootstrap.min.css">
<script src="~/js/bootstrap.min.js" defer></script>
<link rel="stylesheet" href="~/css/app.css">
<link rel="stylesheet" href="~/css/bootstrap.min.css">
@* Ajout de font-awesome *@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">

View File

@@ -0,0 +1,193 @@
@model Webzine.WebApplication.ViewsModels.Titre.TitreDetail
@{
ViewData["Title"] = Model.Details.Libelle;
}
<div class="container mt-4">
<div class="mb-3">
<h2>
<a asp-area="" asp-controller="" asp-action="" asp-route-style="@Model.Details.ArtisteNom">@Model.Details.ArtisteNom</a>
- @Model.Details.Libelle
</h2>
<div class="d-flex justify-content-between align-items-center pb-2 mb-3">
<div class="text-muted small d-flex align-items-center gap-4">
<!-- Date -->
<span class="text-dark">
<i class="fa fa-calendar me-1"></i>
Le @Model.Details.DateSortie.ToString("dd/MM/yyyy 'à' HH:mm")
</span>
<!-- Likes -->
<span>
<i class="fa fa-heart text-dark me-1"></i>
@Model.Details.NbLikes
</span>
<!-- Styles -->
<span class="text-dark">
<i class="fa fa-tags me-1"></i>
Styles :
@for (int i = 0; i < Model.Details.Styles.Count; i++)
{
var style = Model.Details.Styles[i];
<a class="text-primary text-decoration-none fw-semibold"
asp-controller="Titre"
asp-action="Style"
asp-route-style="@style.Libelle">
@style.Libelle
</a>
@if (i < Model.Details.Styles.Count - 1)
{
<span>, </span>
}
}
</span>
</div>
<!-- ACTION BUTTONS -->
<div class="d-flex gap-2">
<form asp-action="Like" method="post">
<input type="hidden" name="IdTitre" value="@Model.Details.IdTitre" />
<button type="submit" class="btn btn-outline-primary btn-sm">
<i class="fa fa-thumbs-up me-1"></i> Like
</button>
</form>
<a class="btn text-primary btn-sm">
<i class="fa fa-pen-to-square me-1"></i> Editer
</a>
</div>
</div>
</div>
<!-- CONTENU -->
<div class="row mt-4">
<div class="col-md-8">
<p class="text-justify">
@Model.Details.Chronique
</p>
</div>
<div class="col-md-4 text-center">
<img src="@Model.Details.UrlJaquette"
class="img-fluid rounded shadow"
alt="Jaquette" />
</div>
</div>
<!-- LECTEUR -->
@if (!string.IsNullOrEmpty(Model.Details.UrlEcoute))
{
<div class="mt-4">
<iframe width="100%" height="315"
src="@Model.Details.UrlEcoute"
title="Lecteur"
allowfullscreen>
</iframe>
</div>
}
<!-- FORMULAIRE COMMENTAIRE -->
<div class="mt-4 mb-4">
<div>
<h4 class="mb-4">Donne ton avis sur le titre</h4>
<form asp-action="Comment" method="post">
<input type="hidden" name="IdTitre" value="@Model.Details.IdTitre"/>
<div class="row mb-3 align-items-center">
<label class="col-sm-2 col-form-label">
Nom<span class="text-danger">*</span>
</label>
<div class="col">
<input name="Auteur"
class="form-control input-full"
placeholder="Votre nom"
required />
</div>
</div>
<div class="row mb-3 align-items-start">
<label class="col-sm-2 col-form-label">
Commentaire<span class="text-danger">*</span>
</label>
<div class="col">
<textarea name="Contenu"
rows="3"
class="form-control input-full"
placeholder="Votre commentaire..."
required></textarea>
</div>
</div>
<div class="row">
<div class="col-sm-6 offset-sm-2">
<button type="submit" class="btn btn-primary">
Envoyer
</button>
</div>
</div>
</form>
</div>
</div>
<!-- COMMENTAIRES -->
<div class="mt-4">
<h4 class="mb-4">Commentaires</h4>
@if (Model.Details.Commentaires.Any())
{
foreach (var comment in Model.Details.Commentaires.OrderByDescending(c => c.DateCreation))
{
<div class="row mb-4">
<div class="col-sm-1"></div>
<div class="col-sm-6 d-flex">
<img src="/images/avatar.png"
width="50"
height="50"
class="rounded-circle me-3 shadow-sm"
alt="avatar" />
<div>
<strong>@comment.Auteur</strong>,
<span class="text-muted small">
le @comment.DateCreation.ToString("dd/MM/yyyy HH:mm")
</span>
<p class="mb-0">@comment.Contenu</p>
</div>
</div>
</div>
}
}
else
{
<div class="row">
<div class="col-sm-6 offset-sm-2">
<p class="text-muted">Aucun commentaire pour le moment.</p>
</div>
</div>
}
</div>
</div>

View File

@@ -0,0 +1,50 @@
@model Webzine.WebApplication.ViewsModels.Titre.TitreStyle
@{
ViewData["Title"] = $"Titres - {Model.StyleName}";
Layout = "_Layout";
}
<div class="container mt-4">
<div class="row">
<!-- COLUMN -->
<div class="col-md-8">
<h1 class="mb-4 titre-h1">Titres ayant le style @Model.StyleName</h1>
@if (!Model.Titres.Any())
{
<div class="alert alert-info">
Aucun titre trouvé.
</div>
}
else
{
@foreach (var titre in Model.Titres)
{
<div class="titre-item d-flex align-items-start">
<!-- Image -->
<div class="me-3">
<img src="@titre.UrlJaquette" alt="@titre.Libelle" />
</div>
<!-- Infos -->
<div>
<a asp-action="Details"
asp-route-id="@titre.IdTitre"
class="titre-link">
@titre.ArtisteNom - @titre.Libelle
</a>
<div class="titre-duree">
Durée : @TimeSpan.FromSeconds(titre.Duree).ToString(@"mm\:ss")
</div>
</div>
</div>
}
}
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace Webzine.WebApplication.ViewsModels.Titre;
public class TitreComment
{
[Required]
public int IdTitre { get; set; }
[Required]
[MinLength(2)]
[MaxLength(30)]
public string Auteur { get; set; }
[Required]
[MinLength(10)]
[MaxLength(1000)]
public string Contenu { get; set; }
}

View File

@@ -0,0 +1,26 @@
using Webzine.Entity;
namespace Webzine.WebApplication.ViewsModels.Titre;
public class TitreContent
{
public int IdTitre { get; set; }
public string Libelle { get; set; }
public string Chronique { get; set; }
public DateTime DateSortie { get; set; }
public int NbLikes { get; set; }
public string UrlJaquette { get; set; }
public string UrlEcoute { get; set; }
public string ArtisteNom { get; set; }
public List<Style> Styles { get; set; } = new();
public List<Commentaire> Commentaires { get; set; } = new();
}

View File

@@ -0,0 +1,7 @@
namespace Webzine.WebApplication.ViewsModels.Titre;
public class TitreDetail
{
public TitreContent Details { get; set; }
public TitreComment CommentForm { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Webzine.WebApplication.ViewsModels.Titre;
public class TitreLike
{
public int IdTitre { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace Webzine.WebApplication.ViewsModels.Titre;
public class TitreStyle
{
public string? StyleName { get; set; }
public List<TitreStyleItem> Titres { get; set; } = new();
}

View File

@@ -0,0 +1,14 @@
namespace Webzine.WebApplication.ViewsModels.Titre;
public class TitreStyleItem
{
public int IdTitre { get; set; }
public string? Libelle { get; set; }
public string? ArtisteNom { get; set; }
public string? UrlJaquette { get; set; }
public int Duree { get; set; }
}

View File

@@ -7,13 +7,6 @@
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Views\Accueils\**" />
<Content Remove="Views\Accueils\**" />
<EmbeddedResource Remove="Views\Accueils\**" />
<None Remove="Views\Accueils\**" />
</ItemGroup>
<ItemGroup>
<Content Include="..\.dockerignore">
<Link>.dockerignore</Link>
@@ -32,7 +25,7 @@
<PackageReference Include="Faker.Net" Version="2.0.163" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.3" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.*" />
<PackageReference Include="NLog" Version="6.1.1" />
<PackageReference Include="NLog" Version="6.1.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -40,7 +33,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Webzine.Repository.Contracts\Webzine.Repository.Contracts.csproj" />
<ProjectReference Include="..\Webzine.Entity\Webzine.Entity.csproj" />
<ProjectReference Include="..\Webzine.Repository\Webzine.Repository.csproj" />
</ItemGroup>

View File

@@ -2,9 +2,12 @@
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
<Controller_SelectedScaffolderID>MvcControllerWithActionsScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
<View_SelectedScaffolderID>RazorViewEmptyScaffolder</View_SelectedScaffolderID>
<View_SelectedScaffolderCategoryPath>root/Common/MVC/View</View_SelectedScaffolderCategoryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@@ -5,5 +5,9 @@
"Microsoft.AspNetCore": "Warning"
}
},
"Webzine": {
"NombreDerniereChronique": 3,
"NombreDeTopTitres" : 5
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,33 @@
a {
text-decoration: none !important;
}
.titre-h1 {
padding: 15px 0;
border-bottom: 1px solid #ddd;
}
.titre-item {
padding: 8px 0;
}
.titre-item img {
width: 70px;
height: 70px;
object-fit: cover;
}
.titre-link {
font-size: 1.1rem;
color: #0d6efd;
text-decoration: none;
}
.titre-link:hover {
text-decoration: underline;
}
.titre-duree {
font-size: 0.9rem;
color: #666;
}