From 89fe535109abfffabfce3660e5df2990e552283f Mon Sep 17 00:00:00 2001 From: Babak Alizadeh Date: Fri, 10 Jan 2025 18:03:20 +0000 Subject: [PATCH] work on adding easyadmin --- assets/styles/app.css | 8 + composer.json | 1 + composer.lock | 406 ++++++++++++++++++- config/bundles.php | 2 + config/packages/security.yaml | 8 +- config/packages/twig_component.yaml | 5 + src/Controller/Admin/DashboardController.php | 46 +++ src/Controller/Admin/PostCrudController.php | 28 ++ src/Controller/SecurityController.php | 75 ++++ symfony.lock | 30 ++ templates/base.html.twig | 3 + templates/post/api_docs.html.twig | 3 +- templates/post/guide.html.twig | 7 +- 13 files changed, 613 insertions(+), 9 deletions(-) create mode 100644 config/packages/twig_component.yaml create mode 100644 src/Controller/Admin/DashboardController.php create mode 100644 src/Controller/Admin/PostCrudController.php create mode 100644 src/Controller/SecurityController.php diff --git a/assets/styles/app.css b/assets/styles/app.css index bd26e3c..10b78b6 100644 --- a/assets/styles/app.css +++ b/assets/styles/app.css @@ -19,3 +19,11 @@ a.nav-link:hover { margin-right: auto; margin-left: 0; } + +pre { + border-radius: 0.5rem; + direction: ltr; + background-color: #d6d6df; + padding: 0.9rem 0.8rem; + color: blue; +} diff --git a/composer.json b/composer.json index 05961c6..11d1c4c 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "doctrine/doctrine-bundle": "^2.13", "doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/orm": "^3.3", + "easycorp/easyadmin-bundle": "^4.20", "phpdocumentor/reflection-docblock": "^5.6", "phpstan/phpdoc-parser": "^2.0", "symfony/apache-pack": "^1.0", diff --git a/composer.lock b/composer.lock index 4822fad..abe873f 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": "5f5819efa6fa681303b07a064aeeed86", + "content-hash": "ca772d9929e27f4922e9abb62ac182b7", "packages": [ { "name": "doctrine/cache", @@ -1229,6 +1229,106 @@ }, "time": "2024-10-21T18:21:57+00:00" }, + { + "name": "easycorp/easyadmin-bundle", + "version": "v4.20.8", + "source": { + "type": "git", + "url": "https://github.com/EasyCorp/EasyAdminBundle.git", + "reference": "4fdc48db1c7a15ca8a27ecaeba9cce51c97f1965" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/4fdc48db1c7a15ca8a27ecaeba9cce51c97f1965", + "reference": "4fdc48db1c7a15ca8a27ecaeba9cce51c97f1965", + "shasum": "" + }, + "require": { + "doctrine/doctrine-bundle": "^2.5", + "doctrine/orm": "^2.12|^3.0", + "ext-json": "*", + "php": ">=8.1", + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/deprecation-contracts": "^3.0", + "symfony/doctrine-bridge": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/security-bundle": "^5.4|^6.0|^7.0", + "symfony/string": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/ux-twig-component": "^2.21", + "symfony/validator": "^5.4|^6.0|^7.0", + "twig/extra-bundle": "^3.17", + "twig/html-extra": "^3.17", + "twig/twig": "^3.15" + }, + "require-dev": { + "doctrine/doctrine-fixtures-bundle": "^3.4|3.5.x-dev", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-phpunit": "^1.2", + "phpstan/phpstan-strict-rules": "^1.4", + "phpstan/phpstan-symfony": "^1.2", + "psr/log": "^1.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/debug-bundle": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^6.1|^7.0", + "symfony/process": "^5.4|^6.0|^7.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "EasyCorp\\Bundle\\EasyAdminBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Project Contributors", + "homepage": "https://github.com/EasyCorp/EasyAdminBundle/graphs/contributors" + } + ], + "description": "Admin generator for Symfony applications", + "homepage": "https://github.com/EasyCorp/EasyAdminBundle", + "keywords": [ + "admin", + "backend", + "generator" + ], + "support": { + "issues": "https://github.com/EasyCorp/EasyAdminBundle/issues", + "source": "https://github.com/EasyCorp/EasyAdminBundle/tree/v4.20.8" + }, + "funding": [ + { + "url": "https://github.com/javiereguiluz", + "type": "github" + } + ], + "time": "2025-01-09T20:44:17+00:00" + }, { "name": "egulias/email-validator", "version": "4.0.3", @@ -5380,6 +5480,85 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.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-09T11:45:10+00:00" + }, { "name": "symfony/process", "version": "v7.2.0", @@ -6952,6 +7131,80 @@ ], "time": "2024-12-20T13:38:37+00:00" }, + { + "name": "symfony/uid", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/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/ux-turbo", "version": "v2.22.1", @@ -7050,6 +7303,89 @@ ], "time": "2024-12-05T14:25:02+00:00" }, + { + "name": "symfony/ux-twig-component", + "version": "v2.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/ux-twig-component.git", + "reference": "9b347f6ca2d9e18cee630787f0a6aa453982bf18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/9b347f6ca2d9e18cee630787f0a6aa453982bf18", + "reference": "9b347f6ca2d9e18cee630787f0a6aa453982bf18", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/deprecation-contracts": "^2.2|^3.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "twig/twig": "^3.8" + }, + "conflict": { + "symfony/config": "<5.4.0" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^6.0|^7.0", + "symfony/stimulus-bundle": "^2.9.1", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/webpack-encore-bundle": "^1.15" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "url": "https://github.com/symfony/ux", + "name": "symfony/ux" + } + }, + "autoload": { + "psr-4": { + "Symfony\\UX\\TwigComponent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Twig components for Symfony", + "homepage": "https://symfony.com", + "keywords": [ + "components", + "symfony-ux", + "twig" + ], + "support": { + "source": "https://github.com/symfony/ux-twig-component/tree/v2.22.1" + }, + "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-12-07T18:05:50+00:00" + }, { "name": "symfony/validator", "version": "v7.2.2", @@ -7607,6 +7943,74 @@ ], "time": "2024-09-26T19:22:23+00:00" }, + { + "name": "twig/html-extra", + "version": "v3.18.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/html-extra.git", + "reference": "c63b28e192c1b7c15bb60f81d2e48b140846239a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/html-extra/zipball/c63b28e192c1b7c15bb60f81d2e48b140846239a", + "reference": "c63b28e192c1b7c15bb60f81d2e48b140846239a", + "shasum": "" + }, + "require": { + "php": ">=8.0.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/mime": "^5.4|^6.4|^7.0", + "twig/twig": "^3.13|^4.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Twig\\Extra\\Html\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + } + ], + "description": "A Twig extension for HTML", + "homepage": "https://twig.symfony.com", + "keywords": [ + "html", + "twig" + ], + "support": { + "source": "https://github.com/twigphp/html-extra/tree/v3.18.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2024-12-29T10:29:59+00:00" + }, { "name": "twig/twig", "version": "v3.18.0", diff --git a/config/bundles.php b/config/bundles.php index ffa89b9..1d966f4 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -15,4 +15,6 @@ return [ Symfony\UX\Turbo\TurboBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true], + Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true], + EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true], ]; diff --git a/config/packages/security.yaml b/config/packages/security.yaml index fbfb8ed..009a9f9 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -16,7 +16,13 @@ security: main: lazy: true provider: app_user_provider + form_login: + # "app_login" is the name of the route created previously + login_path: login + check_path: login + logout: + path: logout # activate different ways to authenticate # https://symfony.com/doc/current/security.html#the-firewall @@ -26,7 +32,7 @@ security: # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: - # - { path: ^/admin, roles: ROLE_ADMIN } + - { path: ^/admin, roles: ROLE_ADMIN } # - { path: ^/profile, roles: ROLE_USER } when@test: diff --git a/config/packages/twig_component.yaml b/config/packages/twig_component.yaml new file mode 100644 index 0000000..fd17ac6 --- /dev/null +++ b/config/packages/twig_component.yaml @@ -0,0 +1,5 @@ +twig_component: + anonymous_template_directory: 'components/' + defaults: + # Namespace & directory for components + App\Twig\Components\: 'components/' diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php new file mode 100644 index 0000000..da2c931 --- /dev/null +++ b/src/Controller/Admin/DashboardController.php @@ -0,0 +1,46 @@ +container->get(AdminUrlGenerator::class); + // return $this->redirect($adminUrlGenerator->setController(OneOfYourCrudController::class)->generateUrl()); + + // Option 2. You can make your dashboard redirect to different pages depending on the user + // + // if ('jane' === $this->getUser()->getUsername()) { + // return $this->redirect('...'); + // } + + // Option 3. You can render some custom template to display a proper dashboard with widgets, etc. + // (tip: it's easier if your template extends from @EasyAdmin/page/content.html.twig) + // + // return $this->render('some/path/my-dashboard.html.twig'); + } + + public function configureDashboard(): Dashboard + { + return Dashboard::new() + ->setTitle('داشبورد مدیریت محتوای حسابیکس'); + } + + public function configureMenuItems(): iterable + { + yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home'); + // yield MenuItem::linkToCrud('The Label', 'fas fa-list', EntityClass::class); + } +} diff --git a/src/Controller/Admin/PostCrudController.php b/src/Controller/Admin/PostCrudController.php new file mode 100644 index 0000000..e126abc --- /dev/null +++ b/src/Controller/Admin/PostCrudController.php @@ -0,0 +1,28 @@ +getLastAuthenticationError(); + $lastUsername = $authenticationUtils->getLastUsername(); + + return $this->render('@EasyAdmin/page/login.html.twig', [ + // parameters usually defined in Symfony login forms + 'error' => $error, + 'last_username' => $lastUsername, + + // OPTIONAL parameters to customize the login form: + + // the translation_domain to use (define this option only if you are +// rendering the login template in a regular Symfony controller; when +// rendering it from an EasyAdmin Dashboard this is automatically set to +// the same domain as the rest of the Dashboard) + 'translation_domain' => 'admin', + + // by default EasyAdmin displays a black square as its default favicon; +// use this method to display a custom favicon: the given path is passed +// "as is" to the Twig asset() function: +// + + // the title visible above the login form (define this option only if you are +// rendering the login template in a regular Symfony controller; when rendering +// it from an EasyAdmin Dashboard this is automatically set as the Dashboard title) + 'page_title' => 'ورود', + + // the string used to generate the CSRF token. If you don't define +// this parameter, the login form won't include a CSRF token + 'csrf_token_intention' => 'authenticate', + + // the URL users are redirected to after the login (default: '/admin') + 'target_path' => $this->generateUrl('admin'), + + // the label displayed for the username form field (the |trans filter is applied to it) + 'username_label' => 'پست الکترونیکی', + + // the label displayed for the password form field (the |trans filter is applied to it) + 'password_label' => 'کلمه عبور', + + // the label displayed for the Sign In form button (the |trans filter is applied to it) + 'sign_in_label' => 'ورود', + + // whether to enable or not the "forgot password?" link (default: false) + 'forgot_password_enabled' => false, + + // whether to enable or not the "remember me" checkbox (default: false) + 'remember_me_enabled' => true, + + // whether to check by default the "remember me" checkbox (default: false) + 'remember_me_checked' => true, + + // the label displayed for the remember me checkbox (the |trans filter is applied to it) + 'remember_me_label' => 'مرا به یاد داشته باش', + ]); + } + + #[Route('/logout', name: 'logout')] + public function logout(AuthenticationUtils $authenticationUtils): Response + { + return $this->redirectToRoute('app_home'); + } +} \ No newline at end of file diff --git a/symfony.lock b/symfony.lock index 9c03c1c..cd8b460 100644 --- a/symfony.lock +++ b/symfony.lock @@ -26,6 +26,15 @@ "migrations/.gitignore" ] }, + "easycorp/easyadmin-bundle": { + "version": "4.20", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.0", + "ref": "b131e6cbfe1b898a508987851963fff485986285" + } + }, "phpunit/phpunit": { "version": "9.6", "recipe": { @@ -271,6 +280,15 @@ "templates/base.html.twig" ] }, + "symfony/uid": { + "version": "7.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "7.0", + "ref": "0df5844274d871b37fc3816c57a768ffc60a43a5" + } + }, "symfony/ux-turbo": { "version": "2.22", "recipe": { @@ -280,6 +298,18 @@ "ref": "c85ff94da66841d7ff087c19cbcd97a2df744ef9" } }, + "symfony/ux-twig-component": { + "version": "2.22", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.13", + "ref": "67814b5f9794798b885cec9d3f48631424449a01" + }, + "files": [ + "config/packages/twig_component.yaml" + ] + }, "symfony/validator": { "version": "7.2", "recipe": { diff --git a/templates/base.html.twig b/templates/base.html.twig index 91daf55..018ba04 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -1,3 +1,4 @@ +{% apply spaceless %} @@ -96,3 +97,5 @@ + +{% endapply %} diff --git a/templates/post/api_docs.html.twig b/templates/post/api_docs.html.twig index 94a7be0..af0d79e 100644 --- a/templates/post/api_docs.html.twig +++ b/templates/post/api_docs.html.twig @@ -1,6 +1,5 @@ {% extends 'base.html.twig' %} -{% block keywords %}item.keywords -{% endblock %} +{% block keywords %}{{item.keywords}}{% endblock %} {% block title %} {{ item.title }} {% endblock %} diff --git a/templates/post/guide.html.twig b/templates/post/guide.html.twig index 38b64dd..42e395d 100644 --- a/templates/post/guide.html.twig +++ b/templates/post/guide.html.twig @@ -1,9 +1,6 @@ {% extends 'base.html.twig' %} -{% block keywords %}item.keywords -{% endblock %} -{% block title %} - {{ item.title }} -{% endblock %} +{% block keywords %}{{item.keywords}}{% endblock %} +{% block title %}{{ item.title }}{% endblock %} {% block des %} {{ item.intro }}