Browse Source

gère les projets

master
vincent 5 months ago
parent
commit
61b42ef422
33 changed files with 4583 additions and 939 deletions
  1. +10
    -0
      .env
  2. +0
    -3
      assets/styles/app.css
  3. +8
    -0
      compose.override.yaml
  4. +26
    -0
      compose.yaml
  5. +13
    -1
      composer.json
  6. +3843
    -904
      composer.lock
  7. +4
    -0
      config/bundles.php
  8. +52
    -0
      config/packages/doctrine.yaml
  9. +6
    -0
      config/packages/doctrine_migrations.yaml
  10. +7
    -0
      config/packages/stof_doctrine_extensions.yaml
  11. +4
    -0
      config/packages/twig.yaml
  12. +11
    -0
      config/packages/validator.yaml
  13. +17
    -0
      config/packages/web_profiler.yaml
  14. +8
    -0
      config/routes/web_profiler.yaml
  15. +0
    -0
      migrations/.gitignore
  16. +31
    -0
      migrations/Version20240720132139.php
  17. +40
    -0
      migrations/Version20240720143743.php
  18. +173
    -0
      src/Controller/ProjectController.php
  19. +0
    -0
      src/Entity/.gitignore
  20. +62
    -0
      src/Entity/Project.php
  21. +31
    -0
      src/Form/ProjectType.php
  22. +0
    -0
      src/Repository/.gitignore
  23. +43
    -0
      src/Repository/ProjectRepository.php
  24. +64
    -0
      symfony.lock
  25. +7
    -0
      templates/_footer.html.twig
  26. +6
    -25
      templates/_header.html.twig
  27. +33
    -3
      templates/base.html.twig
  28. +0
    -1
      templates/home/base.html.twig
  29. +8
    -2
      templates/home/index.html.twig
  30. +12
    -0
      templates/project/create.html.twig
  31. +31
    -0
      templates/project/index.html.twig
  32. +21
    -0
      templates/project/show.html.twig
  33. +12
    -0
      templates/project/update.html.twig

+ 10
- 0
.env View File

@ -18,3 +18,13 @@
APP_ENV=dev APP_ENV=dev
APP_SECRET=058a87fc191ae22ce3144178e163bac8 APP_SECRET=058a87fc191ae22ce3144178e163bac8
###< symfony/framework-bundle ### ###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
# DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###

+ 0
- 3
assets/styles/app.css View File

@ -1,3 +0,0 @@
body {
background-color: skyblue;
}

+ 8
- 0
compose.override.yaml View File

@ -0,0 +1,8 @@
version: '3'
services:
###> doctrine/doctrine-bundle ###
database:
ports:
- "5432"
###< doctrine/doctrine-bundle ###

+ 26
- 0
compose.yaml View File

@ -0,0 +1,26 @@
version: '3'
services:
###> doctrine/doctrine-bundle ###
database:
image: postgres:${POSTGRES_VERSION:-16}-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB:-app}
# You should definitely change the password in production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
POSTGRES_USER: ${POSTGRES_USER:-app}
healthcheck:
test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
timeout: 5s
retries: 5
start_period: 60s
volumes:
- database_data:/var/lib/postgresql/data:rw
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
# - ./docker/db/data:/var/lib/postgresql/data:rw
###< doctrine/doctrine-bundle ###
volumes:
###> doctrine/doctrine-bundle ###
database_data:
###< doctrine/doctrine-bundle ###

+ 13
- 1
composer.json View File

