From b29dbbe3d72b3efd78990e3397f708f73ab2bc00 Mon Sep 17 00:00:00 2001 From: Ploush Date: Sat, 9 May 2026 17:07:31 +0200 Subject: [PATCH] add: new page (maps) --- app/.gitignore | 2 - app/assets/images/logo-dark.svg | 79 ++++++++++++++++++++ app/assets/images/logo-light.svg | 79 ++++++++++++++++++++ app/assets/styles/maps/index.css | 66 ++++++++++++++++ app/assets/styles/partials/header.css | 50 ++++++++----- app/src/Controller/MapsController.php | 60 +++++++++++++++ app/src/Controller/ModpackController.php | 5 ++ app/src/Form/Modpack/ModpackDownloadType.php | 8 +- app/templates/maps/index.html.twig | 36 +++++++++ app/templates/modpack/nomodpack.html.twig | 20 +++++ app/templates/partials/_header.html.twig | 7 +- compose.yml | 32 -------- docker-compose.yml | 26 +++++++ docker/apache/Dockerfile | 6 ++ docker/apache/opcache.ini | 7 ++ stack.env.example | 6 ++ 16 files changed, 431 insertions(+), 58 deletions(-) create mode 100644 app/assets/images/logo-dark.svg create mode 100644 app/assets/images/logo-light.svg create mode 100644 app/assets/styles/maps/index.css create mode 100644 app/src/Controller/MapsController.php create mode 100644 app/templates/maps/index.html.twig create mode 100644 app/templates/modpack/nomodpack.html.twig delete mode 100644 compose.yml create mode 100644 docker-compose.yml create mode 100644 docker/apache/opcache.ini create mode 100644 stack.env.example diff --git a/app/.gitignore b/app/.gitignore index b7bfae0..4de87ab 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,7 +1,5 @@ .idea - - ###> symfony/framework-bundle ### /.env.local /.env.local.php diff --git a/app/assets/images/logo-dark.svg b/app/assets/images/logo-dark.svg new file mode 100644 index 0000000..847d646 --- /dev/null +++ b/app/assets/images/logo-dark.svg @@ -0,0 +1,79 @@ + + + Ploush — logo theme sombre + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/logo-light.svg b/app/assets/images/logo-light.svg new file mode 100644 index 0000000..b9ddcd1 --- /dev/null +++ b/app/assets/images/logo-light.svg @@ -0,0 +1,79 @@ + + + Ploush — logo theme clair + + + + + + + + + + + + + + + + + diff --git a/app/assets/styles/maps/index.css b/app/assets/styles/maps/index.css new file mode 100644 index 0000000..a4b3cd1 --- /dev/null +++ b/app/assets/styles/maps/index.css @@ -0,0 +1,66 @@ +/* ════════════════════════════════════════════════════════════════ + Maps Index Styles + ════════════════════════════════════════════════════════════════ */ + +.maps-list { + display: flex; + flex-direction: column; + gap: 1rem; + width: 100%; + margin-top: 1.5rem; +} + +.maps { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 1rem; + /*background: var(--nav-bg-light);*/ + border: 1px solid var(--border-light); + border-radius: 10px; + transition: background var(--duration-slow) ease, border-color var(--duration-slow) ease, box-shadow var(--duration-slow) ease; +} + +[data-theme="dark"] .maps { + background: var(--nav-bg-dark); + border-color: var(--border-dark); +} + +.maps-name { + font-weight: 600; + font-size: 1rem; + color: var(--text-light); + margin: 0; + transition: color var(--duration-slow) ease; + flex: 1; +} + +[data-theme="dark"] .maps-name { + color: var(--text-dark); +} + +.maps-btn { + display: inline-block; + padding: 0.6rem 1.2rem; + background: var(--violet); + color: white; + text-decoration: none; + border-radius: 8px; + font-weight: 600; + font-size: 0.9rem; + text-align: center; + transition: background var(--duration-normal) ease, transform var(--duration-fast) ease; + white-space: nowrap; + flex-shrink: 0; +} + +.maps-btn:hover { + transform: translateY(-2px); +} + +[data-theme="dark"] .maps-btn { + color: white; +} + diff --git a/app/assets/styles/partials/header.css b/app/assets/styles/partials/header.css index 0554d16..1fe432f 100644 --- a/app/assets/styles/partials/header.css +++ b/app/assets/styles/partials/header.css @@ -43,29 +43,41 @@ header { gap: 0.55rem; text-decoration: none; flex-shrink: 0; + height: 40px; } -.logo-mark { - width: 32px; - height: 32px; - background: var(--violet); - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - transition: transform var(--duration-medium) ease, box-shadow var(--duration-medium) ease; + +.logo img { + height: 100%; + width: auto; + transition: opacity var(--duration-slow) ease, display var(--duration-slow) ease; } -.logo:hover .logo-mark { - transform: rotate(-6deg) scale(1.08); - box-shadow: 0 0 18px var(--violet-glow); + +/* Afficher le logo clair par défaut, masquer le logo sombre */ +.logo .logo-light { + opacity: 1; } -.logo-name { - font-weight: 800; - font-size: 1.05rem; - letter-spacing: -0.02em; - color: var(--text-light); - transition: color var(--duration-slow) ease; +.logo .logo-dark { + opacity: 0; + display: none; +} + +/* En mode sombre, afficher le logo sombre et masquer le logo clair */ +[data-theme="dark"] .logo .logo-light { + opacity: 0; + display: none; +} +[data-theme="dark"] .logo .logo-dark { + opacity: 1; + display: block; +} + +/* Hover effect */ +.logo:hover { + transform: scale(1.05); +} +.logo:hover img { + filter: drop-shadow(0 0 8px var(--violet-glow)); } -[data-theme="dark"] .logo-name { color: var(--text-dark); } /* ── NAVIGATION ────────────────────────────────────────────────── */ header nav { diff --git a/app/src/Controller/MapsController.php b/app/src/Controller/MapsController.php new file mode 100644 index 0000000..08ed03d --- /dev/null +++ b/app/src/Controller/MapsController.php @@ -0,0 +1,60 @@ +getParameter('kernel.project_dir') . '/public/uploads/maps'; + + // Créer le répertoire s'il n'existe pas + if (!is_dir($mapsDir)) { + mkdir($mapsDir, 0755, true); + } + + // Récupérer la liste des fichiers + $files = []; + if (is_dir($mapsDir)) { + $scandir = scandir($mapsDir); + foreach ($scandir as $file) { + if ($file !== '.' && $file !== '..' && is_file($mapsDir . '/' . $file)) { + $files[] = [ + 'filename' => $file, + 'display' => pathinfo($file, PATHINFO_FILENAME) + ]; + } + } + } + usort($files, fn($a, $b) => strcmp($a['filename'], $b['filename'])); + + return $this->render('maps/index.html.twig', [ + 'files' => $files, + ]); + } + + #[Route('/download/{filename}', name: 'app_maps_download')] + public function download(string $filename): Response + { + $mapsDir = $this->getParameter('kernel.project_dir') . '/public/uploads/maps'; + $filePath = $mapsDir . '/' . $filename; + + // Vérifier que le fichier existe et est dans le bon répertoire + if (!file_exists($filePath) || !is_file($filePath) || realpath($filePath) === false) { + throw $this->createNotFoundException('Le fichier n\'existe pas.'); + } + + // Vérifier que le chemin réel est bien dans le répertoire uploads/maps + if (strpos(realpath($filePath), realpath($mapsDir)) !== 0) { + throw $this->createAccessDeniedException('Accès refusé.'); + } + + return $this->file($filePath); + } +} diff --git a/app/src/Controller/ModpackController.php b/app/src/Controller/ModpackController.php index 5a2afd1..171974e 100644 --- a/app/src/Controller/ModpackController.php +++ b/app/src/Controller/ModpackController.php @@ -35,6 +35,11 @@ final class ModpackController extends AbstractController $modpack = $modpacks[0] ?? null; } + // Si aucun modpack n'est disponible, afficher le template approprié + if (!$modpack) { + return $this->render('modpack/nomodpack.html.twig'); + } + $form = $this->createForm(ModpackDownloadType::class, $modpack); return $this->render('modpack/index.html.twig', [ diff --git a/app/src/Form/Modpack/ModpackDownloadType.php b/app/src/Form/Modpack/ModpackDownloadType.php index f8674ea..355f4e7 100644 --- a/app/src/Form/Modpack/ModpackDownloadType.php +++ b/app/src/Form/Modpack/ModpackDownloadType.php @@ -15,13 +15,13 @@ class ModpackDownloadType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { - /** @var Modpack $modpack */ - $modpack = $options['data']; + /** @var Modpack|null $modpack */ + $modpack = $options['data'] ?? null; - $optionnels = $modpack->getConstitues() + $optionnels = $modpack?->getConstitues() ->filter(fn(Constitue $c) => $c->isOptionnel()) ->map(fn(Constitue $c) => $c->getMod()) - ->getValues(); + ->getValues() ?? []; $builder ->add('mods_optionnels', EntityType::class, [ diff --git a/app/templates/maps/index.html.twig b/app/templates/maps/index.html.twig new file mode 100644 index 0000000..3744b9e --- /dev/null +++ b/app/templates/maps/index.html.twig @@ -0,0 +1,36 @@ +{% extends 'base.html.twig' %} + +{% block title %} Maps {% endblock %} + +{% block stylesheets %} + {{ parent() }} + + + +{% endblock %} + +{% block main %} +
+
+

