diff --git a/Dockerfile b/Dockerfile index d6515d8..1866712 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1 +1,4 @@ FROM registry.caldwell.digital/library/php:8.4-apache + +COPY ./bash/vhost.conf /etc/apache2/sites-enabled/vhost.conf +RUN rm /etc/apache2/sites-enabled/000-default.conf diff --git a/assets/app.js b/assets/app.js index 8725cc5..4ca76d8 100644 --- a/assets/app.js +++ b/assets/app.js @@ -8,3 +8,13 @@ import './bootstrap.js'; import './styles/app.css'; console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉'); + +let alert = document.querySelector('.alert'); +var observer = new MutationObserver(function(mutations) { + if (document.contains(alert)) { + observer.disconnect(); + } +}); + +observer.observe(document, {attributes: false, childList: true, characterData: false, subtree:true}); + diff --git a/assets/controllers.json b/assets/controllers.json index b980571..71abe9d 100644 --- a/assets/controllers.json +++ b/assets/controllers.json @@ -8,6 +8,16 @@ "@symfony/ux-live-component/dist/live.min.css": true } } + }, + "@symfony/ux-turbo": { + "turbo-core": { + "enabled": true, + "fetch": "eager" + }, + "mercure-turbo-stream": { + "enabled": true, + "fetch": "eager" + } } }, "entrypoints": [] diff --git a/assets/controllers/alert_controller.js b/assets/controllers/alert_controller.js new file mode 100644 index 0000000..733b017 --- /dev/null +++ b/assets/controllers/alert_controller.js @@ -0,0 +1,18 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + connect() { + let timer = setTimeout(() => { + this.element.remove(); + }, + "3000" + ); + + this.element.addEventListener('mouseout', () => timer = setTimeout(() => { + this.element.remove(); + }, + "3000" + )); + this.element.addEventListener('mouseover', () => clearTimeout(timer)); + } +} diff --git a/bash/vhost.conf b/bash/vhost.conf index b40ca1c..8348d25 100755 --- a/bash/vhost.conf +++ b/bash/vhost.conf @@ -4,6 +4,11 @@ DocumentRoot /var/www/public DirectoryIndex /index.php + + ProxyPass http://mercure:80/ + ProxyPassReverse http://mercure:80/ + + AllowOverride None Order Allow,Deny diff --git a/compose.yml b/compose.yml index 0c1ed50..5a4b7fc 100755 --- a/compose.yml +++ b/compose.yml @@ -24,6 +24,24 @@ services: - ./var/download:/var/download command: php ./bin/console messenger:consume async -v --time-limit=3600 --limit=10 + mercure: + image: dunglas/mercure + restart: unless-stopped + ports: + - "3000:80" + environment: + SERVER_NAME: ':80' + MERCURE_PUBLISHER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!' + MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!' + MERCURE_EXTRA_DIRECTIVES: | + cors_origins * + anonymous + command: /usr/bin/caddy run --config /etc/caddy/dev.Caddyfile + volumes: + - mercure_data:/data + - mercure_config:/config + + database: image: mariadb:10.11.2 ports: @@ -43,3 +61,5 @@ services: volumes: mysql: + mercure_data: + mercure_config: diff --git a/composer.json b/composer.json index f3e544a..7a40359 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "symfony/flex": "^2", "symfony/form": "7.2.*", "symfony/framework-bundle": "7.2.*", + "symfony/mercure-bundle": "^0.3.9", "symfony/messenger": "7.2.*", "symfony/runtime": "7.2.*", "symfony/security-bundle": "7.2.*", @@ -30,6 +31,7 @@ "symfony/twig-bundle": "7.2.*", "symfony/ux-icons": "^2.24", "symfony/ux-live-component": "^2.24", + "symfony/ux-turbo": "^2.24", "symfony/ux-twig-component": "^2.24", "symfony/yaml": "7.2.*", "symfonycasts/tailwind-bundle": "^0.10.0", diff --git a/composer.lock b/composer.lock index 2d4799d..f3da352 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "09d927397449bd08c7c2b96e35d2bd60", + "content-hash": "740c22e45c004ece09230b2bb113e949", "packages": [ { "name": "1tomany/data-uri", @@ -1421,6 +1421,79 @@ }, "time": "2025-01-24T11:45:48+00:00" }, + { + "name": "lcobucci/jwt", + "version": "5.5.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "a835af59b030d3f2967725697cf88300f579088e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e", + "reference": "a835af59b030d3f2967725697cf88300f579088e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-sodium": "*", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "psr/clock": "^1.0" + }, + "require-dev": { + "infection/infection": "^0.29", + "lcobucci/clock": "^3.2", + "lcobucci/coding-standard": "^11.0", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.10.7", + "phpstan/phpstan-deprecation-rules": "^1.1.3", + "phpstan/phpstan-phpunit": "^1.3.10", + "phpstan/phpstan-strict-rules": "^1.5.0", + "phpunit/phpunit": "^11.1" + }, + "suggest": { + "lcobucci/clock": ">= 3.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "support": { + "issues": "https://github.com/lcobucci/jwt/issues", + "source": "https://github.com/lcobucci/jwt/tree/5.5.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2025-01-26T21:29:45+00:00" + }, { "name": "nihilarr/parse-torrent-name", "version": "v0.0.1", @@ -2548,6 +2621,62 @@ }, "time": "2023-04-04T09:50:52+00:00" }, + { + "name": "psr/link", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "84b159194ecfd7eaa472280213976e96415433f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7", + "reference": "84b159194ecfd7eaa472280213976e96415433f7", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "suggest": { + "fig/link-util": "Provides some useful PSR-13 utilities" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for HTTP links", + "homepage": "https://github.com/php-fig/link", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "support": { + "source": "https://github.com/php-fig/link/tree/2.0.1" + }, + "time": "2021-03-11T23:00:27+00:00" + }, { "name": "psr/log", "version": "3.0.2", @@ -4656,6 +4785,173 @@ ], "time": "2025-03-28T13:32:50+00:00" }, + { + "name": "symfony/mercure", + "version": "v0.6.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/mercure.git", + "reference": "304cf84609ef645d63adc65fc6250292909a461b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mercure/zipball/304cf84609ef645d63adc65fc6250292909a461b", + "reference": "304cf84609ef645d63adc65fc6250292909a461b", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/deprecation-contracts": "^2.0|^3.0|^4.0", + "symfony/http-client": "^4.4|^5.0|^6.0|^7.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0|^7.0", + "symfony/polyfill-php80": "^1.22", + "symfony/web-link": "^4.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "lcobucci/jwt": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0|^7.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0|^7.0", + "symfony/phpunit-bridge": "^5.2|^6.0|^7.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0|^7.0", + "twig/twig": "^2.0|^3.0|^4.0" + }, + "suggest": { + "symfony/stopwatch": "Integration with the profiler performances" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/dunglas/mercure", + "name": "dunglas/mercure" + }, + "branch-alias": { + "dev-main": "0.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Mercure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Mercure Component", + "homepage": "https://symfony.com", + "keywords": [ + "mercure", + "push", + "sse", + "updates" + ], + "support": { + "issues": "https://github.com/symfony/mercure/issues", + "source": "https://github.com/symfony/mercure/tree/v0.6.5" + }, + "funding": [ + { + "url": "https://github.com/dunglas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/mercure", + "type": "tidelift" + } + ], + "time": "2024-04-08T12:51:34+00:00" + }, + { + "name": "symfony/mercure-bundle", + "version": "v0.3.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/mercure-bundle.git", + "reference": "77435d740b228e9f5f3f065b6db564f85f2cdb64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mercure-bundle/zipball/77435d740b228e9f5f3f065b6db564f85f2cdb64", + "reference": "77435d740b228e9f5f3f065b6db564f85f2cdb64", + "shasum": "" + }, + "require": { + "lcobucci/jwt": "^3.4|^4.0|^5.0", + "php": ">=7.1.3", + "symfony/config": "^4.4|^5.0|^6.0|^7.0", + "symfony/dependency-injection": "^4.4|^5.4|^6.0|^7.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0|^7.0", + "symfony/mercure": "^0.6.1", + "symfony/web-link": "^4.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.3.7|^5.0|^6.0|^7.0", + "symfony/stopwatch": "^4.3.7|^5.0|^6.0|^7.0", + "symfony/ux-turbo": "*", + "symfony/var-dumper": "^4.3.7|^5.0|^6.0|^7.0" + }, + "suggest": { + "symfony/messenger": "To use the Messenger integration" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MercureBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony MercureBundle", + "homepage": "https://symfony.com", + "keywords": [ + "mercure", + "push", + "sse", + "updates" + ], + "support": { + "issues": "https://github.com/symfony/mercure-bundle/issues", + "source": "https://github.com/symfony/mercure-bundle/tree/v0.3.9" + }, + "funding": [ + { + "url": "https://github.com/dunglas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/mercure-bundle", + "type": "tidelift" + } + ], + "time": "2024-05-31T09:07:18+00:00" + }, { "name": "symfony/messenger", "version": "v7.2.5", @@ -7070,6 +7366,104 @@ ], "time": "2025-03-12T08:41:47+00:00" }, + { + "name": "symfony/ux-turbo", + "version": "v2.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/ux-turbo.git", + "reference": "22954300bd0b01ca46f17c7890ea15138d9cf67f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/22954300bd0b01ca46f17c7890ea15138d9cf67f", + "reference": "22954300bd0b01ca46f17c7890ea15138d9cf67f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/stimulus-bundle": "^2.9.1" + }, + "conflict": { + "symfony/flex": "<1.13" + }, + "require-dev": { + "dbrekelmans/bdi": "dev-main", + "doctrine/doctrine-bundle": "^2.4.3", + "doctrine/orm": "^2.8 | 3.0", + "phpstan/phpstan": "^1.10", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/debug-bundle": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/mercure-bundle": "^0.3.7", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/panther": "^2.1", + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|6.3.*|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/ux-twig-component": "^2.21", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "url": "https://github.com/symfony/ux", + "name": "symfony/ux" + } + }, + "autoload": { + "psr-4": { + "Symfony\\UX\\Turbo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Hotwire Turbo integration for Symfony", + "homepage": "https://symfony.com", + "keywords": [ + "hotwire", + "javascript", + "mercure", + "symfony-ux", + "turbo", + "turbo-stream" + ], + "support": { + "source": "https://github.com/symfony/ux-turbo/tree/v2.24.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T17:29:20+00:00" + }, { "name": "symfony/ux-twig-component", "version": "v2.24.0", @@ -7409,6 +7803,89 @@ ], "time": "2025-03-13T12:21:46+00:00" }, + { + "name": "symfony/web-link", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-link.git", + "reference": "f537556a885e14a1d28f6c759d41e57e93d0a532" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-link/zipball/f537556a885e14a1d28f6c759d41e57e93d0a532", + "reference": "f537556a885e14a1d28f6c759d41e57e93d0a532", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/link": "^1.1|^2.0" + }, + "conflict": { + "symfony/http-kernel": "<6.4" + }, + "provide": { + "psr/link-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/http-kernel": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\WebLink\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages links between resources", + "homepage": "https://symfony.com", + "keywords": [ + "dns-prefetch", + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" + ], + "support": { + "source": "https://github.com/symfony/web-link/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, { "name": "symfony/yaml", "version": "v7.2.5", diff --git a/config/bundles.php b/config/bundles.php index 2adc20d..0fa81a3 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -14,4 +14,6 @@ return [ Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true], + Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true], + Symfony\UX\Turbo\TurboBundle::class => ['all' => true], ]; diff --git a/config/packages/mercure.yaml b/config/packages/mercure.yaml new file mode 100644 index 0000000..f2a7395 --- /dev/null +++ b/config/packages/mercure.yaml @@ -0,0 +1,8 @@ +mercure: + hubs: + default: + url: '%env(MERCURE_URL)%' + public_url: '%env(MERCURE_PUBLIC_URL)%' + jwt: + secret: '%env(MERCURE_JWT_SECRET)%' + publish: '*' diff --git a/importmap.php b/importmap.php index 176ca69..73f4fcf 100644 --- a/importmap.php +++ b/importmap.php @@ -25,4 +25,7 @@ return [ '@symfony/ux-live-component' => [ 'path' => './vendor/symfony/ux-live-component/assets/dist/live_controller.js', ], + '@hotwired/turbo' => [ + 'version' => '7.3.0', + ], ]; diff --git a/src/Controller/AlertController.php b/src/Controller/AlertController.php new file mode 100644 index 0000000..91204ff --- /dev/null +++ b/src/Controller/AlertController.php @@ -0,0 +1,37 @@ +renderer->render('broadcast/Alert.html.twig', [ + 'alert_id' => 1, + 'title' => 'Added to queue', + 'message' => 'This is a testy test!', + ]) + ); + + $this->hub->publish($update); + return $this->json([ + 'Success' => 'Published' + ]); + } +} diff --git a/src/Twig/Components/Alert.php b/src/Twig/Components/Alert.php new file mode 100644 index 0000000..fd8763f --- /dev/null +++ b/src/Twig/Components/Alert.php @@ -0,0 +1,12 @@ + + + diff --git a/templates/broadcast/Download.stream.html.twig b/templates/broadcast/Download.stream.html.twig new file mode 100644 index 0000000..bd2636e --- /dev/null +++ b/templates/broadcast/Download.stream.html.twig @@ -0,0 +1,55 @@ +{# Learn how to use Turbo Streams: https://github.com/symfony/ux-turbo#broadcast-doctrine-entities-update #} +{% block create %} + + + +{% endblock %} + +{% block update %} + {% if entity.status != "Complete" %} + + + + {% else %} + + + + + + + + + + + {% endif %} +{% endblock %} + +{% block remove %} + + +{% endblock %} diff --git a/templates/components/Alert.html.twig b/templates/components/Alert.html.twig new file mode 100644 index 0000000..f1a2cfd --- /dev/null +++ b/templates/components/Alert.html.twig @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/templates/components/Header.html.twig b/templates/components/Header.html.twig index 6e00af9..3cef743 100644 --- a/templates/components/Header.html.twig +++ b/templates/components/Header.html.twig @@ -12,4 +12,11 @@ +
+
+
    + +
+
+