@ -7,21 +7,33 @@
"php": ">=8.2", "php": ">=8.2",
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.2",
"league/commonmark": "^2.4",
"league/html-to-markdown": "^5.1",
"stof/doctrine-extensions-bundle": "^1.12",
"symfony/asset": "7.1.*", "symfony/asset": "7.1.*",
"symfony/asset-mapper": "7.1.*", "symfony/asset-mapper": "7.1.*",
"symfony/console": "7.1.*", "symfony/console": "7.1.*",
"symfony/dotenv": "7.1.*", "symfony/dotenv": "7.1.*",
"symfony/flex": "^2", "symfony/flex": "^2",
"symfony/form": "7.1.*",
"symfony/framework-bundle": "7.1.*", "symfony/framework-bundle": "7.1.*",
"symfony/runtime": "7.1.*", "symfony/runtime": "7.1.*",
"symfony/twig-bundle": "7.1.*", "symfony/twig-bundle": "7.1.*",
"symfony/validator": "7.1.*",
"symfony/yaml": "7.1.*", "symfony/yaml": "7.1.*",
"twig/extra-bundle": "^2.12|^3.0", "twig/extra-bundle": "^2.12|^3.0",
"twig/markdown-extra": "^3.10",
"twig/twig": "^2.12|^3.0" "twig/twig": "^2.12|^3.0"
}, },
"require-dev": { "require-dev": {
"symfony/debug-bundle": "7.1.*", "symfony/debug-bundle": "7.1.*",
"symfony/maker-bundle": "^1.60"
"symfony/maker-bundle": "^1.60",
"symfony/stopwatch": "7.1.*",
"symfony/web-profiler-bundle": "7.1.*"
}, },
"config": { "config": {
"allow-plugins": { "allow-plugins": {


+ 3843
- 904
composer.lock
File diff suppressed because it is too large
View File


+ 4
- 0
config/bundles.php View File

@ -6,4 +6,8 @@ return [
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
]; ];

+ 52
- 0
config/packages/doctrine.yaml View File

@ -0,0 +1,52 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '16'
profiling_collect_backtrace: '%kernel.debug%'
use_savepoints: true
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
report_fields_where_declared: true
validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
type: attribute
is_bundle: false
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
controller_resolver:
auto_mapping: false
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system

+ 6
- 0
config/packages/doctrine_migrations.yaml View File

@ -0,0 +1,6 @@
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations'
enable_profiler: false

+ 7
- 0
config/packages/stof_doctrine_extensions.yaml View File

@ -0,0 +1,7 @@
# Read the documentation: https://symfony.com/doc/current/bundles/StofDoctrineExtensionsBundle/index.html
# See the official DoctrineExtensions documentation for more details: https://github.com/doctrine-extensions/DoctrineExtensions/tree/main/doc
stof_doctrine_extensions:
default_locale: fr_FR
orm:
default:
sluggable: true

+ 4
- 0
config/packages/twig.yaml View File

@ -1,7 +1,11 @@
twig: twig:
file_name_pattern: '*.twig' file_name_pattern: '*.twig'
form_themes: ['bootstrap_5_layout.html.twig']
globals: globals:
title: Gestionnaire de tâches simple title: Gestionnaire de tâches simple
menu:
header:
- { route: 'app_project', label: 'Projets' }
when@test: when@test:
twig: twig:


+ 11
- 0
config/packages/validator.yaml View File

@ -0,0 +1,11 @@
framework:
validation:
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []
when@test:
framework:
validation:
not_compromised_password: false

+ 17
- 0
config/packages/web_profiler.yaml View File

@ -0,0 +1,17 @@
when@dev:
web_profiler:
toolbar: true
intercept_redirects: false
framework:
profiler:
only_exceptions: false
collect_serializer_data: true
when@test:
web_profiler:
toolbar: false
intercept_redirects: false
framework:
profiler: { collect: false }

+ 8
- 0
config/routes/web_profiler.yaml View File

@ -0,0 +1,8 @@
when@dev:
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
prefix: /_wdt
web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler

+ 0
- 0
migrations/.gitignore View File


+ 31
- 0
migrations/Version20240720132139.php View File

@ -0,0 +1,31 @@
<?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 Version20240720132139 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 project (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description CLOB DEFAULT NULL)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE project');
}
}

+ 40
- 0
migrations/Version20240720143743.php View File

@ -0,0 +1,40 @@
<?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 Version20240720143743 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 TEMPORARY TABLE __temp__project AS SELECT id, name, description FROM project');
$this->addSql('DROP TABLE project');
$this->addSql('CREATE TABLE project (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description CLOB DEFAULT NULL, slug VARCHAR(255) NOT NULL)');
$this->addSql('INSERT INTO project (id, name, description) SELECT id, name, description FROM __temp__project');
$this->addSql('DROP TABLE __temp__project');
$this->addSql('CREATE UNIQUE INDEX UNIQ_2FB3D0EE989D9B62 ON project (slug)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TEMPORARY TABLE __temp__project AS SELECT id, name, description FROM project');
$this->addSql('DROP TABLE project');
$this->addSql('CREATE TABLE project (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description CLOB DEFAULT NULL)');
$this->addSql('INSERT INTO project (id, name, description) SELECT id, name, description FROM __temp__project');
$this->addSql('DROP TABLE __temp__project');
}
}

