Skip to content

Commit

Permalink
Symfony Quest Nr.27 Challenge
Browse files Browse the repository at this point in the history
  • Loading branch information
jlegrand-79 committed Feb 11, 2023
1 parent e8f129a commit 2222e4f
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 25 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
Démonstration vidéo des fonctionnalités
# Démonstration vidéo des fonctionnalités

Symfony Quest Nr.14 Challenge
https://webmshare.com/play/EedXy
<https://webmshare.com/play/EedXy>

- Ajout d'une catégorie
- Ajout d'un programme dans cette nouvelle catégorie

Symfony Quest Nr.16 Challenge
https://webmshare.com/play/rE14Q
<https://webmshare.com/play/rE14Q>

- Contrôles serveur sur valeurs du formulaire de création de série
- Champs obligatoires, taille maximale, unicité du titre, pas de "plus belle la vie" dans le synopsis

Symfony Quest Nr.27 Challenge
<https://webmshare.com/play/1yJGL>

- Ajout/Suppression d'une série à la Watchlist pour un utilisateur
19 changes: 11 additions & 8 deletions assets/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
* (and its CSS file) in your base layout (base.html.twig).
*/

// any CSS you import will output into a single css file (app.css in this case)
import './styles/app.scss';

// start the Stimulus application
import './bootstrap';

// Message de test
console.log('Hello Webpack Encore !')
// const $ = require('jquery');
// this "modifies" the jquery module: adding behavior to it
// the bootstrap module doesn't export/return anything

// Message de test
// console.log('Hello Webpack Encore !')

// const $ = require('jquery');
// // this "modifies" the jquery module: adding behavior to it
// // the bootstrap module doesn't export/return anything
require('bootstrap');

// Import of Bootstrap-icons
import 'bootstrap-icons/font/bootstrap-icons.css';

// any CSS you import will output into a single css file (app.css in this case)
import './styles/app.scss';

// // or you can include specific pieces
// // require('bootstrap/js/dist/tooltip');
// // require('bootstrap/js/dist/popover');
Expand Down
13 changes: 13 additions & 0 deletions assets/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,21 @@ main {

h1 {
color: $primary;
font-size: 2em;
margin: 0.5em;
margin-left: 0;
}

h2 {
color: $secondary;
}

.watchlist-icons {
color: $primary;
font-size: 2em;
}

.program-poster {
max-height: 400px;
max-height: 50vh;
}
12 changes: 6 additions & 6 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions migrations/Version20230130065732.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20230130065732 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE watchlist (user_id INT NOT NULL, program_id INT NOT NULL, INDEX IDX_340388D3A76ED395 (user_id), INDEX IDX_340388D33EB8070A (program_id), PRIMARY KEY(user_id, program_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE watchlist ADD CONSTRAINT FK_340388D3A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE watchlist ADD CONSTRAINT FK_340388D33EB8070A FOREIGN KEY (program_id) REFERENCES program (id) ON DELETE CASCADE');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE watchlist DROP FOREIGN KEY FK_340388D3A76ED395');
$this->addSql('ALTER TABLE watchlist DROP FOREIGN KEY FK_340388D33EB8070A');
$this->addSql('DROP TABLE watchlist');
}
}
28 changes: 28 additions & 0 deletions src/Controller/ProgramController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
use App\Form\ProgramType;
use App\Form\SearchProgramType;
use App\Repository\CommentRepository;
use App\Repository\UserRepository;
use App\Service\ProgramDuration;
use DateTime;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\String\Slugger\SluggerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\User\UserInterface;

#[Route('/program', name: 'program_')]
class ProgramController extends AbstractController
Expand Down Expand Up @@ -204,6 +206,32 @@ public function showEpisode(
]);
}

// WATCHLIST START

#[Route('/{id}/watchlist', methods: ['GET', 'POST'], name: 'watchlist')]
public function addToWatchlist(Program $program, UserRepository $userRepository): Response
{
if (!$program) {
throw $this->createNotFoundException(
'Aucune série correspondante en base.'
);
}

/** @var \App\Entity\User */
$user = $this->getUser();
if ($user->isInWatchlist($program)) {
$user->removeFromWatchlist($program);
} else {
$user->addToWatchlist($program);
}

$userRepository->save($user, true);

return $this->redirectToRoute('program_show', ['slug' => $program->getSlug()], Response::HTTP_SEE_OTHER);
}

// WATCHLIST END

// DELETE PROGRAM START

#[Route('/{id}', name: 'delete', methods: ['POST'])]
Expand Down
31 changes: 31 additions & 0 deletions src/Entity/Program.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@ class Program
#[ORM\JoinColumn(nullable: false)]
private ?User $Owner = null;