Télécharger les Maps

+
+ +
+

Liste des maps :

+ {% if files is not empty %} +
+ {% for file in files %} +
+

{{ file.display }}

+ + Télécharger + +
+ {% endfor %} +
+ {% else %} +

Aucune map n'est actuellement disponible au téléchargement.

+ {% endif %} +
+
+{% endblock %} diff --git a/app/templates/modpack/nomodpack.html.twig b/app/templates/modpack/nomodpack.html.twig new file mode 100644 index 0000000..5f9ccf1 --- /dev/null +++ b/app/templates/modpack/nomodpack.html.twig @@ -0,0 +1,20 @@ +{% extends 'base.html.twig' %} + +{% block title %} Modpack {% endblock %} + +{% block stylesheets %} + {{ parent() }} + + +{% endblock %} + +{% block main %} +
+
+

Modpack indisponible

+

Aucun modpack n'est actuellement disponible au téléchargement.

+

Veuillez réessayer plus tard.

+
+
+{% endblock %} + diff --git a/app/templates/partials/_header.html.twig b/app/templates/partials/_header.html.twig index f27167b..73e6521 100644 --- a/app/templates/partials/_header.html.twig +++ b/app/templates/partials/_header.html.twig @@ -11,7 +11,8 @@
diff --git a/compose.yml b/compose.yml deleted file mode 100644 index 083040a..0000000 --- a/compose.yml +++ /dev/null @@ -1,32 +0,0 @@ -# ============================================================ -# Stack Symfony — minecraft.ploush.top -# Traefik (rvproxy) + PostgreSQL (db_networking) externes -# ============================================================ - -services: - - apache: - image: ghcr.io/ploush/mcserverwebsite:latest - container_name: apache_symfony - restart: unless-stopped - environment: - APP_ENV: prod - networks: - - rvproxy - - localdb - labels: - - "traefik.enable=true" - - "traefik.docker.network=rvproxy" - # Routeur - - "traefik.http.routers.symfony.rule=Host(`minecraft.ploush.top`)" - - "traefik.http.routers.symfony.entrypoints=websecure" - - "traefik.http.routers.symfony.tls=true" - - "traefik.http.routers.symfony.tls.certresolver=myresolver" - # Service interne (port Apache) - - "traefik.http.services.symfony.loadbalancer.server.port=80" - -networks: - rvproxy: - external: true - localdb: - external: true diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..77531f7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +services: + app: + image: ghcr.io/ploush/mcserverwebsite:latest + restart: unless-stopped + env_file: + - stack.env + labels: + - "traefik.enable=true" + - "traefik.http.routers.mcwebsite.rule=Host(`minecraft.ploush.top`)" + - "traefik.http.routers.mcwebsite.entrypoints=websecure" + - "traefik.http.routers.mcwebsite.tls.certresolver=myresolver" + - "traefik.http.services.mcwebsite.loadbalancer.server.port=80" + volumes: + - uploads:/var/www/html/public/uploads + networks: + - localdb + - rvproxy + +volumes: + uploads: + +networks: + localdb: + external: true + rvproxy: + external: true diff --git a/docker/apache/Dockerfile b/docker/apache/Dockerfile index c783c61..68b8ccb 100644 --- a/docker/apache/Dockerfile +++ b/docker/apache/Dockerfile @@ -37,11 +37,17 @@ RUN composer install --no-dev --optimize-autoloader --no-scripts --no-interactio # Puis le reste du code COPY app/ . +# ── Assets ────────────────────────────────────────────── +RUN APP_ENV=prod php bin/console asset-map:compile + # ── Droits ────────────────────────────────────────────────── RUN mkdir -p /var/www/html/var \ && chown -R www-data:www-data /var/www/html \ && chmod -R 755 /var/www/html/var +# ── Config OPcache ─────────────────────────────────────── +COPY docker/apache/opcache.ini /usr/local/etc/php/conf.d/opcache.ini + # ── Config Apache ──────────────────────────────────────────── COPY docker/apache/symfony.conf /etc/apache2/sites-enabled/000-default.conf diff --git a/docker/apache/opcache.ini b/docker/apache/opcache.ini new file mode 100644 index 0000000..45bb3f3 --- /dev/null +++ b/docker/apache/opcache.ini @@ -0,0 +1,7 @@ +opcache.enable=1 +opcache.memory_consumption=256 +opcache.interned_strings_buffer=16 +opcache.max_accelerated_files=20000 +opcache.validate_timestamps=0 +opcache.save_comments=1 +opcache.fast_shutdown=0 diff --git a/stack.env.example b/stack.env.example new file mode 100644 index 0000000..ec325d1 --- /dev/null +++ b/stack.env.example @@ -0,0 +1,6 @@ +APP_ENV=prod +APP_SECRET=changeme_32_chars_random_string +DATABASE_URL=postgresql://USER:PASSWORD@postgres_db:5432/DB_NAME?serverVersion=16 +DEFAULT_URI=https://minecraft.ploush.top +MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 +MAILER_DSN=null://null