+ 173
- 0
src/Controller/ProjectController.php View File

@ -0,0 +1,173 @@
<?php
namespace App\Controller;
use App\Entity\Project;
use App\Form\ProjectType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
#[Route('/project')]
class ProjectController extends AbstractController
{
#[Route('/', name: 'app_project')]
public function index(EntityManagerInterface $entityManager): Response
{
$repository = $entityManager->getRepository(Project::class);
$projects = $repository->findAll();
$this->addFlash(
'info',
sprintf('%s projet%s trouvé%s', count($projects), (count($projects) > 1 ? 's' : ''), (count($projects) > 1 ? 's' : ''))
);
return $this->render('project/index.html.twig', [
'projects' => $projects,
]);
}
#[Route('/create', name: 'app_project_create')]
public function create(Request $request, EntityManagerInterface $entityManager): Response
{
$project = new Project();
$createForm = $this->createForm(ProjectType::class, $project);
$createForm->add('submit', SubmitType::class, [
'label' => 'Créer',
]);
$createForm->handleRequest($request);
if ($createForm->isSubmitted() and $createForm->isValid()) {
$project = $createForm->getData();
try {
$entityManager->persist($project);
$entityManager->flush();
$this->addFlash(
'success',
'Projet créé !'
);
return $this->redirectToRoute('app_project');
} catch (\Exception $exception) {
$this->addFlash(
'danger',
'Impossible de créer le projet !'
);
}
}
return $this->render('project/create.html.twig', [
'create_form' => $createForm,
]);
}
#[Route('/show/{slug}', name: 'app_project_show')]
public function show(EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Project::class);
$project = $repository->findOneBySlug($slug);
if (!$project) {
$this->addFlash(
'warning',
'Projet non trouvé !'
);
return $this->redirectToRoute('app_project');
}
return $this->render('project/show.html.twig', [
'project' => $project,
]);
}
#[Route('/update/{slug}', name: 'app_project_update')]
public function update(Request $request, EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Project::class);
$project = $repository->findOneBySlug($slug);
if (!$project) {
$this->addFlash(
'warning',
'Projet non trouvé !'
);
return $this->redirectToRoute('app_project');
}
$updateForm = $this->createForm(ProjectType::class, $project);
$updateForm->add('submit', SubmitType::class, [
'label' => 'Modifier',
]);
$updateForm->handleRequest($request);
if ($updateForm->isSubmitted() and $updateForm->isValid()) {
$project = $updateForm->getData();
try {
$entityManager->persist($project);
$entityManager->flush();
$this->addFlash(
'success',
'Projet modifié !'
);
return $this->redirectToRoute('app_project');
} catch (\Exception $exception) {
$this->addFlash(
'danger',
'Impossible de mopdifier le projet !'
);
}
}
return $this->render('project/update.html.twig', [
'project' => $project,
'update_form' => $updateForm,
]);
}
#[Route('/remove/{slug}', name: 'app_project_remove')]
public function remove(EntityManagerInterface $entityManager, $slug): Response
{
$repository = $entityManager->getRepository(Project::class);
$project = $repository->findOneBySlug($slug);
if (!$project) {
$this->addFlash(
'warning',
'Projet non trouvé !'
);
return $this->redirectToRoute('app_project');
}
try {
$entityManager->remove($project);
$entityManager->flush();
$this->addFlash(
'success',
'Projet supprimé !'
);
return $this->redirectToRoute('app_project');
} catch (\Exception $exception) {
$this->addFlash(
'danger',
'Impossible de supprimer le projet !'
);
}
return $this->redirectToRoute('app_project');
}
}