#[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'watchlist')]
private Collection $viewers;

public function __construct()
{
// $this->number = new ArrayCollection();
$this->seasons = new ArrayCollection();
$this->actors = new ArrayCollection();
$this->viewers = new ArrayCollection();
}


Expand Down Expand Up @@ -249,4 +253,31 @@ public function setOwner(?User $Owner): self

return $this;
}

/**
* @return Collection<int, User>
*/
public function getViewers(): Collection
{
return $this->viewers;
}

public function addViewer(User $viewer): self
{
if (!$this->viewers->contains($viewer)) {
$this->viewers->add($viewer);
$viewer->addToWatchlist($this);
}

return $this;
}

public function removeViewer(User $viewer): self
{
if ($this->viewers->removeElement($viewer)) {
$viewer->removeFromWatchlist($this);
}

return $this;
}
}
34 changes: 34 additions & 0 deletions src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Column(type: 'boolean')]
private $isVerified = false;

#[ORM\ManyToMany(targetEntity: Program::class, inversedBy: 'viewers')]
#[ORM\JoinTable(name: 'watchlist')]
private Collection $watchlist;

public function __construct()
{
$this->comments = new ArrayCollection();
$this->programs = new ArrayCollection();
$this->watchlist = new ArrayCollection();
}

public function getId(): ?int
Expand Down Expand Up @@ -187,4 +192,33 @@ public function setIsVerified(bool $isVerified): self

return $this;
}

/**
* @return Collection<int, Program>
*/
public function getWatchlist(): Collection
{
return $this->watchlist;
}

public function addToWatchlist(Program $watchlist): self
{
if (!$this->watchlist->contains($watchlist)) {
$this->watchlist->add($watchlist);
}

return $this;
}

public function removeFromWatchlist(Program $watchlist): self
{
$this->watchlist->removeElement($watchlist);

return $this;
}

public function isInWatchlist(Program $program): bool
{
return $this->watchlist->contains($program) ? true : false;
}
}
4 changes: 3 additions & 1 deletion templates/base.html.twig
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<!DOCTYPE html>
<html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" href="{{ asset('build/images/favicon-16x16.png') }}"/>
<title>
{% block title %}Welcome!
Expand Down
19 changes: 13 additions & 6 deletions templates/program/show.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@

{% block body %}
<div class="media">
{% if program.poster is empty %}
<div></div>
{% else %}
{% if program.poster %}
{% if program.poster starts with 'http' %}
<div>
<img class="align-self-start mr-3" src="{{program.poster}}" alt="{{ program.title }} poster">
<img class="align-self-start mr-3 program-poster" src="{{program.poster}}" alt="{{ program.title }} poster">
</div>
{% else %}
<div>
<img class="align-self-start mr-3" src="{{ vich_uploader_asset(program) }}" alt="{{ program.title }} poster">
<img class="align-self-start mr-3 program-poster" src="{{ vich_uploader_asset(program) }}" alt="{{ program.title }} poster">
</div>
{% endif %}
{% endif %}
<h1 class="mt-0">{{ program.title }}</h1>
<div class="d-flex flex-row align-items-center">
<h1>{{ program.title }}</h1>
{% if app.user %}
<div>
<a href="{{ path('program_watchlist', {id: program.id})}}">
<i class="watchlist-icons bi {{ app.user.isInWatchlist(program) ? 'bi-heart-fill' : 'bi-heart' }}" alt="watchlist"></i>
</a>
</div>
{% endif %}
</div>
<p>{{ program.synopsis }}</p>
<p>Catégorie :
{{ program.category.name }}</p>
Expand Down
3 changes: 3 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,8 @@ fullConfig.devServer = {
watchFiles: {
paths: ['templates/**/*.html.twig'],
},
headers: {
'Access-Control-Allow-Origin': '*',
},
};
module.exports = fullConfig;
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,7 @@ boolbase@^1.0.0:

bootstrap-icons@^1.10.3:
version "1.10.3"
resolved "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.3.tgz"
resolved "https://registry.yarnpkg.com/bootstrap-icons/-/bootstrap-icons-1.10.3.tgz#c587b078ca6743bef4653fe90434b4aebfba53b2"
integrity sha512-7Qvj0j0idEm/DdX9Q0CpxAnJYqBCFCiUI6qzSPYfERMcokVuV9Mdm/AJiVZI8+Gawe4h/l6zFcOzvV7oXCZArw==

bootstrap@^5.2.3:
Expand Down

0 comments on commit 2222e4f

Please sign in to comment.