From 357f7f97c152ef39862030935c9cb3adc9951557 Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Wed, 28 Aug 2024 14:33:06 +0200 Subject: [PATCH 1/6] Add Tailwind documentation Co-authored-by: lfortunier --- README.md | 4 + docs/tailwind.md | 193 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 docs/tailwind.md diff --git a/README.md b/README.md index f36c72e..028e997 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,10 @@ return [ @import "variables"; @import 'smartbooster/sonata-bundle/assets/styles/main'; +### Tailwind + +Check the [Tailwind documentation](docs/tailwind.md) to enable it and use our tailwind templates. + ## What's inside ! - Default styles for sonata admin diff --git a/docs/tailwind.md b/docs/tailwind.md new file mode 100644 index 0000000..9d74102 --- /dev/null +++ b/docs/tailwind.md @@ -0,0 +1,193 @@ +# Tailwind + +This bundle provide some templates based on the tailwindcss framework sush as : +- The `ui_banner` macro from `templates/macros/ui_banner.html.twig` which can nicely display the current server environment base on a twig global var + +So to used thoses templates you must enable tailwind on your project. + +## Tailwind installation steps + +- Add front packages : +```bash +yarn add tailwindcss@^3.2.4 @tailwindcss/typography@^0.5.13 +yarn add --dev autoprefixer@^10.4.13 postcss@^8.4.19 postcss-loader@^7.0.2 +``` + +- Add the following file `postcss.config.js` at the root of your project +```js +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + } +}; +``` + +- Add the following file `tailwind.config.js` at the root of your project +```js +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + 'templates/**/*.html.twig', + 'vendor/smartbooster/sonata-bundle/templates/**/*.html.twig', + ], + theme: { + extend: { + colors: { + primary: { + transparent: 'var(--primary-transparent)', + lighter: 'var(--primary-lighter)', + light: 'var(--primary-light)', + DEFAULT: 'var(--primary-default)', + dark: 'var(--primary-dark)', + darker: 'var(--primary-darker)' + }, + neutral: { + transparent: 'var(--neutral-transparent)', + lighter: 'var(--neutral-lighter)', + light: 'var(--neutral-light)', + DEFAULT: 'var(--neutral-default)', + dark: 'var(--neutral-dark)', + darker: 'var(--neutral-darker)' + }, + success: { + light: 'var(--success-light-color)', + DEFAULT: 'var(--success-color)', + dark: 'var(--success-dark-color)', + }, + warning: { + light: 'var(--warning-light-color)', + DEFAULT: 'var(--warning-color)', + dark: 'var(--warning-dark-color)', + }, + danger: { + light: 'var(--danger-light-color)', + DEFAULT: 'var(--danger-color)', + dark: 'var(--danger-dark-color)', + }, + info: { + light: 'var(--info-light-color)', + DEFAULT: 'var(--info-color)', + dark: 'var(--info-dark-color)', + }, + } + }, + }, + // https://dev.to/kachkolasa/how-to-use-tailwindcss-bootstrap-in-the-same-project-5ho + corePlugins: { + preflight: false, + }, + plugins: [ + require('@tailwindcss/typography'), + ], + important: '.sb-tailwind', + safelist: [ + 'bg-primary-transparent', + 'bg-primary-lighter', + 'bg-primary-light', + 'bg-primary', + 'bg-primary-dark', + 'bg-primary-darker', + 'bg-neutral-transparent', + 'bg-neutral-lighter', + 'bg-neutral-light', + 'bg-neutral', + 'bg-neutral-dark', + 'bg-neutral-darker', + 'bg-success-light', + 'bg-success', + 'bg-success-dark', + 'bg-warning-light', + 'bg-warning', + 'bg-warning-dark', + 'bg-danger-light', + 'bg-danger', + 'bg-danger-dark', + 'bg-info-light', + 'bg-info', + 'bg-info-dark', + ], +} +``` + +- Add the following line to your `webpack.config.js` +```js +Encore + // Existing content ... + + // Enable postcss for Tailwind + .enablePostCssLoader((options) => { + options.postcssOptions = { + config: './postcss.config.js' + } + }) +``` + +- Add the following file `assets\admin\styles\_tailwind_base.scss` +```scss +@layer base { + /* color palette from custom UI chart with customer prefix */ + /* https://tailwindcss.com/docs/customizing-colors */ + :root { + /* Pour la configuration tailwind.config.js et la génération de classe automatique */ + --primary-transparent: theme(colors.blue.50); + --primary-lighter: theme(colors.blue.200); + --primary-light: theme(colors.blue.300); + --primary-default: theme(colors.blue.600); + --primary-dark: theme(colors.blue.700); + --primary-darker: theme(colors.blue.900); + + /* Couleur neutre utilisé pour les bordures, ombres, constrates ... */ + --neutral-transparent: theme(colors.neutral.50); + --neutral-lighter: theme(colors.neutral.300); + --neutral-light: theme(colors.neutral.500); + --neutral-default: theme(colors.neutral.700); + --neutral-dark: theme(colors.neutral.800); + --neutral-darker: theme(colors.neutral.900); + + /* Alert, callout, card */ + --success-color: theme(colors.green.500); + --success-light-color: theme(colors.green.300); + --success-dark-color: theme(colors.green.700); + --warning-color: theme(colors.yellow.500); + --warning-light-color: theme(colors.yellow.300); + --warning-dark-color: theme(colors.yellow.700); + --danger-color: theme(colors.red.600); + --danger-light-color: theme(colors.red.300); + --danger-dark-color: theme(colors.red.700); + --info-color: theme(colors.blue.500); + --info-light-color: theme(colors.blue.400); + --info-dark-color: theme(colors.blue.700); + } + + /* semantic color variables for this project */ + :root { + /* Button */ + --primary-background-color: var(--primary-default); + --primary-hover-background-color: var(--primary-dark); + } +} +``` + +- And import @tailwind minimal layer on your `admin/main.scss` before your existing content +```scss +@tailwind base; +@tailwind components; +@tailwind utilities; + +@import "tailwind_base"; + +// Existing content ... +``` + +## How to enable the ui_banner + +To display the ui_banner add the following global var to your `config/packages/twig.yaml` config. + +```yaml +twig: + globals: + smart_server_environment: '%env(default::ENVIRONMENT)%' +``` + +And define the `ENVIRONMENT` value in your .env according to your server environment. From 8262fd5dcecfe24c0a4e88f1789c3e93543b6d01 Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Wed, 28 Aug 2024 14:47:30 +0200 Subject: [PATCH 2/6] AbstractAdmin::getHistoryConfig new method to impact on show_history_field rendering + Adjust the template to translate when history config fields has the enum_prefix_label option + Add render_diff and render_diff_label block to ease template override --- src/Admin/AbstractAdmin.php | 7 +++ .../base_field/show_history_field.html.twig | 48 ++++++++++--------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/Admin/AbstractAdmin.php b/src/Admin/AbstractAdmin.php index 4f5e5f9..c10dda9 100644 --- a/src/Admin/AbstractAdmin.php +++ b/src/Admin/AbstractAdmin.php @@ -160,4 +160,11 @@ protected function init(?string $code = null, ?string $class = null, ?string $ba $this->setBaseControllerName($baseControllerName); } } + + public function getHistoryConfig(): array + { + return [ + 'fields' => [], // Indexed array which contains display options for each field + ]; + } } diff --git a/templates/admin/base_field/show_history_field.html.twig b/templates/admin/base_field/show_history_field.html.twig index c814321..1902128 100644 --- a/templates/admin/base_field/show_history_field.html.twig +++ b/templates/admin/base_field/show_history_field.html.twig @@ -11,7 +11,7 @@ {% endif %} {% endmacro %} -{% macro render_diff_value(value) %} +{% macro render_diff_value(field, value) %} {% if is_iso8601_datetime(value) and value|date('H:i') == '00:00' %} {{ value|date(constant('Smart\\CoreBundle\\Formatter\\PhpFormatter::DATE_FR')) }} {% elseif is_iso8601_datetime(value) and value|date('H:i') != '00:00' %} @@ -26,6 +26,8 @@ {% for item in value %} {{ item }} {% endfor %} + {% elseif admin.historyConfig.fields[field].enum_prefix_label ?? null is not null %} + {{ (admin.historyConfig.fields[field].enum_prefix_label ~ value)|trans({}, 'messages') }} {% else %} {{ value|raw|nl2br }} {% endif %} @@ -158,28 +160,30 @@ {% if row.diff is defined %}
    {% for field, field_data in row.diff %} -
  • - {{ _self.render_diff_label(field) }} : - {% if field_data.c_u is defined and field_data.c_u is not empty %} -
      - {% for item in field_data.c_u %} -
    • {{ item }}
    • - {% endfor %} -
    - {% elseif field_data.f is not null or field_data.t is not null%} - - {% block render_diff_from_value %} - {{ _self.render_diff_value(field_data.f) }} + {% block render_diff %} +
  • + {% block render_diff_label %}{{ _self.render_diff_label(field) }} :{% endblock %} + {% if field_data.c_u is defined and field_data.c_u is not empty %} +
      + {% for item in field_data.c_u %} +
    • {{ item }}
    • + {% endfor %} +
    + {% elseif field_data.f is not null or field_data.t is not null%} + + {% block render_diff_from_value %} + {{ _self.render_diff_value(field, field_data.f) }} + {% endblock %} + + + {% block render_diff_to_value %} + {{ _self.render_diff_value(field, field_data.t) }} {% endblock %} - - - {% block render_diff_to_value %} - {{ _self.render_diff_value(field_data.t) }} - {% endblock %} - {% else %} - ({{ field_data|trans }}) - {% endif %} -
  • + {% else %} + ({{ field_data|trans }}) + {% endif %} + + {% endblock %} {% endfor %}
{% endif %} From f0cd17296241b7eeda5b8cef09fed7110f6f4d2d Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Wed, 28 Aug 2024 14:49:31 +0200 Subject: [PATCH 3/6] Add common translations used on ApiCallAdmin and CronAdmin + history.context.sso --- translations/admin.en.xlf | 133 +++++++++++++++++++++++++++++++++++ translations/admin.fr.xlf | 96 +++++++++++++++++++++++++ translations/messages.en.xlf | 4 ++ translations/messages.fr.xlf | 4 ++ 4 files changed, 237 insertions(+) diff --git a/translations/admin.en.xlf b/translations/admin.en.xlf index 6165925..3012d6a 100644 --- a/translations/admin.en.xlf +++ b/translations/admin.en.xlf @@ -54,6 +54,18 @@ dashboard.label_documentation_projet Project documentation + + dashboard.label_monitoring + Monitoring + + + dashboard.label_crons + Crons + + + dashboard.label_api_call + API + breadcrumb.link_parameter_list Parameter list @@ -66,6 +78,14 @@ breadcrumb.link_batch_log_list Logs list + + breadcrumb.link_cron_list + Crons list + + + breadcrumb.link_api_call_list + API call list + fieldset.label_general @@ -172,6 +192,119 @@ field.label_data Data + + + label.files + Files + + + + label.pdf_file + PDF file + + + label.image + Image + + + label.image_updated_at + Image updated at + + + label.image_original_name + Image original name + + + label.pdf_updated_at + PDF updated at + + + label.pdf_original_name + PDF original name + + + label.uuid + UUID + + + label.type + Type + + + label.started_at + Started at + + + label.ended_at + Ended at + + + label.duration + Duration + + + label.status + Status + + + label.summary + Summary + + + label.logs + Logs + + + label.process_data + Process data + + + label.process_json_data + Process JSON data + + + label.origin + Origin + + + label.status_code + Status HTTP + + + label.route_url + URL + + + label.route + Route + + + label.result + Result + + + label.method + Method + + + label.api_params + API params + + + label.input_data + Input data + + + label.output_response + Output response + + + label.headers + Headers + diff --git a/translations/admin.fr.xlf b/translations/admin.fr.xlf index 084a073..c1aecec 100644 --- a/translations/admin.fr.xlf +++ b/translations/admin.fr.xlf @@ -54,6 +54,18 @@ dashboard.label_documentation_projet Documentation Projet + + dashboard.label_monitoring + Monitoring + + + dashboard.label_crons + Crons + + + dashboard.label_api_call + API + breadcrumb.link_parameter_list Liste des paramètres @@ -66,6 +78,14 @@ breadcrumb.link_batch_log_list Liste des logs + + breadcrumb.link_cron_list + Liste des crons + + + breadcrumb.link_api_call_list + Liste des appels API + fieldset.label_general @@ -209,6 +229,82 @@ label.uuid Identifiant technique UUID + + label.type + Type + + + label.started_at + Date de début + + + label.ended_at + Date de fin + + + label.duration + Durée + + + label.status + Statut + + + label.summary + Résumé + + + label.logs + Logs + + + label.process_data + Détail du traitement + + + label.process_json_data + Données interne du traitement + + + label.origin + Origine + + + label.status_code + Code HTTP + + + label.route_url + URL + + + label.route + Route + + + label.result + Résultat + + + label.method + Méthode + + + label.api_params + Paramètres API + + + label.input_data + Paramètres d'entrée + + + label.output_response + Réponse en sortie + + + label.headers + Headers + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index bbebe37..12935b4 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -149,6 +149,10 @@ history.context.cron Cron + + history.context.sso + SSO + history.email.sent Email sent diff --git a/translations/messages.fr.xlf b/translations/messages.fr.xlf index cc878fc..2e31e4b 100644 --- a/translations/messages.fr.xlf +++ b/translations/messages.fr.xlf @@ -149,6 +149,10 @@ history.context.cron Cron + + history.context.sso + SSO + history.email.sent Email envoyé From 8b08ffd39c44187dd25b45c2172edf68f795ec5e Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Wed, 28 Aug 2024 14:53:32 +0200 Subject: [PATCH 4/6] Fixed the BaseMailer::setRecipientToEmail recipients reset for successive calls --- src/Mailer/BaseMailer.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Mailer/BaseMailer.php b/src/Mailer/BaseMailer.php index 68541d0..494198a 100644 --- a/src/Mailer/BaseMailer.php +++ b/src/Mailer/BaseMailer.php @@ -64,7 +64,7 @@ public function newEmail(string $code, ?array $context = null): TemplatedEmail /** * @param mixed $recipient */ - public function send(TemplatedEmail $email, $recipient = null): void + public function send(TemplatedEmail $email, mixed $recipient = null): void { $email->subject($this->translator->trans($email->getSubject(), $email->getSubjectParameters(), 'email')); @@ -92,18 +92,23 @@ public function send(TemplatedEmail $email, $recipient = null): void * Protected method to allow ease extend and put custom logic based on the recipient * @param mixed $recipient */ - protected function setRecipientToEmail(TemplatedEmail $email, $recipient = null): void + protected function setRecipientToEmail(TemplatedEmail $email, mixed $recipient = null): void { if ( ($recipient instanceof MailableInterface && $recipient->getRecipientEmail() === null) || (is_array($recipient) && empty($recipient)) - || $recipient == null + || $recipient === null ) { throw new \InvalidArgumentException($this->translator->trans('smart.email.empty_recipient_error', [ '%code%' => $email->getCode() ], 'email')); } + // Recipients reset in case of successive calls with the same email param + $email->to(); + $email->cc(); + $email->Bcc(); + if ($recipient instanceof MailableInterface) { $this->recipientToString = $recipient->getRecipientEmail(); $email->addTo(...$this->extractEmailFromString($recipient->getRecipientEmail())); From b55754144641d405d71cdd192ac46316bd22718d Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Wed, 28 Aug 2024 17:53:51 +0200 Subject: [PATCH 5/6] Update mailer.md doc route import, documentation_help block, MailableInterface use and how to extend the BaseMailer --- docs/mailer.md | 91 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 13 deletions(-) diff --git a/docs/mailer.md b/docs/mailer.md index d8089cd..105c560 100644 --- a/docs/mailer.md +++ b/docs/mailer.md @@ -6,20 +6,18 @@ ## How to add the autogenerated email documentation -Add the route to your application’s routing file: - +Enable the bundle route on your `config/routes.yaml` file: ```yaml -# config/routes/sonata_admin.yaml -smart_sonata: - resource: "@SmartSonataBundle/config/routing.yaml" - host: "admin.%domain%" +_smart_sonata: + resource: . + type: smart_sonata + host: "admin.%domain%" ``` Update you sonata_admin config package: - ```yaml sonata_admin: - ... + # ... dashboard: groups: documentations: @@ -37,8 +35,7 @@ And voilà ! Define your email code as shown on the [configuration reference](configuration.md) -Then create your email template based on the path of your email code. - +Then create your email template based on the path of your email code. For example if your email code is `admin.security.forgot_password` then you must create a template on theses path : ```yaml @@ -50,7 +47,7 @@ For example if your email code is `admin.security.forgot_password` then you must /tempaltes/en/email/admin/security/forgot_password.html.twig ``` -Last step is to create the appropriate translation for your email code for the **subject** and **documentation**. +Create the appropriate translation for your email code for the **subject** and **documentation**. ```xml @@ -64,6 +61,17 @@ Last step is to create the appropriate translation for your email code for the * ``` +Finaly to keep track on the documentation email who is the recipient, and what trigger the email sending, you can add the following on your template : + +```twig +{% block documentation_help %} +

{{ 'email.recipient'|trans }} : Foo

+

{{ 'email.trigger'|trans }} : The email is sent when ...

+{% endblock %} +``` + +_The `templates/admin/documentation/email.html.twig` will render the documentation_help block_ + ## How to send an email - Inject the BaseMailer service on your controller or service. @@ -92,5 +100,62 @@ use Smart\SonataBundle\Mailer\BaseMailer; } ``` -If you need to centralize custom logic to set the recipient for the email (like a CommercialMailer for example that -get his email from some external configuration), just extend the BaseMailer and override the `setRecipientToEmail` method. +### Send email to MailableInterface + +The core-bundle provide a `MailableInterface` which is a valid recipient for the `BaseMailer::send` method. +This allow you to pass an entity/object to the send method which automatically set the to, cc and Bcc. + +```php +/** @var MailableInterface */ +$mailer->send($email, $user); +``` + +## How to extend the BaseMailer to add custom business logic + +In some case, you might want to extend our Mailer to add custom logic when the email is sent, for example : +- Log the event of the email being sent in a dedicated ActionLog entity (specific to the project which also contains other actions) for statistic purpose. + +If that the case here is a boilerplate of what you need to do : + +```php +service = $service; + } + + public function send(TemplatedEmail $email, mixed $recipient = null): void + { + parent::send($email, $recipient); + + $this->service->customBusinessLogic(); + // ... + } + + /** + * Known issue that the sender address isn't set on custom mailer like BaseMailer is by the SmartSonataExtension. + * So we fix it by autowire the sender with param fetch with the Autowire attribute which is cleaner to do it via the __construct + */ + #[Required] + public function autowireSender(#[Autowire('%app.mail_from%')] string $address): void + { + $this->setSender(['address' => $address]); + } +} +``` + +As mention on the example above, inject custom service using the `#[Required]` instead of the `__construct` method. +This technique helps you with less upgrade maintaining in case the `__construct` method of the parent BaseMailer evolves. From ca85046fbcd9f4ff79b1a2cdfcdb7e02718f6361 Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Wed, 28 Aug 2024 18:02:20 +0200 Subject: [PATCH 6/6] Update CHANGELOG for release v2.7.0 - (2024-08-28) --- CHANGELOG.md | 15 +++++++++++++++ CHANGELOG_fix_documentation_css.md | 2 -- 2 files changed, 15 insertions(+), 2 deletions(-) delete mode 100644 CHANGELOG_fix_documentation_css.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 88cf0b3..6312003 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ CHANGELOG =================== +## v2.7.0 - (2024-08-28) +### Added +- `docs/tailwind.md` documentation +- `AbstractAdmin::getHistoryConfig` new method to impact on show_history_field rendering +- `show_history_field.html.twig` Add `render_diff` and `render_diff_label` block to ease template override +- Add common translations used on ApiCallAdmin and CronAdmin + history.context.sso + +### Changed +- `show_history_field.html.twig` Adjust the template to translate when history config fields has the enum_prefix_label option +- `docs/mailer.md` update documentation on doc route import, documentation_help block, MailableInterface use and how to extend the BaseMailer + +### Fixed +- `_documentation.scss` Fix tailwind sb-documentation style : max-width + table and image max-width/transform +- `BaseMailer::setRecipientToEmail` recipients reset for successive calls on the send method + ## v2.6.0 - (2024-07-11) ### Added - add vich_uploader translations diff --git a/CHANGELOG_fix_documentation_css.md b/CHANGELOG_fix_documentation_css.md deleted file mode 100644 index 0d2ed34..0000000 --- a/CHANGELOG_fix_documentation_css.md +++ /dev/null @@ -1,2 +0,0 @@ -### Fixed -- Fix tailwind sb-documentation style : max-width + table and image max-width/transform