+ 0
- 0
src/Entity/.gitignore View File


+ 62
- 0
src/Entity/Project.php View File

@ -0,0 +1,62 @@
<?php
namespace App\Entity;
use App\Repository\ProjectRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
#[ORM\Entity(repositoryClass: ProjectRepository::class)]
class Project
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $description = null;
#[ORM\Column(length: 255, unique: true)]
#[Gedmo\Slug(fields: ['name'])]
private ?string $slug = null;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): static
{
$this->description = $description;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
}

+ 31
- 0
src/Form/ProjectType.php View File

@ -0,0 +1,31 @@
<?php
namespace App\Form;
use App\Entity\Project;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProjectType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', null, [
'label' => 'Nom',
])
->add('description', null, [
'label' => 'Description',
'help' => 'On peut mettre du Markdown ici…',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Project::class,
]);
}
}

+ 0
- 0
src/Repository/.gitignore View File


+ 43
- 0
src/Repository/ProjectRepository.php View File

@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\Project;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Project>
*/
class ProjectRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Project::class);
}
// /**
// * @return Project[] Returns an array of Project objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('p')
// ->andWhere('p.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('p.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Project
// {
// return $this->createQueryBuilder('p')
// ->andWhere('p.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

+ 64
- 0
symfony.lock View File

@ -1,4 +1,43 @@
{ {
"doctrine/doctrine-bundle": {
"version": "2.12",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.12",
"ref": "7266981c201efbbe02ae53c87f8bb378e3f825ae"
},
"files": [
"config/packages/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"stof/doctrine-extensions-bundle": {
"version": "1.12",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "1.2",
"ref": "e805aba9eff5372e2d149a9ff56566769e22819d"
},
"files": [
"config/packages/stof_doctrine_extensions.yaml"
]
},
"symfony/asset-mapper": { "symfony/asset-mapper": {
"version": "7.1", "version": "7.1",
"recipe": { "recipe": {
@ -104,6 +143,31 @@
"templates/base.html.twig" "templates/base.html.twig"
] ]
}, },
"symfony/validator": {
"version": "7.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
},
"files": [
"config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "7.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.1",
"ref": "e42b3f0177df239add25373083a564e5ead4e13a"
},
"files": [
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
},
"twig/extra-bundle": { "twig/extra-bundle": {
"version": "v3.10.0" "version": "v3.10.0"
} }


+ 7
- 0
templates/_footer.html.twig View File

@ -0,0 +1,7 @@
<div class="container">
<div class="row bg-body-tertiary border-top p-2">
<div class="col">
<p class="text-muted mb-0"></p>
</div>
</div>
</div>

+ 6
- 25
templates/_header.html.twig View File

@ -1,37 +1,18 @@
<header> <header>
<nav class="navbar navbar-expand-lg bg-body-tertiary"> <nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<a class="navbar-brand" href="{{ path('app_home') }}">{{ title }}</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<div class="collapse navbar-collapse" id="navbar">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> <ul class="navbar-nav me-auto mb-2 mb-lg-0">
{% for item in menu.header %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled" aria-disabled="true">Disabled</a>
<a {% if app.request.attributes.get('_route') == item.route %}class="nav-link active" aria-current="page"{% else %}class="nav-link"{% endif %} href="{{ path(item.route) }}">{{ item.label }}</a>
</li> </li>
{% endfor %}
</ul> </ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div> </div>
</div> </div>
</nav> </nav>


+ 33
- 3
templates/base.html.twig View File

@ -13,9 +13,39 @@
</head> </head>
<body> <body>
{% block body %} {% block body %}
{% block header %}{% include '_header.html.twig' %}{% endblock %}
{% block main %}{% endblock %}
{% block footer %}{% endblock %}
<header>{% block header %}{% include '_header.html.twig' %}{% endblock %}</header>
<main>
<div class="container my-3">
<div class="row">
<div class="col mb-3">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
{% block breadcrumb %}{% endblock %}
</ol>
</nav>
</div>
</div>
<div class="row">
<div class="col mb-3">
<h1>{% block page_title %}{% endblock %}</h1>
</div>
</div>
<div class="row">
<div class="col mb-3">
{% for label, messages in app.flashes %}
{% for message in messages %}
<div class="alert alert-{{ label }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endfor %}
</div>
</div>{% block page_content %}
{% endblock %}
</div>
</main>
<footer>{% block footer %}{% include '_footer.html.twig' %}{% endblock %}</footer>
{% endblock %} {% endblock %}
</body> </body>
</html> </html>

+ 0
- 1
templates/home/base.html.twig View File

@ -1 +0,0 @@
{% extends 'base.html.twig' %}

+ 8
- 2
templates/home/index.html.twig View File

@ -1,5 +1,11 @@
{% extends 'home/base.html.twig' %}
{% extends 'base.html.twig' %}
{% block main %} {% block main %}
home
<div class="container">
<div class="row">
<div class="col">
ici la page d’accueil
</div>
</div>
</div>
{% endblock %} {% endblock %}

+ 12
- 0
templates/project/create.html.twig View File

@ -0,0 +1,12 @@
{% extends 'base.html.twig' %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{{ path('app_project') }}">Projets</a></li>
<li class="breadcrumb-item"><a href="{{ path('app_project_create') }}">Créer un nouveau projet</a></li>
{% endblock %}
{% block page_title %}Créer un nouveau projet{% endblock %}
{% block page_content %}
{{ form(create_form) }}
{% endblock %}

+ 31
- 0
templates/project/index.html.twig View File

@ -0,0 +1,31 @@
{% extends 'base.html.twig' %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{{ path('app_project') }}">Projets</a></li>
{% endblock %}
{% block page_title %}Projets{% endblock %}
{% block page_content %}
<div class="row">
<div class="col mb-3">
<a href="{{ path('app_project_create') }}" class="btn btn-primary">Créer un projet</a>
</div>
</div>
{% if projects is not empty %}
<div class="row">
{% for project in projects %}
<div class="col col-md-4 mb-3">
<div class="card h-100">
<div class="card-body">
<h2 class="card-title">{{ project.name }}</h2>
{% if project.description %}<p class="card-text">{{ project.description|markdown_to_html }}</p>{% endif %}
<a href="{{ path('app_project_show', {'slug': project.slug}) }}" class="btn btn-primary">Voir</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% endblock %}

+ 21
- 0
templates/project/show.html.twig View File

@ -0,0 +1,21 @@
{% extends 'base.html.twig' %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{{ path('app_project') }}">Projets</a></li>
<li class="breadcrumb-item"><a href="{{ path('app_project_show', {'slug': project.slug}) }}">Projet {{ project.name }}</a></li>
{% endblock %}
{% block page_title %}Projet {{ project.name }}{% endblock %}
{% block page_content %}
<div class="row">
<div class="col mb-3">
<a href="{{ path('app_project_update', {'slug': project.slug}) }}" class="btn btn-primary">Modifier le projet</a>
<a href="{{ path('app_project_remove', {'slug': project.slug}) }}" class="btn btn-primary">Supprimer le projet</a>
</div>
</div>
<div class="row">
<div class="col mb-3 lead">{{ project.description|markdown_to_html }}</div>
</div>
{% endblock %}

+ 12
- 0
templates/project/update.html.twig View File

@ -0,0 +1,12 @@
{% extends 'base.html.twig' %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{{ path('app_project') }}">Projets</a></li>
<li class="breadcrumb-item"><a href="{{ path('app_project_create') }}">Modifier le projet {{ project.name }}</a></li>
{% endblock %}
{% block page_title %}Modifier le projet {{ project.name }}{% endblock %}
{% block page_content %}
{{ form(update_form) }}
{% endblock %}

Loading…
Cancel
Save