From e64548b982ba47ff35f2272e2e30dd85eeba950b Mon Sep 17 00:00:00 2001 From: Yassine Doghri <yassine@doghri.fr> Date: Wed, 15 Sep 2021 15:58:21 +0000 Subject: [PATCH] feat: replace form helper functions with components in admin template --- app/Controllers/PostController.php | 3 +- app/Entities/EpisodeComment.php | 3 - app/Language/en/Fediverse.php | 35 +- app/Language/fr/Fediverse.php | 35 +- app/Libraries/ViewComponents/Component.php | 5 +- app/Resources/images/castopod-logo-base.svg | 5 + app/Resources/images/castopod-logo.svg | 43 +- .../images/castopod-mascot_confused.svg | 300 +++------- app/Resources/js/modules/Clipboard.ts | 10 +- app/Resources/js/modules/ThemePicker.ts | 9 +- app/Resources/styles/breadcrumb.css | 2 +- app/Resources/styles/switch.css | 40 +- app/Views/Components/Alert.php | 39 ++ app/Views/Components/Button.php | 33 +- app/Views/Components/Forms/Checkbox.php | 39 ++ app/Views/Components/Forms/DatetimePicker.php | 29 + app/Views/Components/Forms/FormComponent.php | 18 + app/Views/Components/Forms/Helper.php | 2 +- app/Views/Components/Forms/Input.php | 11 +- app/Views/Components/Forms/Label.php | 7 +- app/Views/Components/Forms/MultiSelect.php | 6 +- app/Views/Components/Forms/Radio.php | 32 + app/Views/Components/Forms/RadioButton.php | 5 - app/Views/Components/Forms/Section.php | 8 +- app/Views/Components/Forms/Select.php | 2 +- app/Views/Components/Forms/Textarea.php | 31 + app/Views/Components/Forms/Toggler.php | 33 +- app/Views/Components/Forms/XMLEditor.php | 4 +- app/Views/Components/Heading.php | 2 +- app/Views/Components/IconButton.php | 21 + modules/Admin/Language/en/Episode.php | 1 + modules/Admin/Language/en/Person.php | 6 - modules/Admin/Language/en/Podcast.php | 1 - modules/Admin/Language/en/PodcastImport.php | 6 +- modules/Admin/Language/fr/Episode.php | 1 + modules/Admin/Language/fr/Person.php | 22 +- modules/Admin/Language/fr/Podcast.php | 1 - modules/Admin/Language/fr/PodcastImport.php | 2 +- themes/cp_admin/_layout.php | 4 +- themes/cp_admin/_message_block.php | 20 + themes/cp_admin/contributor/add.php | 52 +- themes/cp_admin/contributor/edit.php | 36 +- themes/cp_admin/episode/create.php | 507 ++++++---------- themes/cp_admin/episode/edit.php | 512 ++++++---------- themes/cp_admin/episode/embeddable_player.php | 52 +- themes/cp_admin/episode/persons.php | 87 ++- themes/cp_admin/episode/publish.php | 169 ++---- themes/cp_admin/episode/publish_edit.php | 175 ++---- themes/cp_admin/episode/soundbites.php | 2 +- themes/cp_admin/episode/unpublish.php | 52 +- themes/cp_admin/fediverse/blocked_actors.php | 39 +- themes/cp_admin/fediverse/blocked_domains.php | 38 +- .../cp_admin/my_account/change_password.php | 53 +- themes/cp_admin/page/create.php | 66 +-- themes/cp_admin/page/edit.php | 72 +-- themes/cp_admin/person/create.php | 111 +--- themes/cp_admin/person/edit.php | 116 ++-- themes/cp_admin/podcast/create.php | 558 ++++++------------ themes/cp_admin/podcast/edit.php | 18 +- themes/cp_admin/podcast/import.php | 299 +++------- themes/cp_admin/podcast/persons.php | 61 +- themes/cp_admin/podcast/platforms.php | 54 +- themes/cp_app/home.php | 2 +- .../cp_app/podcast/_layout_authenticated.php | 2 +- .../comment_actions_authenticated.php | 6 +- .../_partials/episode_preview_card.php | 2 +- themes/cp_app/podcast/activity.php | 10 +- .../cp_app/podcast/activity_authenticated.php | 2 + themes/cp_app/podcast/episode.php | 1 + .../cp_app/podcast/episode_authenticated.php | 2 + 70 files changed, 1461 insertions(+), 2571 deletions(-) create mode 100644 app/Resources/images/castopod-logo-base.svg create mode 100644 app/Views/Components/Alert.php create mode 100644 app/Views/Components/Forms/Checkbox.php create mode 100644 app/Views/Components/Forms/DatetimePicker.php create mode 100644 app/Views/Components/Forms/Radio.php create mode 100644 app/Views/Components/Forms/Textarea.php create mode 100644 app/Views/Components/IconButton.php create mode 100644 themes/cp_admin/_message_block.php diff --git a/app/Controllers/PostController.php b/app/Controllers/PostController.php index 764477fcae..184825adca 100644 --- a/app/Controllers/PostController.php +++ b/app/Controllers/PostController.php @@ -81,9 +81,8 @@ class PostController extends FediversePostController if (! ($cachedView = cache($cacheName))) { $data = [ - 'podcast' => $this->podcast, - 'actor' => $this->actor, 'post' => $this->post, + 'podcast' => $this->podcast, ]; // if user is logged in then send to the authenticated activity view diff --git a/app/Entities/EpisodeComment.php b/app/Entities/EpisodeComment.php index cb39152c55..b7670d82ac 100644 --- a/app/Entities/EpisodeComment.php +++ b/app/Entities/EpisodeComment.php @@ -69,9 +69,6 @@ class EpisodeComment extends UuidEntity 'is_from_post' => 'boolean', ]; - /** - * Returns the comment's attached episode - */ public function getEpisode(): ?Episode { if ($this->episode_id === null) { diff --git a/app/Language/en/Fediverse.php b/app/Language/en/Fediverse.php index a445724791..6477b70ec8 100644 --- a/app/Language/en/Fediverse.php +++ b/app/Language/en/Fediverse.php @@ -3,23 +3,34 @@ declare(strict_types=1); /** - * @copyright 2020 Podlibre + * @copyright 2021 Podlibre * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ return [ - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', + 'your_handle' => 'Your handle', + 'your_handle_hint' => 'Enter the @username@domain you want to act from.', + 'follow' => [ + 'label' => 'Follow', + 'title' => 'Follow {actorDisplayName}', + 'subtitle' => 'You are going to follow:', + 'accountNotFound' => 'The account could not be found.', + 'submit' => 'Proceed to follow', ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', + 'favourite' => [ + 'title' => "Favourite {actorDisplayName}'s post", + 'subtitle' => 'You are going to favourite:', + 'submit' => 'Proceed to favourite', + ], + 'reblog' => [ + 'title' => "Share {actorDisplayName}'s post", + 'subtitle' => 'You are going to share:', + 'submit' => 'Proceed to share', + ], + 'reply' => [ + 'title' => "Reply to {actorDisplayName}'s post", + 'subtitle' => 'You are going to reply to:', + 'submit' => 'Proceed to reply', ], ]; diff --git a/app/Language/fr/Fediverse.php b/app/Language/fr/Fediverse.php index fa6b48972c..886181be3b 100644 --- a/app/Language/fr/Fediverse.php +++ b/app/Language/fr/Fediverse.php @@ -3,20 +3,35 @@ declare(strict_types=1); /** - * @copyright 2020 Podlibre + * @copyright 2021 Podlibre * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ return [ - 'block_lists' => 'Listes de blocage', - 'block_lists_form' => [ - 'blocked_users' => 'Utilisateurs bloqués', - 'blocked_users_hint' => - 'Entrez les pseudonymes @utilisateur@domaine séparés par une virgule.', - 'blocked_domains' => 'Domaines bloqués', - 'blocked_domains_hint' => - 'Entrez les noms de domaine séparés par une virgule.', - 'submit' => 'Sauvegarder les listes', + 'your_handle' => 'Votre pseudonyme', + 'your_handle_hint' => + 'Entrez le @utilisateur@domaine avec lequel vous voulez interagir.', + 'follow' => [ + 'label' => 'Suivre', + 'title' => 'Suivre {actorDisplayName}', + 'subtitle' => 'Vous allez suivre :', + 'accountNotFound' => 'Le compte n’a pas pu être trouvé.', + 'submit' => 'Poursuivre', + ], + 'favourite' => [ + 'title' => 'Mettez la publication de {actorDisplayName} en favori', + 'subtitle' => 'Vous allez mettre en favori :', + 'submit' => 'Poursuivre', + ], + 'reblog' => [ + 'title' => 'Partagez la publication de {actorDisplayName}', + 'subtitle' => 'Vous allez partager :', + 'submit' => 'Poursuivre', + ], + 'reply' => [ + 'title' => 'Répondre à la publication de {actorDisplayName}', + 'subtitle' => 'Vous allez répondre à :', + 'submit' => 'Poursuivre', ], ]; diff --git a/app/Libraries/ViewComponents/Component.php b/app/Libraries/ViewComponents/Component.php index 2aa0a9135b..47dc262535 100644 --- a/app/Libraries/ViewComponents/Component.php +++ b/app/Libraries/ViewComponents/Component.php @@ -24,11 +24,12 @@ class Component implements ComponentInterface { helper('viewcomponents'); + // overwrite default attributes if set + $this->attributes = array_merge($this->attributes, $attributes); + if ($attributes !== []) { $this->hydrate($attributes); } - // overwrite default attributes if set - $this->attributes = array_merge($this->attributes, $attributes); } /** diff --git a/app/Resources/images/castopod-logo-base.svg b/app/Resources/images/castopod-logo-base.svg new file mode 100644 index 0000000000..482eebfe63 --- /dev/null +++ b/app/Resources/images/castopod-logo-base.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59 40"> + <path d="M52.801 38.23h-8.853s-.93-1.975-1.306-2.671c-.378-.697-1.278-.668-1.278-.668H17.33s-.871-.116-1.307.668c-.464.784-1.335 2.67-1.335 2.67H5.98c-2.003 0-3.658-1.625-3.658-3.628V5.893c0-2.003 1.626-3.658 3.629-3.658h46.821c2.003 0 3.658 1.626 3.658 3.629v28.708c.029 2.003-1.626 3.657-3.629 3.657Z" fill="#009486"/> + <path d="M17.01 10.014h24.703c4.267-.028 7.721 3.426 7.692 7.722 0 4.238-3.454 7.692-7.692 7.692H17.01c-4.238 0-7.692-3.454-7.692-7.692 0-4.238 3.454-7.722 7.692-7.722Z" fill="#E7F9E4"/> + <path d="M39.768 14.804a3.773 3.773 0 0 0-3.774 3.777c0 .861.298 1.656.795 2.319 0 0 1.29-.96 3.111-.96 1.357 0 2.946.827 2.946.827.43-.63.695-1.358.695-2.186a3.773 3.773 0 0 0-3.773-3.777Zm-20.9 0a3.773 3.773 0 0 0-3.774 3.777c0 .828.265 1.557.695 2.186 0 0 1.59-.828 2.946-.828 1.821 0 3.112.96 3.112.96a3.707 3.707 0 0 0 .794-2.318 3.773 3.773 0 0 0-3.773-3.777Z" fill="#009486"/> +</svg> diff --git a/app/Resources/images/castopod-logo.svg b/app/Resources/images/castopod-logo.svg index 444036e3e8..039deb7482 100644 --- a/app/Resources/images/castopod-logo.svg +++ b/app/Resources/images/castopod-logo.svg @@ -1,39 +1,6 @@ -<?xml version="1.0" encoding="utf-8"?> -<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - viewBox="0 0 202.4 137.8" style="enable-background:new 0 0 202.4 137.8;" xml:space="preserve"> -<style type="text/css"> - .st0{fill:#009486;} - .st1{fill:#E7F9E4;} - .st2{fill:none;} - .st3{fill:#E7FFE3;} -</style> -<g> - <path id="dark_greeen_19_" class="st0" d="M181.9,131.7h-32.5c0,0-1.2-2.5-2.5-4.9c-1.3-2.4-4.4-2.3-4.4-2.3H59.7 - c0,0-3-0.4-4.5,2.3c-1.6,2.7-2.6,4.9-2.6,4.9H20.6c-6.9,0-12.6-5.6-12.6-12.5V20.3c0-6.9,5.6-12.6,12.5-12.6h161.3 - c6.9,0,12.6,5.6,12.6,12.5v98.9C194.5,126,188.8,131.7,181.9,131.7z"/> - <path class="st1" d="M143.7,34.5H58.6c-14.6,0-26.5,12-26.5,26.6c0,14.6,11.9,26.5,26.5,26.5h85.1c14.6,0,26.5-11.9,26.5-26.5 - C170.3,46.3,158.4,34.4,143.7,34.5z M68.3,68.7c0,0-3.9-2.9-9.4-2.9c-4.1,0-8.9,2.5-8.9,2.5c-1.3-1.9-2.1-4.1-2.1-6.6 - c0-6.3,5.1-11.4,11.4-11.4s11.4,5.1,11.4,11.4C70.7,64.4,69.8,66.8,68.3,68.7z M101.2,75.3c-12.5,0-12-9.6-12-9.6 - c-0.2-1.8,2.1-2.4,2.9-1.3c0.4,0.6,0.4,0.6,0.7,1.7c1.7,5.9,8.4,5.6,8.4,5.6s6.7,0.4,8.4-5.6c0.3-1,0.3-1.1,0.7-1.7 - c0.8-1,3.1-0.5,2.9,1.3C113.2,65.7,113.7,75.3,101.2,75.3z M152.3,68.4c0,0-4.8-2.5-8.9-2.5c-5.5,0-9.4,2.9-9.4,2.9 - c-1.5-1.9-2.4-4.3-2.4-7c0-6.3,5.1-11.4,11.4-11.4s11.4,5.1,11.4,11.4C154.5,64.2,153.7,66.5,152.3,68.4z"/> - <path class="st2" d="M110.3,64.3c-0.4,0.6-0.4,0.6-0.7,1.7c-1.7,5.9-8.4,5.6-8.4,5.6s-6.7,0.4-8.4-5.6c-0.3-1-0.3-1.1-0.7-1.7 - c-0.8-1-3.1-0.5-2.9,1.3c0,0-0.5,9.6,12,9.6c12.5,0,12-9.6,12-9.6C113.4,63.9,111.1,63.3,110.3,64.3z"/> - <path class="st2" d="M143.1,50.4c-6.3,0-11.4,5.1-11.4,11.4c0,2.6,0.9,5,2.4,7c0,0,3.9-2.9,9.4-2.9c4.1,0,8.9,2.5,8.9,2.5 - c1.3-1.9,2.1-4.1,2.1-6.6C154.5,55.5,149.4,50.4,143.1,50.4z"/> - <path class="st2" d="M59.3,50.4c-6.3,0-11.4,5.1-11.4,11.4c0,2.5,0.8,4.7,2.1,6.6c0,0,4.8-2.5,8.9-2.5c5.5,0,9.4,2.9,9.4,2.9 - c1.5-1.9,2.4-4.3,2.4-7C70.7,55.5,65.6,50.4,59.3,50.4z"/> - <g> - <g> - <path class="st3" d="M47.1,23.3c-6.3-1.7-11.7,2.1-14.7,7.3c-0.7,1.2-0.2,2.2,0.5,2.6c1,0.3,1.7,0.1,2.8-1.5 - c2.2-3.9,5.9-6.1,10.1-5.3c0,0,2.9,0.9,3.3-1C49.4,24.2,48.3,23.6,47.1,23.3z"/> - </g> - </g> - <g> - <g> - <path class="st3" d="M159.9,27.3c-0.1,1.9,2.9,1.9,2.9,1.9c4.2,0.4,6.8,2.3,7.8,6.7c0.6,1.9,1.2,2.2,2.3,2.2 - c0.8-0.1,1.6-1,1.2-2.4c-1.4-5.8-5.1-9.8-11.7-9.9C161.2,25.7,160,26,159.9,27.3z"/> - </g> - </g> -</g> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59 40"> + <path d="M53.024 38.23H43.55s-.35-.726-.728-1.423c-.38-.697-1.283-.668-1.283-.668H17.403s-.875-.116-1.312.668a16.505 16.505 0 0 0-.758 1.422H6.005c-2.011 0-3.673-1.625-3.673-3.628V5.893c0-2.003 1.632-3.658 3.644-3.658h47.02c2.01 0 3.672 1.626 3.672 3.629v28.708c.03 2.003-1.632 3.657-3.644 3.657Z" fill="#009486"/> + <path d="M41.889 10.014H17.082c-4.256 0-7.725 3.484-7.725 7.722s3.47 7.692 7.725 7.692h24.807c4.256 0 7.725-3.454 7.725-7.692a7.655 7.655 0 0 0-7.725-7.722Zm-21.98 9.928s-1.136-.842-2.74-.842c-1.195 0-2.594.726-2.594.726a3.333 3.333 0 0 1-.612-1.916 3.315 3.315 0 0 1 3.323-3.31 3.315 3.315 0 0 1 3.323 3.31c0 .784-.262 1.48-.7 2.032Zm9.591 1.916c-3.644 0-3.498-2.787-3.498-2.787-.058-.522.612-.697.845-.377.117.174.117.174.204.493.496 1.713 2.449 1.626 2.449 1.626s1.953.116 2.449-1.626c.087-.29.087-.32.204-.493.233-.29.903-.145.845.377 0 0 .146 2.787-3.498 2.787Zm14.896-2.003s-1.4-.726-2.595-.726c-1.603 0-2.74.842-2.74.842a3.238 3.238 0 0 1-.7-2.032 3.315 3.315 0 0 1 3.324-3.31 3.315 3.315 0 0 1 3.323 3.31 3.014 3.014 0 0 1-.612 1.916Z" fill="#E7F9E4"/> + <path d="M41.714 14.63a3.315 3.315 0 0 0-3.323 3.309c0 .755.262 1.451.7 2.032 0 0 1.136-.842 2.74-.842 1.195 0 2.594.726 2.594.726.379-.552.612-1.19.612-1.916a3.315 3.315 0 0 0-3.323-3.31ZM17.286 14.63a3.315 3.315 0 0 0-3.323 3.309c0 .726.233 1.364.612 1.916 0 0 1.4-.726 2.594-.726 1.604 0 2.74.842 2.74.842.438-.552.7-1.248.7-2.032a3.315 3.315 0 0 0-3.323-3.31Z" fill="#009486"/> + <path d="M13.73 6.763c-1.837-.493-3.41.61-4.285 2.12-.204.348-.059.638.145.754.292.087.496.03.817-.435.641-1.132 1.72-1.77 2.944-1.539 0 0 .845.262.962-.29.087-.348-.233-.522-.583-.61ZM46.611 7.925c-.03.551.845.551.845.551 1.225.116 1.983.668 2.274 1.945.175.551.35.639.67.639.234-.03.467-.29.35-.697-.408-1.684-1.486-2.845-3.41-2.874-.35-.029-.7.058-.729.436Z" fill="#E7F9E4"/> </svg> diff --git a/app/Resources/images/castopod-mascot_confused.svg b/app/Resources/images/castopod-mascot_confused.svg index b4ff04f5f1..5d6f9d32e1 100644 --- a/app/Resources/images/castopod-mascot_confused.svg +++ b/app/Resources/images/castopod-mascot_confused.svg @@ -1,234 +1,68 @@ -<?xml version="1.0" encoding="utf-8"?> -<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - viewBox="0 0 155.9 184.3" style="enable-background:new 0 0 155.9 184.3;" xml:space="preserve"> -<style type="text/css"> - .st0{fill:#006D60;} - .st1{fill:#00564A;} - .st2{fill:#009486;} - .st3{fill:#2B6B5F;} - .st4{fill:#E7F9E4;} - .st5{fill:#71AFA3;} - .st6{fill:#DCF4D7;} -</style> -<g> - <g id="FOOTS_1_"> - <path class="st0" d="M55.8,134.7l37.2-0.3c1.4,0,2.5-1.2,2.5-2.6l0,0c0-1.4-1.2-2.5-2.6-2.5l-37.2,0.3c-1.4,0-2.5,1.2-2.5,2.6v0 - C53.3,133.5,54.4,134.7,55.8,134.7z"/> - <path class="st1" d="M89.2,129.3l-29.5,0.2c0,0,7.5,1.3,15.2,1.2C82.8,130.7,89.2,129.3,89.2,129.3z"/> - </g> - <g id="LEGS_5_"> - - <rect x="40.6" y="102.5" transform="matrix(-1 7.722594e-03 -7.722594e-03 -1 149.3678 218.2719)" class="st1" width="67.3" height="13.8"/> - <path class="st2" d="M38.4,116.2L38.4,116.2c0.1,6.5,5.4,11.8,11.9,11.8l48.2-0.4c6.5,0,11.7-5.5,11.7-12l0,0l0-1.9 - c0-1.6-1.3-2.9-2.9-2.9l-66,0.5c-1.6,0-2.9,1.3-2.9,2.9L38.4,116.2z"/> - <g> - - <rect x="41.4" y="107.9" transform="matrix(-1 7.722594e-03 -7.722594e-03 -1 149.3352 215.4585)" class="st3" width="65.8" height="0.2"/> - - <rect x="41.4" y="108.7" transform="matrix(-1 7.722594e-03 -7.722594e-03 -1 149.3543 217.1097)" class="st3" width="65.8" height="0.2"/> - - <rect x="41.4" y="109.6" transform="matrix(-1 7.722594e-03 -7.722594e-03 -1 149.3735 218.761)" class="st3" width="65.8" height="0.2"/> - </g> - <path class="st0" d="M75.1,127.8l23.3-0.2c6.5-0.1,11.8-5.5,11.7-12l0,0c0,0-1,5.3-8.2,8c-5.3,2-12.8,1.6-26.9,1.7 - c-14.1,0.1-23,0.6-28.4-1.3c-7.2-2.6-8.3-7.8-8.3-7.8l0,0c0.1,6.5,5.4,11.8,11.9,11.8L75.1,127.8z"/> - </g> - <g id="NECK_5_"> - <path class="st1" d="M51.3,82.6l0.1-1.3l2.9-5c0,0,0.3-0.7,2-0.6c0.8,0,38.5,2.1,39.3,2.1c1.8,0.1,2,0.8,2,0.8l1.6,3.8l-0.1,1.3 - L51.3,82.6z"/> - <g> - - <rect x="75.7" y="57.7" transform="matrix(5.436085e-02 -0.9985 0.9985 5.436085e-02 -6.2381 149.5234)" class="st3" width="0.2" height="40.7"/> - - <rect x="75.7" y="57.8" transform="matrix(5.436085e-02 -0.9985 0.9985 5.436085e-02 -7.1037 150.2582)" class="st3" width="0.2" height="42.2"/> - </g> - </g> - <g id="HEAD_18_"> - <path id="dark_greeen_9_" class="st2" d="M35.2,76.5l16.4,0.9c0,0,0.7-1.2,1.4-2.4c0.7-1.2,2.3-1,2.3-1l41.7,2.3 - c0,0,1.5-0.1,2.2,1.3c0.7,1.4,1.2,2.5,1.2,2.5l16.1,0.9c3.5,0.2,6.5-2.5,6.7-6l2.7-49.8c0.2-3.5-2.5-6.5-6-6.7l-81.1-4.4 - c-3.5-0.2-6.5,2.5-6.7,6l-2.7,49.8C29,73.3,31.7,76.3,35.2,76.5z"/> - <path class="st0" d="M98.1,57.7l-43.4-2.4c0,0,10.9,2.5,22.2,3.1C88.6,59.1,98.1,57.7,98.1,57.7z"/> - <g id="light_green_4_"> - <path class="st4" d="M43.3,41.3c-0.4,7.4,5.3,13.7,12.6,14.1l42.8,2.3c7.4,0.4,13.7-5.2,14.1-12.6c0.4-7.4-5.3-13.7-12.6-14.1 - l-42.8-2.3C50,28.2,43.7,33.9,43.3,41.3z"/> - <g> - <g> - <path class="st4" d="M109.4,28.1c3.2,0.8,4.7,3.7,4.8,6.7c0,0.7-0.4,1.1-0.9,1c-0.5-0.1-0.8-0.3-0.9-1.3c0-2.3-1.2-4.1-3.2-4.8 - c0,0-1.5-0.3-1.2-1.2C108.2,28,108.8,28,109.4,28.1z"/> - </g> - </g> - <g> - <g> - <path class="st4" d="M50.2,25.8c0.1,1-1.4,1-1.4,1c-2.1,0.3-3.3,1.3-3.7,3.6c-0.3,1-0.5,1.2-1.1,1.2c-0.4,0-0.8-0.4-0.7-1.1 - c0.5-3,2.3-5.1,5.6-5.3C49.4,25.1,50.1,25.2,50.2,25.8z"/> - </g> - </g> - </g> - <path id="dark_greeen_3_" class="st0" d="M50.8,77.4l-15.6-0.8c-3.5-0.2-6.2-3.3-5.9-6.8l1.9-33.9l1.7,33.9c0,0-0.6,3.7,5,4.9 - L50.8,77.4z"/> - <path class="st0" d="M82.8,46.5c0,0-2.8-0.3-5.9,0c-3.1,0.3-4.7,1-4.7,1c-0.6,0-1.1-0.4-1.1-0.9v0c0-0.6,0.3-0.9,0.9-1.1 - c0,0,3-0.8,4.8-1c1.8-0.1,5.9,0,5.9,0c0.6,0,1.1,0.4,1.1,0.9l0,0C83.7,45.9,83.3,46.4,82.8,46.5z"/> - <g id="light_green_5_"> - <path class="st0" d="M62.9,44.4c0,0-2.1-1.2-4.8-0.9c-2,0.2-4.3,1.8-4.3,1.8c-0.8-0.8-1.3-1.9-1.5-3.1c-0.4-3.1,1.8-6,5-6.4 - s6,1.9,6.3,5C63.8,42.1,63.5,43.4,62.9,44.4z M101.8,47.9c0,0-2.1-1.7-4.1-2.2c-2.7-0.6-4.9,0.5-4.9,0.5 - c-0.5-1.1-0.7-2.4-0.4-3.7c0.7-3.1,3.7-5.1,6.8-4.4c3.1,0.7,5,3.7,4.4,6.8C103.3,46.1,102.7,47.1,101.8,47.9z"/> - </g> - </g> - <g id="ARMS_5_"> - <g id="BRAS_10_"> - <g id="ARM_20_"> - <path class="st0" d="M115.4,97.6c1-0.1,1.8-1.6,1.7-3.4l-0.2-6.2c-0.1-2.3-1.5-3.3-7.1-3c-1.6,0.1-6,0.4-6,0.4 - c-1,0.1-1.8,1.6-1.7,3.4l0.6,9.6C103.1,98.4,115.4,97.6,115.4,97.6z"/> - </g> - </g> - <g id="ARM_19_"> - <path class="st2" d="M144.5,67.9l0.5,0.5c2.5,2.6,2,7.3-0.6,9.8l-8.4,8.3c-3,3-11.7,7.8-16,3.5l-1-1c-2.5-2.6-0.5-4.7,2.1-7.2 - l14.1-13.9C137.8,65.3,142,65.4,144.5,67.9z"/> - <path class="st0" d="M144.5,67.9c0,0-2.8-2.7-8.1,1.6c-2.2,1.8-14.5,14-15.8,15.6c-1.8,2.3-1.6,3.9-1.6,3.9 - c-2.5-2.6-0.5-4.7,2.1-7.2l14.1-13.9C137.8,65.3,142,65.4,144.5,67.9z"/> - <g> - - <rect x="134" y="77.6" transform="matrix(-0.7025 -0.7117 0.7117 -0.7025 179.7647 230.6487)" class="st5" width="8.2" height="0.2"/> - - <rect x="135.1" y="76.6" transform="matrix(-0.7025 -0.7117 0.7117 -0.7025 182.4193 229.5794)" class="st5" width="8.2" height="0.2"/> - - <rect x="136.2" y="75.5" transform="matrix(-0.7025 -0.7117 0.7117 -0.7025 185.074 228.5101)" class="st5" width="8.2" height="0.2"/> - </g> - </g> - <g id="BRAS_8_"> - <g id="ARM_18_"> - <path class="st0" d="M33.5,96c-1-0.1-1.7-1.7-1.4-3.5l0.6-6.1c0.3-2.3,1.7-3.2,7.3-2.5c1.6,0.2,5.9,0.8,5.9,0.8 - c1,0.1,1.7,1.7,1.4,3.5l-1.3,9.5C45.8,97.7,33.5,96,33.5,96z"/> - </g> - </g> - <g id="ARM_16_"> - <path class="st2" d="M13.4,58.2l-0.6,0.3c-3.3,1.5-4.4,6.1-2.9,9.4l5,10.8c1.8,3.8,8.2,11.4,13.7,8.9l1.3-0.6 - c3.3-1.5,2.1-4.2,0.6-7.5l-8.3-18C20.6,58.1,16.7,56.7,13.4,58.2z"/> - <path class="st0" d="M13.4,58.2c0,0,3.5-1.6,7,4.4c1.4,2.5,8.7,18.2,9.3,20.2c0.9,2.8,0.2,4.2,0.2,4.2c3.3-1.5,2.1-4.2,0.6-7.5 - l-8.3-18C20.6,58.1,16.7,56.7,13.4,58.2z"/> - <g> - - <rect x="11.9" y="69.5" transform="matrix(0.9084 -0.4182 0.4182 0.9084 -27.6607 13.0783)" class="st5" width="8.2" height="0.2"/> - - <rect x="11.2" y="68.1" transform="matrix(0.9084 -0.4182 0.4182 0.9084 -27.131 12.678)" class="st5" width="8.2" height="0.2"/> - - <rect x="10.6" y="66.7" transform="matrix(0.9084 -0.4182 0.4182 0.9084 -26.6013 12.2776)" class="st5" width="8.2" height="0.2"/> - </g> - </g> - </g> - <path id="BELLY_5_" class="st2" d="M43.3,105.4c-6.7-0.1-8-2.6-8-9.1c0,0-0.2-10.9-0.2-12.2c0-2.2,4.5-3.9,8.9-3.8l61.8,1.3 - c4.4,0.1,8.8,1.9,8.7,4.2c0,1.3-0.7,12.1-0.7,12.1c-0.3,6.5-1.7,8.9-8.4,8.8L43.3,105.4z"/> - <ellipse id="SHADOW_5_" class="st6" cx="74.3" cy="163.5" rx="53.1" ry="6.7"/> - <g id="TXT_4_"> - <g> - <path class="st1" d="M64.3,91.8c0-0.1,0-0.4,0-0.5c0-0.1,0-0.1,0-0.2l0.7,0c0,0.1,0,0.1-0.1,0.4c0,0.1,0,0.1,0,0.2l0.8,0 - c0.1,0,0.2,0,0.2,0l0.3,0.3c0,0.1,0,0.1-0.1,0.3c0,0.8-0.1,1.4-0.2,1.6c-0.1,0.3-0.3,0.4-0.7,0.4c-0.1,0-0.2,0-0.5,0 - c0-0.3,0-0.4-0.1-0.6c0.2,0.1,0.4,0.1,0.5,0.1c0.2,0,0.2-0.1,0.3-0.4c0-0.2,0.1-0.7,0.1-1l-0.7,0c0,0.2,0,0.2-0.1,0.4 - c-0.2,0.7-0.5,1.2-1.3,1.7c-0.2-0.3-0.3-0.4-0.5-0.6c0.5-0.2,0.8-0.5,1-0.9c0.1-0.2,0.1-0.3,0.2-0.6l-0.5,0c-0.2,0-0.3,0-0.5,0 - l0-0.6c0.2,0,0.2,0,0.5,0L64.3,91.8z"/> - <path class="st1" d="M69.3,94.5c-0.3-0.4-0.6-0.7-1-1.1c-0.4,0.4-0.8,0.7-1.4,1c-0.1-0.3-0.2-0.4-0.4-0.6 - c0.5-0.2,0.9-0.4,1.2-0.7c0.3-0.3,0.6-0.6,0.8-1l-0.9,0c-0.3,0-0.4,0-0.6,0l0-0.6c0.1,0,0.2,0,0.4,0c0,0,0.1,0,0.2,0l1.2,0 - c0.2,0,0.2,0,0.3,0l0.3,0.3c-0.1,0.1-0.1,0.1-0.1,0.2c-0.2,0.4-0.3,0.7-0.6,1c0.4,0.3,0.6,0.5,1.1,1L69.3,94.5z"/> - <path class="st1" d="M70.5,94.5c0-0.2,0-0.3,0-0.6l0.1-2.1c0-0.3,0-0.3,0-0.5l0.7,0c0,0.1,0,0.3,0,0.5l0,0.5 - c0.6,0.2,1.1,0.4,1.6,0.8l-0.4,0.6c-0.3-0.3-0.8-0.5-1.1-0.7c-0.1-0.1-0.1-0.1-0.2-0.1l0,0.9c0,0.2,0,0.4,0,0.6L70.5,94.5z"/> - <path class="st1" d="M73.3,92.7c0.2,0,0.4,0,0.7,0.1l1.7,0c0.4,0,0.5,0,0.7,0l0,0.7c-0.2,0-0.3,0-0.7,0l-1.7,0 - c-0.4,0-0.5,0-0.7,0L73.3,92.7z"/> - <path class="st1" d="M77.9,93c0,0.1,0,0.1,0,0.1c-0.1,0.6-0.3,1-0.6,1.4c-0.2-0.1-0.4-0.2-0.6-0.3c0.3-0.4,0.5-0.9,0.6-1.4 - L77.9,93z M80.1,92.7c-0.1,0-0.2,0-0.6,0l-0.7,0l0,1.6c0,0.2,0,0.4,0,0.5l-0.7,0c0-0.1,0-0.3,0-0.6l0-1.6l-0.7,0 - c-0.3,0-0.4,0-0.5,0l0-0.6c0.1,0,0.2,0,0.6,0l0.7,0l0-0.1c0-0.2,0-0.3,0-0.4l0.7,0c0,0.1,0,0.2,0,0.4l0,0.1l0.8,0 - c-0.1-0.1-0.1-0.2-0.1-0.3c0-0.2,0.2-0.4,0.4-0.4c0.2,0,0.4,0.2,0.4,0.4c0,0.1-0.1,0.3-0.2,0.4L80.1,92.7z M79.6,92.8 - c0.1,0.5,0.3,1.1,0.6,1.4c-0.2,0.1-0.4,0.2-0.6,0.3c-0.3-0.5-0.4-0.8-0.5-1.4c0-0.1,0-0.1-0.1-0.2L79.6,92.8z M79.7,91.8 - c0,0.1,0.1,0.2,0.2,0.2c0.1,0,0.2-0.1,0.2-0.2c0-0.1-0.1-0.2-0.2-0.2C79.8,91.6,79.7,91.7,79.7,91.8z"/> - <path class="st1" d="M81.1,92.4c0.1,0.3,0.2,0.6,0.3,0.9l-0.6,0.2c-0.1-0.4-0.2-0.6-0.3-0.9L81.1,92.4z M83.2,92.5 - c0,0.1,0,0.1-0.1,0.2c-0.1,0.5-0.3,0.9-0.5,1.2c-0.2,0.3-0.5,0.5-0.8,0.7c-0.1,0.1-0.2,0.1-0.4,0.2c-0.1-0.2-0.2-0.3-0.4-0.5 - c0.7-0.3,1.1-0.6,1.4-1.2c0.1-0.3,0.2-0.5,0.2-0.8L83.2,92.5z M81.9,92.3c0.2,0.4,0.2,0.5,0.3,0.9l-0.6,0.2 - c-0.1-0.3-0.2-0.6-0.3-0.9L81.9,92.3z"/> - <path class="st1" d="M84,94.9c0-0.2,0-0.3,0-0.6l0.1-2.1c0-0.3,0-0.3,0-0.5l0.7,0c0,0.1,0,0.2,0,0.5l0,0.5 - c0.6,0.2,1.1,0.5,1.6,0.8L86,94.1c-0.3-0.2-0.7-0.5-1.1-0.7c-0.1,0-0.1,0-0.1-0.1c0,0,0,0,0,0l0,0.9c0,0.3,0,0.5,0,0.6L84,94.9z - M85.7,91.9c0.1,0.2,0.2,0.3,0.3,0.5l-0.3,0.2c-0.1-0.2-0.2-0.4-0.3-0.5L85.7,91.9z M86.2,91.7c0.1,0.1,0.2,0.3,0.4,0.5l-0.3,0.2 - c-0.1-0.2-0.2-0.4-0.3-0.5L86.2,91.7z"/> - </g> - <g> - <path class="st1" d="M70.6,97.8c-0.1,0-0.1,0-0.2,0.1c-0.1,0-0.1,0-0.2,0c-0.2,0-0.4-0.1-0.5-0.2c-0.1-0.1-0.2-0.3-0.2-0.6 - c0-0.3,0.1-0.5,0.2-0.6c0.1-0.1,0.3-0.2,0.5-0.2c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.2,0.1l0,0.3c-0.1-0.1-0.1-0.1-0.2-0.1 - c0,0-0.1,0-0.2,0c-0.1,0-0.2,0-0.3,0.1C70,96.7,70,96.9,70,97c0,0.2,0,0.3,0.1,0.4c0.1,0.1,0.1,0.1,0.3,0.1c0.1,0,0.1,0,0.2,0 - c0.1,0,0.1-0.1,0.2-0.1L70.6,97.8z"/> - <path class="st1" d="M71.5,96.3l0.3,0l0,1l0.2,0l0,0.3l-0.2,0l0,0.3l-0.3,0l0-0.3l-0.6,0l0-0.3L71.5,96.3z M71.5,96.6l-0.4,0.6 - l0.4,0L71.5,96.6z"/> - <path class="st1" d="M72.3,96.3l0.9,0l0,0.3l-0.6,0l0,0.3c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0.2,0,0.3,0.1,0.4,0.2 - s0.1,0.2,0.1,0.4c0,0.2-0.1,0.3-0.2,0.4c-0.1,0.1-0.3,0.1-0.4,0.1c-0.1,0-0.1,0-0.2,0c-0.1,0-0.1,0-0.2-0.1l0-0.3 - c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.1,0,0.2,0c0.1,0,0.2,0,0.3-0.1c0.1,0,0.1-0.1,0.1-0.2c0-0.1,0-0.2-0.1-0.2 - c-0.1-0.1-0.1-0.1-0.2-0.1c-0.1,0-0.1,0-0.2,0c-0.1,0-0.1,0-0.2,0.1L72.3,96.3z"/> - <path class="st1" d="M73.6,96.3l1,0l0,0.2L74,97.9l-0.3,0l0.5-1.3l-0.7,0L73.6,96.3z"/> - <path class="st1" d="M74.8,97.2c0-0.3,0.1-0.5,0.1-0.6c0.1-0.1,0.2-0.2,0.4-0.2c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.1,0.3,0.1,0.6 - c0,0.3-0.1,0.5-0.1,0.6c-0.1,0.1-0.2,0.2-0.4,0.2c-0.2,0-0.3-0.1-0.4-0.2S74.8,97.4,74.8,97.2z M75.4,96.6c-0.1,0-0.1,0-0.2,0.1 - c0,0.1-0.1,0.2-0.1,0.4c0,0.1,0,0.1,0,0.2l0.4-0.6c0,0,0,0,0,0C75.5,96.7,75.5,96.6,75.4,96.6z M75.2,97.6c0,0.1,0.1,0.1,0.2,0.1 - c0.1,0,0.1,0,0.2-0.1c0-0.1,0.1-0.2,0.1-0.4c0-0.1,0-0.1,0-0.2L75.2,97.6C75.2,97.6,75.2,97.6,75.2,97.6z"/> - <path class="st1" d="M76.2,96.4l0.4,0c0.2,0,0.4,0,0.5,0.1c0.1,0.1,0.1,0.2,0.1,0.4c0,0.2-0.1,0.3-0.2,0.4 - c-0.1,0.1-0.3,0.1-0.5,0.1l-0.1,0l0,0.6l-0.3,0L76.2,96.4z M76.5,96.7l0,0.5l0.1,0c0.1,0,0.2,0,0.2,0c0,0,0.1-0.1,0.1-0.2 - c0-0.1,0-0.1-0.1-0.2c0,0-0.1-0.1-0.2-0.1L76.5,96.7z"/> - <path class="st1" d="M77.5,97.2c0-0.3,0.1-0.5,0.1-0.6c0.1-0.1,0.2-0.2,0.4-0.2c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.1,0.3,0.1,0.6 - c0,0.3-0.1,0.5-0.1,0.6c-0.1,0.1-0.2,0.2-0.4,0.2c-0.2,0-0.3-0.1-0.4-0.2S77.5,97.5,77.5,97.2z M78,96.7c-0.1,0-0.1,0-0.2,0.1 - c0,0.1-0.1,0.2-0.1,0.4c0,0.1,0,0.1,0,0.2l0.4-0.6c0,0,0,0,0,0C78.1,96.7,78.1,96.7,78,96.7z M77.8,97.7c0,0.1,0.1,0.1,0.2,0.1 - c0.1,0,0.1,0,0.2-0.1c0-0.1,0.1-0.2,0.1-0.4c0-0.1,0-0.1,0-0.2L77.8,97.7C77.8,97.6,77.8,97.6,77.8,97.7z"/> - <path class="st1" d="M78.8,96.5l0.3,0c0.3,0,0.4,0.1,0.6,0.2c0.1,0.1,0.2,0.3,0.2,0.6c0,0.3-0.1,0.5-0.2,0.6 - c-0.1,0.1-0.3,0.2-0.6,0.2l-0.3,0L78.8,96.5z M79.1,96.7l0,1l0.1,0c0.1,0,0.2,0,0.3-0.1c0.1-0.1,0.1-0.2,0.1-0.4 - c0-0.2,0-0.3-0.1-0.4C79.4,96.8,79.3,96.8,79.1,96.7L79.1,96.7z"/> - </g> - <g> - <path class="st4" d="M64.3,91.6c0-0.1,0-0.4,0-0.5c0-0.1,0-0.1,0-0.2l0.7,0c0,0.1,0,0.1-0.1,0.4c0,0.1,0,0.1,0,0.2l0.8,0 - c0.1,0,0.2,0,0.2,0l0.3,0.3c0,0.1,0,0.1-0.1,0.3c0,0.8-0.1,1.4-0.2,1.6c-0.1,0.3-0.3,0.4-0.7,0.4c-0.1,0-0.2,0-0.5,0 - c0-0.3,0-0.4-0.1-0.6c0.2,0.1,0.4,0.1,0.5,0.1c0.2,0,0.2-0.1,0.3-0.4c0-0.2,0.1-0.7,0.1-1l-0.7,0c0,0.2,0,0.2-0.1,0.4 - c-0.2,0.7-0.5,1.2-1.3,1.7c-0.2-0.3-0.3-0.4-0.5-0.6c0.5-0.2,0.8-0.5,1-0.9c0.1-0.2,0.1-0.3,0.2-0.6l-0.5,0c-0.2,0-0.3,0-0.5,0 - l0-0.6c0.2,0,0.2,0,0.5,0L64.3,91.6z"/> - <path class="st4" d="M69.3,94.3c-0.3-0.4-0.6-0.7-1-1.1c-0.4,0.4-0.8,0.7-1.4,1c-0.1-0.3-0.2-0.4-0.4-0.6 - c0.5-0.2,0.9-0.4,1.2-0.7c0.3-0.3,0.6-0.6,0.8-1l-0.9,0c-0.3,0-0.4,0-0.6,0l0-0.6c0.1,0,0.2,0,0.4,0c0,0,0.1,0,0.2,0l1.2,0 - c0.2,0,0.2,0,0.3,0l0.3,0.3c-0.1,0.1-0.1,0.1-0.1,0.2c-0.2,0.4-0.3,0.7-0.6,1c0.4,0.3,0.6,0.5,1.1,1L69.3,94.3z"/> - <path class="st4" d="M70.5,94.3c0-0.2,0-0.3,0-0.6l0.1-2.1c0-0.3,0-0.3,0-0.5l0.7,0c0,0.1,0,0.3,0,0.5l0,0.5 - c0.6,0.2,1.1,0.4,1.6,0.8l-0.4,0.6c-0.3-0.3-0.8-0.5-1.1-0.7c-0.1-0.1-0.1-0.1-0.2-0.1l0,0.9c0,0.2,0,0.4,0,0.6L70.5,94.3z"/> - <path class="st4" d="M73.3,92.4c0.2,0,0.4,0,0.7,0.1l1.7,0c0.4,0,0.5,0,0.7,0l0,0.7c-0.2,0-0.3,0-0.7,0l-1.7,0 - c-0.4,0-0.5,0-0.7,0L73.3,92.4z"/> - <path class="st4" d="M77.9,92.7c0,0.1,0,0.1,0,0.1c-0.1,0.6-0.3,1-0.6,1.4c-0.2-0.1-0.4-0.2-0.6-0.3c0.3-0.4,0.5-0.9,0.6-1.4 - L77.9,92.7z M80.1,92.5c-0.1,0-0.2,0-0.6,0l-0.7,0l0,1.6c0,0.2,0,0.4,0,0.5l-0.7,0c0-0.1,0-0.3,0-0.6l0-1.6l-0.7,0 - c-0.3,0-0.4,0-0.5,0l0-0.6c0.1,0,0.2,0,0.6,0l0.7,0l0-0.1c0-0.2,0-0.3,0-0.4l0.7,0c0,0.1,0,0.2,0,0.4l0,0.1l0.8,0 - c-0.1-0.1-0.1-0.2-0.1-0.3c0-0.2,0.2-0.4,0.4-0.4c0.2,0,0.4,0.2,0.4,0.4c0,0.1-0.1,0.3-0.2,0.4L80.1,92.5z M79.6,92.6 - c0.1,0.5,0.3,1.1,0.6,1.4c-0.2,0.1-0.4,0.2-0.6,0.3c-0.3-0.5-0.4-0.8-0.5-1.4c0-0.1,0-0.1-0.1-0.2L79.6,92.6z M79.7,91.6 - c0,0.1,0.1,0.2,0.2,0.2c0.1,0,0.2-0.1,0.2-0.2c0-0.1-0.1-0.2-0.2-0.2C79.8,91.4,79.7,91.5,79.7,91.6z"/> - <path class="st4" d="M81.1,92.2c0.1,0.3,0.2,0.6,0.3,0.9l-0.6,0.2c-0.1-0.4-0.2-0.6-0.3-0.9L81.1,92.2z M83.2,92.3 - c0,0.1,0,0.1-0.1,0.2c-0.1,0.5-0.3,0.9-0.5,1.2c-0.2,0.3-0.5,0.5-0.8,0.7c-0.1,0.1-0.2,0.1-0.4,0.2c-0.1-0.2-0.2-0.3-0.4-0.5 - c0.7-0.3,1.1-0.6,1.4-1.2c0.1-0.3,0.2-0.5,0.2-0.8L83.2,92.3z M81.9,92.1c0.2,0.4,0.2,0.5,0.3,0.9l-0.6,0.2 - c-0.1-0.3-0.2-0.6-0.3-0.9L81.9,92.1z"/> - <path class="st4" d="M84,94.7c0-0.2,0-0.3,0-0.6l0.1-2.1c0-0.3,0-0.3,0-0.5l0.7,0c0,0.1,0,0.2,0,0.5l0,0.5 - c0.6,0.2,1.1,0.5,1.6,0.8L86,93.9c-0.3-0.2-0.7-0.5-1.1-0.7c-0.1,0-0.1,0-0.1-0.1c0,0,0,0,0,0l0,0.9c0,0.3,0,0.5,0,0.6L84,94.7z - M85.7,91.7c0.1,0.2,0.2,0.3,0.3,0.5l-0.3,0.2c-0.1-0.2-0.2-0.4-0.3-0.5L85.7,91.7z M86.2,91.5c0.1,0.1,0.2,0.3,0.4,0.5l-0.3,0.2 - c-0.1-0.2-0.2-0.4-0.3-0.5L86.2,91.5z"/> - </g> - <g> - <path class="st4" d="M70.6,97.6c-0.1,0-0.1,0-0.2,0.1c-0.1,0-0.1,0-0.2,0c-0.2,0-0.4-0.1-0.5-0.2s-0.2-0.3-0.2-0.6 - c0-0.3,0.1-0.5,0.2-0.6c0.1-0.1,0.3-0.2,0.5-0.2c0.1,0,0.1,0,0.2,0s0.1,0,0.2,0.1l0,0.3c-0.1-0.1-0.1-0.1-0.2-0.1 - c0,0-0.1,0-0.2,0c-0.1,0-0.2,0-0.3,0.1C70,96.5,70,96.6,70,96.8c0,0.2,0,0.3,0.1,0.4c0.1,0.1,0.1,0.1,0.3,0.1c0.1,0,0.1,0,0.2,0 - c0.1,0,0.1-0.1,0.2-0.1L70.6,97.6z"/> - <path class="st4" d="M71.5,96.1l0.3,0l0,1l0.2,0l0,0.3l-0.2,0l0,0.3l-0.3,0l0-0.3l-0.6,0l0-0.3L71.5,96.1z M71.5,96.4L71.1,97 - l0.4,0L71.5,96.4z"/> - <path class="st4" d="M72.3,96.1l0.9,0l0,0.3l-0.6,0l0,0.3c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0.2,0,0.3,0.1,0.4,0.2 - c0.1,0.1,0.1,0.2,0.1,0.4c0,0.2-0.1,0.3-0.2,0.4c-0.1,0.1-0.3,0.1-0.4,0.1c-0.1,0-0.1,0-0.2,0c-0.1,0-0.1,0-0.2-0.1l0-0.3 - c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.1,0,0.2,0c0.1,0,0.2,0,0.3-0.1c0.1,0,0.1-0.1,0.1-0.2c0-0.1,0-0.2-0.1-0.2 - c-0.1-0.1-0.1-0.1-0.2-0.1c-0.1,0-0.1,0-0.2,0c-0.1,0-0.1,0-0.2,0.1L72.3,96.1z"/> - <path class="st4" d="M73.6,96.1l1,0l0,0.2L74,97.7l-0.3,0l0.5-1.3l-0.7,0L73.6,96.1z"/> - <path class="st4" d="M74.8,96.9c0-0.3,0.1-0.5,0.1-0.6c0.1-0.1,0.2-0.2,0.4-0.2c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.1,0.3,0.1,0.6 - c0,0.3-0.1,0.5-0.1,0.6c-0.1,0.1-0.2,0.2-0.4,0.2c-0.2,0-0.3-0.1-0.4-0.2S74.8,97.2,74.8,96.9z M75.4,96.4c-0.1,0-0.1,0-0.2,0.1 - c0,0.1-0.1,0.2-0.1,0.4c0,0.1,0,0.1,0,0.2l0.4-0.6c0,0,0,0,0,0C75.5,96.4,75.5,96.4,75.4,96.4z M75.2,97.4c0,0.1,0.1,0.1,0.2,0.1 - c0.1,0,0.1,0,0.2-0.1c0-0.1,0.1-0.2,0.1-0.4c0-0.1,0-0.1,0-0.2L75.2,97.4C75.2,97.4,75.2,97.4,75.2,97.4z"/> - <path class="st4" d="M76.2,96.2l0.4,0c0.2,0,0.4,0,0.5,0.1c0.1,0.1,0.1,0.2,0.1,0.4c0,0.2-0.1,0.3-0.2,0.4 - c-0.1,0.1-0.3,0.1-0.5,0.1l-0.1,0l0,0.6l-0.3,0L76.2,96.2z M76.5,96.5l0,0.5l0.1,0c0.1,0,0.2,0,0.2,0c0,0,0.1-0.1,0.1-0.2 - c0-0.1,0-0.1-0.1-0.2c0,0-0.1-0.1-0.2-0.1L76.5,96.5z"/> - <path class="st4" d="M77.5,97c0-0.3,0.1-0.5,0.1-0.6c0.1-0.1,0.2-0.2,0.4-0.2c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.1,0.3,0.1,0.6 - c0,0.3-0.1,0.5-0.1,0.6c-0.1,0.1-0.2,0.2-0.4,0.2c-0.2,0-0.3-0.1-0.4-0.2S77.5,97.3,77.5,97z M78,96.5c-0.1,0-0.1,0-0.2,0.1 - c0,0.1-0.1,0.2-0.1,0.4c0,0.1,0,0.1,0,0.2l0.4-0.6c0,0,0,0,0,0C78.1,96.5,78.1,96.5,78,96.5z M77.8,97.4c0,0.1,0.1,0.1,0.2,0.1 - c0.1,0,0.1,0,0.2-0.1c0-0.1,0.1-0.2,0.1-0.4c0-0.1,0-0.1,0-0.2L77.8,97.4C77.8,97.4,77.8,97.4,77.8,97.4z"/> - <path class="st4" d="M78.8,96.2l0.3,0c0.3,0,0.4,0.1,0.6,0.2c0.1,0.1,0.2,0.3,0.2,0.6c0,0.3-0.1,0.5-0.2,0.6 - c-0.1,0.1-0.3,0.2-0.6,0.2l-0.3,0L78.8,96.2z M79.1,96.5l0,1l0.1,0c0.1,0,0.2,0,0.3-0.1c0.1-0.1,0.1-0.2,0.1-0.4 - c0-0.2,0-0.3-0.1-0.4C79.4,96.6,79.3,96.5,79.1,96.5L79.1,96.5z"/> - </g> - </g> -</g> +<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 155.9 184.3" xml:space="preserve"> + <style> + .st0{fill:#006d60}.st1{fill:#00564a}.st2{fill:#009486}.st3{fill:#2b6b5f}.st4{fill:#e7f9e4}.st5{fill:#71afa3} + </style> + <g id="FOOTS_1_"> + <path class="st0" d="m55.8 134.7 37.2-.3c1.4 0 2.5-1.2 2.5-2.6 0-1.4-1.2-2.5-2.6-2.5l-37.2.3c-1.4 0-2.5 1.2-2.5 2.6.1 1.3 1.2 2.5 2.6 2.5z"/> + <path class="st1" d="m89.2 129.3-29.5.2s7.5 1.3 15.2 1.2c7.9 0 14.3-1.4 14.3-1.4z"/> + </g> + <g id="LEGS_5_"> + <path transform="matrix(-1 .00772 -.00772 -1 149.368 218.272)" class="st1" d="M40.6 102.5h67.3v13.8H40.6z"/> + <path class="st2" d="M38.4 116.2c.1 6.5 5.4 11.8 11.9 11.8l48.2-.4c6.5 0 11.7-5.5 11.7-12v-1.9c0-1.6-1.3-2.9-2.9-2.9l-66 .5c-1.6 0-2.9 1.3-2.9 2.9v2z"/> + <path transform="matrix(-1 .00772 -.00772 -1 149.335 215.458)" class="st3" d="M41.4 107.9h65.8v.2H41.4z"/> + <path transform="matrix(-1 .00772 -.00772 -1 149.354 217.11)" class="st3" d="M41.4 108.7h65.8v.2H41.4z"/> + <path transform="matrix(-1 .00772 -.00772 -1 149.374 218.761)" class="st3" d="M41.4 109.6h65.8v.2H41.4z"/> + <path class="st0" d="m75.1 127.8 23.3-.2c6.5-.1 11.8-5.5 11.7-12 0 0-1 5.3-8.2 8-5.3 2-12.8 1.6-26.9 1.7-14.1.1-23 .6-28.4-1.3-7.2-2.6-8.3-7.8-8.3-7.8.1 6.5 5.4 11.8 11.9 11.8l24.9-.2z"/> + </g> + <g id="NECK_5_"> + <path class="st1" d="m51.3 82.6.1-1.3 2.9-5s.3-.7 2-.6c.8 0 38.5 2.1 39.3 2.1 1.8.1 2 .8 2 .8l1.6 3.8-.1 1.3-47.8-1.1z"/> + <path transform="rotate(-86.884 75.824 78.055) scale(.99998)" class="st3" d="M75.7 57.7h.2v40.7h-.2z"/> + <path transform="rotate(-86.884 75.779 78.88) scale(.99998)" class="st3" d="M75.7 57.8h.2V100h-.2z"/> + </g> + <g id="HEAD_18_"> + <path id="dark_greeen_9_" class="st2" d="m35.2 76.5 16.4.9L53 75c.7-1.2 2.3-1 2.3-1L97 76.3s1.5-.1 2.2 1.3c.7 1.4 1.2 2.5 1.2 2.5l16.1.9c3.5.2 6.5-2.5 6.7-6l2.7-49.8c.2-3.5-2.5-6.5-6-6.7l-81.1-4.4c-3.5-.2-6.5 2.5-6.7 6l-2.7 49.8c-.4 3.4 2.3 6.4 5.8 6.6z"/> + <path class="st0" d="m98.1 57.7-43.4-2.4s10.9 2.5 22.2 3.1c11.7.7 21.2-.7 21.2-.7z"/> + <g id="light_green_4_"> + <path class="st4" d="M43.3 41.3c-.4 7.4 5.3 13.7 12.6 14.1l42.8 2.3c7.4.4 13.7-5.2 14.1-12.6.4-7.4-5.3-13.7-12.6-14.1l-42.8-2.3c-7.4-.5-13.7 5.2-14.1 12.6zM109.4 28.1c3.2.8 4.7 3.7 4.8 6.7 0 .7-.4 1.1-.9 1-.5-.1-.8-.3-.9-1.3 0-2.3-1.2-4.1-3.2-4.8 0 0-1.5-.3-1.2-1.2.2-.5.8-.5 1.4-.4zM50.2 25.8c.1 1-1.4 1-1.4 1-2.1.3-3.3 1.3-3.7 3.6-.3 1-.5 1.2-1.1 1.2-.4 0-.8-.4-.7-1.1.5-3 2.3-5.1 5.6-5.3.5-.1 1.2 0 1.3.6z"/> + </g> + <path id="dark_greeen_3_" class="st0" d="m50.8 77.4-15.6-.8c-3.5-.2-6.2-3.3-5.9-6.8l1.9-33.9 1.7 33.9s-.6 3.7 5 4.9l12.9 2.7z"/> + <path class="st0" d="M82.8 46.5s-2.8-.3-5.9 0c-3.1.3-4.7 1-4.7 1-.6 0-1.1-.4-1.1-.9 0-.6.3-.9.9-1.1 0 0 3-.8 4.8-1 1.8-.1 5.9 0 5.9 0 .6 0 1.1.4 1.1.9-.1.5-.5 1-1 1.1z"/> + <path class="st0" d="M62.9 44.4s-2.1-1.2-4.8-.9c-2 .2-4.3 1.8-4.3 1.8-.8-.8-1.3-1.9-1.5-3.1-.4-3.1 1.8-6 5-6.4s6 1.9 6.3 5c.2 1.3-.1 2.6-.7 3.6zm38.9 3.5s-2.1-1.7-4.1-2.2c-2.7-.6-4.9.5-4.9.5-.5-1.1-.7-2.4-.4-3.7.7-3.1 3.7-5.1 6.8-4.4 3.1.7 5 3.7 4.4 6.8-.3 1.2-.9 2.2-1.8 3z" id="light_green_5_"/> + </g> + <g id="ARMS_5_"> + <g id="BRAS_10_"> + <path class="st0" d="M115.4 97.6c1-.1 1.8-1.6 1.7-3.4l-.2-6.2c-.1-2.3-1.5-3.3-7.1-3-1.6.1-6 .4-6 .4-1 .1-1.8 1.6-1.7 3.4l.6 9.6c.4 0 12.7-.8 12.7-.8z" id="ARM_20_"/> + </g> + <g id="ARM_19_"> + <path class="st2" d="m144.5 67.9.5.5c2.5 2.6 2 7.3-.6 9.8l-8.4 8.3c-3 3-11.7 7.8-16 3.5l-1-1c-2.5-2.6-.5-4.7 2.1-7.2l14.1-13.9c2.6-2.6 6.8-2.5 9.3 0z"/> + <path class="st0" d="M144.5 67.9s-2.8-2.7-8.1 1.6c-2.2 1.8-14.5 14-15.8 15.6-1.8 2.3-1.6 3.9-1.6 3.9-2.5-2.6-.5-4.7 2.1-7.2l14.1-13.9c2.6-2.6 6.8-2.5 9.3 0z"/> + <path transform="rotate(-134.628 138.09 77.75)" class="st5" d="M134 77.6h8.2v.2H134z"/> + <path transform="rotate(-134.628 139.195 76.66)" class="st5" d="M135.1 76.6h8.2v.2h-8.2z"/> + <path transform="rotate(-134.628 140.298 75.571)" class="st5" d="M136.2 75.5h8.2v.2h-8.2z"/> + </g> + <g id="BRAS_8_"> + <path class="st0" d="M33.5 96c-1-.1-1.7-1.7-1.4-3.5l.6-6.1c.3-2.3 1.7-3.2 7.3-2.5 1.6.2 5.9.8 5.9.8 1 .1 1.7 1.7 1.4 3.5L46 97.7c-.2 0-12.5-1.7-12.5-1.7z" id="ARM_18_"/> + </g> + <g id="ARM_16_"> + <path class="st2" d="m13.4 58.2-.6.3c-3.3 1.5-4.4 6.1-2.9 9.4l5 10.8c1.8 3.8 8.2 11.4 13.7 8.9l1.3-.6c3.3-1.5 2.1-4.2.6-7.5l-8.3-18c-1.6-3.4-5.5-4.8-8.8-3.3z"/> + <path class="st0" d="M13.4 58.2s3.5-1.6 7 4.4c1.4 2.5 8.7 18.2 9.3 20.2.9 2.8.2 4.2.2 4.2 3.3-1.5 2.1-4.2.6-7.5l-8.3-18c-1.6-3.4-5.5-4.8-8.8-3.3z"/> + <path transform="rotate(-24.72 16.01 69.65)" class="st5" d="M11.9 69.5h8.2v.2h-8.2z"/> + <path transform="rotate(-24.72 15.362 68.242)" class="st5" d="M11.2 68.1h8.2v.2h-8.2z"/> + <path transform="rotate(-24.72 14.713 66.833)" class="st5" d="M10.6 66.7h8.2v.2h-8.2z"/> + </g> + </g> + <path id="BELLY_5_" class="st2" d="M43.3 105.4c-6.7-.1-8-2.6-8-9.1 0 0-.2-10.9-.2-12.2 0-2.2 4.5-3.9 8.9-3.8l61.8 1.3c4.4.1 8.8 1.9 8.7 4.2 0 1.3-.7 12.1-.7 12.1-.3 6.5-1.7 8.9-8.4 8.8l-62.1-1.3z"/> + <ellipse id="SHADOW_5_" cx="74.3" cy="163.5" rx="53.1" ry="6.7" fill="#dcf4d7"/> + <g id="TXT_4_"> + <path class="st1" d="M64.3 91.8v-.7h.7c0 .1 0 .1-.1.4v.2h1l.3.3c0 .1 0 .1-.1.3 0 .8-.1 1.4-.2 1.6-.1.3-.3.4-.7.4h-.5c0-.3 0-.4-.1-.6.2.1.4.1.5.1.2 0 .2-.1.3-.4 0-.2.1-.7.1-1h-.7c0 .2 0 .2-.1.4-.2.7-.5 1.2-1.3 1.7-.2-.3-.3-.4-.5-.6.5-.2.8-.5 1-.9.1-.2.1-.3.2-.6h-1v-.6h1.2zM69.3 94.5c-.3-.4-.6-.7-1-1.1-.4.4-.8.7-1.4 1-.1-.3-.2-.4-.4-.6.5-.2.9-.4 1.2-.7.3-.3.6-.6.8-1H67v-.6h2.1l.3.3c-.1.1-.1.1-.1.2-.2.4-.3.7-.6 1 .4.3.6.5 1.1 1l-.5.5zM70.5 94.5v-.6l.1-2.1v-.5h.7v1c.6.2 1.1.4 1.6.8l-.4.6c-.3-.3-.8-.5-1.1-.7-.1-.1-.1-.1-.2-.1v1.5l-.7.1zM73.3 92.7c.2 0 .4 0 .7.1h2.4v.7H73.3v-.8zM77.9 93v.1c-.1.6-.3 1-.6 1.4l-.6-.3c.3-.4.5-.9.6-1.4l.6.2zm2.2-.3H78.8v2.1h-.7v-2.2h-1.2V92H78.2v-.5h.7v.5h.8c-.1-.1-.1-.2-.1-.3 0-.2.2-.4.4-.4s.4.2.4.4c0 .1-.1.3-.2.4l-.1.6zm-.5.1c.1.5.3 1.1.6 1.4l-.6.3c-.3-.5-.4-.8-.5-1.4 0-.1 0-.1-.1-.2l.6-.1zm.1-1c0 .1.1.2.2.2s.2-.1.2-.2-.1-.2-.2-.2-.2.1-.2.2zM81.1 92.4l.3.9-.6.2c-.1-.4-.2-.6-.3-.9l.6-.2zm2.1.1c0 .1 0 .1-.1.2-.1.5-.3.9-.5 1.2-.2.3-.5.5-.8.7-.1.1-.2.1-.4.2-.1-.2-.2-.3-.4-.5.7-.3 1.1-.6 1.4-1.2.1-.3.2-.5.2-.8l.6.2zm-1.3-.2c.2.4.2.5.3.9l-.6.2-.3-.9.6-.2zM84 94.9v-.6l.1-2.1v-.5h.7v1c.6.2 1.1.5 1.6.8l-.4.6c-.3-.2-.7-.5-1.1-.7-.1 0-.1 0-.1-.1v1.5l-.8.1zm1.7-3c.1.2.2.3.3.5l-.3.2c-.1-.2-.2-.4-.3-.5l.3-.2zm.5-.2c.1.1.2.3.4.5l-.3.2c-.1-.2-.2-.4-.3-.5l.2-.2z"/> + <g> + <path class="st1" d="M70.6 97.8c-.1 0-.1 0-.2.1h-.2c-.2 0-.4-.1-.5-.2-.1-.1-.2-.3-.2-.6s.1-.5.2-.6c.1-.1.3-.2.5-.2h.2c.1 0 .1 0 .2.1v.3c-.1-.1-.1-.1-.2-.1h-.2c-.1 0-.2 0-.3.1.1 0 .1.2.1.3 0 .2 0 .3.1.4.1.1.1.1.3.1h.2c.1 0 .1-.1.2-.1l-.2.4zM71.5 96.3h.3v1h.2v.3h-.2v.3h-.3v-.3h-.6v-.3l.6-1zm0 .3-.4.6h.4v-.6zM72.3 96.3h.9v.3h-.6v.3h.2c.2 0 .3.1.4.2s.1.2.1.4-.1.3-.2.4c-.1.1-.3.1-.4.1h-.2c-.1 0-.1 0-.2-.1v-.3c.1 0 .1.1.2.1h.2c.1 0 .2 0 .3-.1.1 0 .1-.1.1-.2s0-.2-.1-.2c-.1-.1-.1-.1-.2-.1h-.2c-.1 0-.1 0-.2.1l-.1-.9zM73.6 96.3h1v.2l-.6 1.4h-.3l.5-1.3h-.7l.1-.3zM74.8 97.2c0-.3.1-.5.1-.6.1-.1.2-.2.4-.2s.3.1.4.2c.1.1.1.3.1.6s-.1.5-.1.6c-.1.1-.2.2-.4.2s-.3-.1-.4-.2-.1-.4-.1-.6zm.6-.6c-.1 0-.1 0-.2.1 0 .1-.1.2-.1.4v.2l.4-.6s0-.1-.1-.1zm-.2 1c0 .1.1.1.2.1s.1 0 .2-.1c0-.1.1-.2.1-.4V97l-.5.6zM76.2 96.4h.4c.2 0 .4 0 .5.1.1.1.1.2.1.4s-.1.3-.2.4c-.1.1-.3.1-.5.1h-.1v.6h-.3l.1-1.6zm.3.3v.5H76.8s.1-.1.1-.2 0-.1-.1-.2c0 0-.1-.1-.2-.1h-.1zM77.5 97.2c0-.3.1-.5.1-.6.1-.1.2-.2.4-.2s.3.1.4.2c.1.1.1.3.1.6s-.1.5-.1.6c-.1.1-.2.2-.4.2s-.3-.1-.4-.2-.1-.3-.1-.6zm.5-.5c-.1 0-.1 0-.2.1 0 .1-.1.2-.1.4v.2l.4-.6c0-.1 0-.1-.1-.1zm-.2 1c0 .1.1.1.2.1s.1 0 .2-.1c0-.1.1-.2.1-.4v-.2l-.5.6c0-.1 0-.1 0 0zM78.8 96.5h.3c.3 0 .4.1.6.2.1.1.2.3.2.6s-.1.5-.2.6c-.1.1-.3.2-.6.2h-.3v-1.6zm.3.2v1h.1c.1 0 .2 0 .3-.1.1-.1.1-.2.1-.4s0-.3-.1-.4c-.1 0-.2 0-.4-.1z"/> + </g> + <g> + <path class="st4" d="M64.3 91.6v-.7h.7c0 .1 0 .1-.1.4v.2h1l.3.3c0 .1 0 .1-.1.3 0 .8-.1 1.4-.2 1.6-.1.3-.3.4-.7.4h-.5c0-.3 0-.4-.1-.6.2.1.4.1.5.1.2 0 .2-.1.3-.4 0-.2.1-.7.1-1h-.7c0 .2 0 .2-.1.4-.2.7-.5 1.2-1.3 1.7-.2-.3-.3-.4-.5-.6.5-.2.8-.5 1-.9.1-.2.1-.3.2-.6h-1v-.6h1.2zM69.3 94.3c-.3-.4-.6-.7-1-1.1-.4.4-.8.7-1.4 1-.1-.3-.2-.4-.4-.6.5-.2.9-.4 1.2-.7.3-.3.6-.6.8-1H67v-.6h2.1l.3.3c-.1.1-.1.1-.1.2-.2.4-.3.7-.6 1 .4.3.6.5 1.1 1l-.5.5zM70.5 94.3v-.6l.1-2.1v-.5h.7v1c.6.2 1.1.4 1.6.8l-.4.6c-.3-.3-.8-.5-1.1-.7-.1-.1-.1-.1-.2-.1v1.5l-.7.1zM73.3 92.4c.2 0 .4 0 .7.1h2.4v.7H73.3v-.8zM77.9 92.7v.1c-.1.6-.3 1-.6 1.4l-.6-.3c.3-.4.5-.9.6-1.4l.6.2zm2.2-.2H78.8v2.1h-.7v-2.2h-1.2v-.6H78.2v-.5h.7v.5h.8c-.1-.1-.1-.2-.1-.3 0-.2.2-.4.4-.4s.4.2.4.4c0 .1-.1.3-.2.4l-.1.6zm-.5.1c.1.5.3 1.1.6 1.4l-.6.3c-.3-.5-.4-.8-.5-1.4 0-.1 0-.1-.1-.2l.6-.1zm.1-1c0 .1.1.2.2.2s.2-.1.2-.2-.1-.2-.2-.2-.2.1-.2.2zM81.1 92.2l.3.9-.6.2c-.1-.4-.2-.6-.3-.9l.6-.2zm2.1.1c0 .1 0 .1-.1.2-.1.5-.3.9-.5 1.2-.2.3-.5.5-.8.7-.1.1-.2.1-.4.2-.1-.2-.2-.3-.4-.5.7-.3 1.1-.6 1.4-1.2.1-.3.2-.5.2-.8l.6.2zm-1.3-.2c.2.4.2.5.3.9l-.6.2-.3-.9.6-.2zM84 94.7v-.6l.1-2.1v-.5h.7v1c.6.2 1.1.5 1.6.8l-.4.6c-.3-.2-.7-.5-1.1-.7-.1 0-.1 0-.1-.1v1.5l-.8.1zm1.7-3c.1.2.2.3.3.5l-.3.2c-.1-.2-.2-.4-.3-.5l.3-.2zm.5-.2c.1.1.2.3.4.5l-.3.2c-.1-.2-.2-.4-.3-.5l.2-.2z"/> + </g> + <g> + <path class="st4" d="M70.6 97.6c-.1 0-.1 0-.2.1h-.2c-.2 0-.4-.1-.5-.2s-.2-.3-.2-.6.1-.5.2-.6c.1-.1.3-.2.5-.2h.2c.1 0 .1 0 .2.1v.3c-.1-.1-.1-.1-.2-.1h-.2c-.1 0-.2 0-.3.1.1 0 .1.1.1.3 0 .2 0 .3.1.4.1.1.1.1.3.1h.2c.1 0 .1-.1.2-.1l-.2.4zM71.5 96.1h.3v1h.2v.3h-.2v.3h-.3v-.3h-.6v-.3l.6-1zm0 .3-.4.6h.4v-.6zM72.3 96.1h.9v.3h-.6v.3h.2c.2 0 .3.1.4.2.1.1.1.2.1.4s-.1.3-.2.4c-.1.1-.3.1-.4.1h-.2c-.1 0-.1 0-.2-.1v-.3c.1 0 .1.1.2.1h.2c.1 0 .2 0 .3-.1.1 0 .1-.1.1-.2s0-.2-.1-.2c-.1-.1-.1-.1-.2-.1h-.2c-.1 0-.1 0-.2.1l-.1-.9zM73.6 96.1h1v.2l-.6 1.4h-.3l.5-1.3h-.7l.1-.3zM74.8 96.9c0-.3.1-.5.1-.6.1-.1.2-.2.4-.2s.3.1.4.2c.1.1.1.3.1.6s-.1.5-.1.6c-.1.1-.2.2-.4.2s-.3-.1-.4-.2-.1-.3-.1-.6zm.6-.5c-.1 0-.1 0-.2.1 0 .1-.1.2-.1.4v.2l.4-.6c0-.1 0-.1-.1-.1zm-.2 1c0 .1.1.1.2.1s.1 0 .2-.1c0-.1.1-.2.1-.4v-.2l-.5.6zM76.2 96.2h.4c.2 0 .4 0 .5.1.1.1.1.2.1.4s-.1.3-.2.4c-.1.1-.3.1-.5.1h-.1v.6h-.3l.1-1.6zm.3.3v.5H76.8s.1-.1.1-.2 0-.1-.1-.2c0 0-.1-.1-.2-.1h-.1zM77.5 97c0-.3.1-.5.1-.6.1-.1.2-.2.4-.2s.3.1.4.2c.1.1.1.3.1.6s-.1.5-.1.6c-.1.1-.2.2-.4.2s-.3-.1-.4-.2-.1-.3-.1-.6zm.5-.5c-.1 0-.1 0-.2.1 0 .1-.1.2-.1.4v.2l.4-.6c0-.1 0-.1-.1-.1zm-.2.9c0 .1.1.1.2.1s.1 0 .2-.1c0-.1.1-.2.1-.4v-.2l-.5.6zM78.8 96.2h.3c.3 0 .4.1.6.2.1.1.2.3.2.6s-.1.5-.2.6c-.1.1-.3.2-.6.2h-.3v-1.6zm.3.3v1h.1c.1 0 .2 0 .3-.1.1-.1.1-.2.1-.4s0-.3-.1-.4c-.1 0-.2-.1-.4-.1z"/> + </g> + </g> </svg> diff --git a/app/Resources/js/modules/Clipboard.ts b/app/Resources/js/modules/Clipboard.ts index 09718bcf31..defb176a08 100644 --- a/app/Resources/js/modules/Clipboard.ts +++ b/app/Resources/js/modules/Clipboard.ts @@ -5,13 +5,13 @@ const Clipboard = (): void => { if (buttons) { for (let i = 0; i < buttons.length; i++) { const button: HTMLButtonElement = buttons[i]; - const textArea: HTMLTextAreaElement | null = document.querySelector( - `textarea[id="${button.dataset.clipboardTarget}"]` + const element: HTMLFormElement | null = document.querySelector( + `[id="${button.dataset.clipboardTarget}"]` ); - if (textArea) { + if (element) { button.addEventListener("click", () => { - textArea.select(); - textArea.setSelectionRange(0, textArea.value.length); + element.select(); + element.setSelectionRange(0, element.value.length); document.execCommand("copy"); }); } diff --git a/app/Resources/js/modules/ThemePicker.ts b/app/Resources/js/modules/ThemePicker.ts index e7a2b13a45..57b0a75bbc 100644 --- a/app/Resources/js/modules/ThemePicker.ts +++ b/app/Resources/js/modules/ThemePicker.ts @@ -4,11 +4,10 @@ const ThemePicker = (): void => { const iframe: HTMLIFrameElement | null = document.querySelector( `iframe[id="embeddable_player"]` ); - const iframeTextArea: HTMLTextAreaElement | null = document.querySelector( - `textarea[id="iframe"]` - ); - const urlTextArea: HTMLTextAreaElement | null = - document.querySelector(`textarea[id="url"]`); + const iframeTextArea: HTMLFormElement | null = + document.querySelector(`[id="iframe"]`); + const urlTextArea: HTMLFormElement | null = + document.querySelector(`[id="url"]`); if (buttons && iframe && iframeTextArea && urlTextArea) { for (let i = 0; i < buttons.length; i++) { diff --git a/app/Resources/styles/breadcrumb.css b/app/Resources/styles/breadcrumb.css index ac4a3fabb6..44716ecead 100644 --- a/app/Resources/styles/breadcrumb.css +++ b/app/Resources/styles/breadcrumb.css @@ -1,5 +1,5 @@ .breadcrumb { - @apply inline-flex flex-wrap px-1 text-sm; + @apply inline-flex flex-wrap px-1; } .breadcrumb-item + .breadcrumb-item::before { diff --git a/app/Resources/styles/switch.css b/app/Resources/styles/switch.css index b124f0f43f..be217ecf11 100644 --- a/app/Resources/styles/switch.css +++ b/app/Resources/styles/switch.css @@ -15,25 +15,49 @@ } &:checked + .form-switch-slider::after { - @apply transform translate-x-1; - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%23ffffff'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='m10 15.172 9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z'/%3E%3C/svg%3E%0A"); + @apply transform translate-x-0 left-2; + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='m10 15.172 9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z'/%3E%3C/svg%3E%0A"); + } + + &:checked + .form-switch-slider.form-switch-slider--small::before { + @apply translate-x-6; + } + + &:checked + .form-switch-slider.form-switch-slider--small::after { + @apply left-1; } } .form-switch-slider { - @apply relative inset-0 flex-shrink-0 w-[72px] h-10 transition duration-200 bg-gray-400 border-black rounded-full cursor-pointer border-3; + @apply relative inset-0 flex-shrink-0 w-16 h-8 transition duration-200 bg-gray-400 border-black rounded-full cursor-pointer border-3; + + &.form-switch-slider--small { + @apply w-12 h-6; + + &::before { + @apply w-4 h-4; + } + + &::after { + @apply translate-x-5; + left: 0; + top: -1px; + } + } &::before { - @apply absolute z-10 w-[28px] h-[28px] transition duration-200 bg-white rounded-full ring-1 ring-black ring-opacity-5 shadow; + @apply absolute z-10 w-6 h-6 transition duration-200 bg-white rounded-full shadow ring-1 ring-black ring-opacity-5; content: ""; - left: 3px; - bottom: 3px; + left: 1px; + bottom: 1px; } &::after { - @apply absolute w-6 h-6 transition duration-150 transform translate-x-8 top-1 left-1; + @apply absolute w-5 h-5 transition duration-150 transform translate-x-5; - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='m12 10.586 4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E%0A"); + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='m12 10.586 4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E%0A"); + top: 3px; + left: 10px; } } } diff --git a/app/Views/Components/Alert.php b/app/Views/Components/Alert.php new file mode 100644 index 0000000000..478c42c20f --- /dev/null +++ b/app/Views/Components/Alert.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +namespace App\Views\Components; + +use ViewComponents\Component; + +class Alert extends Component +{ + protected ?string $glyph = null; + + protected ?string $title = null; + + /** + * @var 'default'|'success'|'danger'|'warning' + */ + protected string $variant = 'default'; + + public function render(): string + { + $variantClasses = [ + 'default' => 'text-gray-800 bg-gray-100 border-gray-300', + 'success' => 'text-pine-900 bg-pine-100 border-pine-300', + 'danger' => 'text-red-900 bg-red-100 border-red-300', + 'warning' => 'text-yellow-900 bg-yellow-100 border-yellow-300', + ]; + + $glyph = $this->glyph === null ? '' : '<Icon glyph="' . $this->glyph . '" class="flex-shrink-0 mr-2 text-lg" />'; + $title = $this->title === null ? '' : '<div class="font-semibold">' . $this->title . '</div>'; + $class = 'inline-flex w-full p-2 text-sm border rounded ' . $variantClasses[$this->variant] . ' ' . $this->class; + + $attributes = stringify_attributes($this->attributes); + + return <<<HTML + <div class="{$class}" role="alert" {$attributes}>{$glyph}<div>{$title}{$this->slot}</div></div> + HTML; + } +} diff --git a/app/Views/Components/Button.php b/app/Views/Components/Button.php index 3c29a3a3f5..34473df475 100644 --- a/app/Views/Components/Button.php +++ b/app/Views/Components/Button.php @@ -8,8 +8,6 @@ use ViewComponents\Component; class Button extends Component { - protected string $label = ''; - protected string $uri = ''; protected string $variant = 'default'; @@ -22,6 +20,11 @@ class Button extends Component protected bool $isSquared = false; + public function setIsSquared(string $value): void + { + $this->isSquared = $value === 'true'; + } + public function render(): string { $baseClass = @@ -80,19 +83,31 @@ class Button extends Component $this->slot .= '<Icon glyph="' . $this->iconRight . '" class="ml-2" />'; } + unset($this->attributes['slot']); + unset($this->attributes['variant']); + unset($this->attributes['size']); + unset($this->attributes['iconLeft']); + unset($this->attributes['iconRight']); + unset($this->attributes['isSquared']); + unset($this->attributes['uri']); + unset($this->attributes['label']); + if ($this->uri !== '') { - return anchor($this->uri, $this->label, array_merge([ - 'class' => $buttonClass, - ], $this->attributes)); + $tagName = 'a'; + $defaultButtonAttributes = [ + 'href' => $this->uri, + ]; + } else { + $tagName = 'button'; + $defaultButtonAttributes = [ + 'type' => 'button', + ]; } - $defaultButtonAttributes = [ - 'type' => 'button', - ]; $attributes = stringify_attributes(array_merge($defaultButtonAttributes, $this->attributes)); return <<<HTML - <button class="{$buttonClass}" {$attributes}>{$this->slot}</button> + <{$tagName} class="{$buttonClass}" {$attributes}>{$this->slot}</{$tagName}> HTML; } } diff --git a/app/Views/Components/Forms/Checkbox.php b/app/Views/Components/Forms/Checkbox.php new file mode 100644 index 0000000000..440300b788 --- /dev/null +++ b/app/Views/Components/Forms/Checkbox.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +namespace App\Views\Components\Forms; + +class Checkbox extends FormComponent +{ + protected ?string $hint = null; + + protected bool $isChecked = false; + + public function setIsChecked(string $value): void + { + $this->isChecked = $value === 'true'; + } + + public function render(): string + { + $checkboxInput = form_checkbox( + [ + 'id' => $this->value, + 'name' => $this->name, + 'class' => 'form-checkbox text-pine-500 border-black border-3 focus:ring-2 focus:ring-pine-500 focus:ring-offset-2 focus:ring-offset-pine-100 w-6 h-6', + ], + $this->value, + old($this->name) ? old($this->name) === $this->value : $this->isChecked, + ); + + $hint = $this->hint === null ? '' : hint_tooltip($this->hint, 'ml-1'); + + return <<<HTML + <label class="leading-8"> + {$checkboxInput} + <span class="ml-2">{$this->slot}{$hint}</label> + </label> + HTML; + } +} diff --git a/app/Views/Components/Forms/DatetimePicker.php b/app/Views/Components/Forms/DatetimePicker.php new file mode 100644 index 0000000000..19229b2882 --- /dev/null +++ b/app/Views/Components/Forms/DatetimePicker.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace App\Views\Components\Forms; + +class DatetimePicker extends FormComponent +{ + public function render(): string + { + $this->attributes['class'] = 'rounded-l-lg border-0 border-rounded-r-none flex-1 focus:ring-0'; + $this->attributes['data-input'] = ''; + $dateInput = form_input($this->attributes, old($this->name, $this->value)); + + $clearLabel = lang( + 'Episode.publish_form.scheduled_publication_date_clear', + ); + $closeIcon = icon('close'); + + return <<<HTML + <div class="flex border-3 rounded-lg border-black focus-within:ring-2 focus-within:ring-pine-500 focus-within:ring-offset-2 focus-within:ring-offset-pine-100 {$this->class}" data-picker="datetime"> + {$dateInput} + <button class="p-3 bg-white hover:bg-pine-100 focus:outline-none rounded-r-md focus:ring-inset focus:ring-2 focus:ring-pine-500 focus:ring-offset-2 focus:ring-offset-pine-100" type="button" aria-label="{$clearLabel}" title="{$clearLabel}" data-clear=""> + {$closeIcon} + </button> + </div> + HTML; + } +} diff --git a/app/Views/Components/Forms/FormComponent.php b/app/Views/Components/Forms/FormComponent.php index 785c049625..818f1ff5af 100644 --- a/app/Views/Components/Forms/FormComponent.php +++ b/app/Views/Components/Forms/FormComponent.php @@ -16,17 +16,35 @@ class FormComponent extends Component protected bool $required = false; + protected bool $readonly = false; + public function __construct($attributes) { parent::__construct($attributes); if ($this->id === null) { $this->id = $this->name; + $this->attributes['id'] = $this->id; } } public function setRequired(string $value): void { $this->required = $value === 'true'; + if ($this->required) { + $this->attributes['required'] = 'required'; + } else { + unset($this->attributes['required']); + } + } + + public function setReadonly(string $value): void + { + $this->readonly = $value === 'true'; + if ($this->readonly) { + $this->attributes['readonly'] = 'readonly'; + } else { + unset($this->attributes['readonly']); + } } } diff --git a/app/Views/Components/Forms/Helper.php b/app/Views/Components/Forms/Helper.php index 05174678c4..158fd3def0 100644 --- a/app/Views/Components/Forms/Helper.php +++ b/app/Views/Components/Forms/Helper.php @@ -7,7 +7,7 @@ namespace App\Views\Components\Forms; class Helper extends FormComponent { /** - * @var "default"|"error" + * @var 'default'|'error' */ protected string $type = 'default'; diff --git a/app/Views/Components/Forms/Input.php b/app/Views/Components/Forms/Input.php index 7d77109977..2379ab4249 100644 --- a/app/Views/Components/Forms/Input.php +++ b/app/Views/Components/Forms/Input.php @@ -21,17 +21,12 @@ class Input extends FormComponent $class .= ' border-black focus:border-black'; } - $data = [ - 'id' => $this->id, - 'name' => $this->name, - 'class' => $class, - 'type' => $this->type, - ]; + $this->attributes['class'] = $class; if ($this->required) { - $data['required'] = 'required'; + $this->attributes['required'] = 'required'; } - return form_input($data, old($this->name, $this->value)); + return form_input($this->attributes, old($this->name, $this->value)); } } diff --git a/app/Views/Components/Forms/Label.php b/app/Views/Components/Forms/Label.php index 609780f656..49bbac3ebc 100644 --- a/app/Views/Components/Forms/Label.php +++ b/app/Views/Components/Forms/Label.php @@ -24,12 +24,17 @@ class Label extends Component $labelClass = 'text-sm ' . $this->attributes['class']; unset($this->attributes['class']); - $attributes = stringify_attributes($this->attributes); $optionalText = $this->isOptional ? '<small class="ml-1 lowercase">(' . lang('Common.optional') . ')</small>' : ''; $hint = $this->hint === null ? '' : hint_tooltip($this->hint, 'ml-1'); + unset($this->attributes['isOptional']); + unset($this->attributes['hint']); + unset($this->attributes['slot']); + + $attributes = stringify_attributes($this->attributes); + return <<<HTML <label class="{$labelClass}" {$attributes}>{$this->slot}{$optionalText}{$hint}</label> HTML; diff --git a/app/Views/Components/Forms/MultiSelect.php b/app/Views/Components/Forms/MultiSelect.php index f9c25c0723..9ae032aaac 100644 --- a/app/Views/Components/Forms/MultiSelect.php +++ b/app/Views/Components/Forms/MultiSelect.php @@ -4,9 +4,7 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use ViewComponents\Component; - -class MultiSelect extends Component +class MultiSelect extends FormComponent { /** * @var array<string, string> @@ -36,6 +34,6 @@ class MultiSelect extends Component ]; $extra = array_merge($defaultAttributes, $this->attributes); - return form_dropdown($this->attributes['name'], $this->options, $this->selected, $extra); + return form_dropdown($this->name, $this->options, $this->selected, $extra); } } diff --git a/app/Views/Components/Forms/Radio.php b/app/Views/Components/Forms/Radio.php new file mode 100644 index 0000000000..cdbcd65051 --- /dev/null +++ b/app/Views/Components/Forms/Radio.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace App\Views\Components\Forms; + +class Radio extends FormComponent +{ + protected bool $isChecked = false; + + public function setIsChecked(string $value): void + { + $this->isChecked = $value === 'true'; + } + + public function render(): string + { + $radioInput = form_radio( + [ + 'id' => $this->value, + 'name' => $this->name, + 'class' => 'text-pine-500 border-black border-3 focus:ring-2 focus:ring-pine-500 focus:ring-offset-2 focus:ring-offset-pine-100 w-6 h-6', + ], + $this->value, + old($this->name) ? old($this->name) === $this->value : $this->isChecked, + ); + + return <<<HTML + <label class="leading-8">{$radioInput}<span class="ml-2">{$this->slot}</span></label> + HTML; + } +} diff --git a/app/Views/Components/Forms/RadioButton.php b/app/Views/Components/Forms/RadioButton.php index 222afa1f27..6d35442123 100644 --- a/app/Views/Components/Forms/RadioButton.php +++ b/app/Views/Components/Forms/RadioButton.php @@ -4,11 +4,6 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -/** - * Form Checkbox Switch - * - * Abstracts form_label to stylize it as a switch toggle - */ class RadioButton extends FormComponent { protected bool $isChecked = false; diff --git a/app/Views/Components/Forms/Section.php b/app/Views/Components/Forms/Section.php index 38adec8703..7458f6436b 100644 --- a/app/Views/Components/Forms/Section.php +++ b/app/Views/Components/Forms/Section.php @@ -4,15 +4,19 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -class Section extends FormComponent +use ViewComponents\Component; + +class Section extends Component { protected string $title = ''; protected ?string $subtitle = null; + protected string $subtitleClass = ''; + public function render(): string { - $subtitle = $this->subtitle === null ? '' : '<p class="text-sm text-gray-600 clear-left">' . $this->subtitle . '</p>'; + $subtitle = $this->subtitle === null ? '' : '<p class="text-sm text-gray-600 clear-left ' . $this->subtitleClass . '">' . $this->subtitle . '</p>'; return <<<HTML <fieldset class="w-full max-w-xl p-8 bg-white border-2 border-black rounded-xl {$this->class}"> diff --git a/app/Views/Components/Forms/Select.php b/app/Views/Components/Forms/Select.php index 983a6be08d..2b8f4521ea 100644 --- a/app/Views/Components/Forms/Select.php +++ b/app/Views/Components/Forms/Select.php @@ -11,7 +11,7 @@ class Select extends FormComponent */ protected array $options = []; - protected string $selected; + protected string $selected = ''; public function setOptions(string $value): void { diff --git a/app/Views/Components/Forms/Textarea.php b/app/Views/Components/Forms/Textarea.php new file mode 100644 index 0000000000..31bc45de22 --- /dev/null +++ b/app/Views/Components/Forms/Textarea.php @@ -0,0 +1,31 @@ +<?php + +declare(strict_types=1); + +namespace App\Views\Components\Forms; + +class Textarea extends FormComponent +{ + public function setValue(?string $value): void + { + if ($value) { + $this->value = html_entity_decode($value); + } + } + + public function render(): string + { + unset($this->attributes['value']); + + $this->attributes['class'] = 'focus:border-black focus:ring-2 focus:ring-pine-500 focus:ring-offset-2 focus:ring-offset-pine-100 rounded-lg border-3 border-black ' . $this->class; + + $textarea = form_textarea( + $this->attributes, + old($this->name, $this->value ?? '', false) + ); + + return <<<HTML + {$textarea} + HTML; + } +} diff --git a/app/Views/Components/Forms/Toggler.php b/app/Views/Components/Forms/Toggler.php index a8ae1e8769..15d101900c 100644 --- a/app/Views/Components/Forms/Toggler.php +++ b/app/Views/Components/Forms/Toggler.php @@ -4,24 +4,12 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use ViewComponents\Component; - -/** - * Form Checkbox Switch - * - * Abstracts form_label to stylize it as a switch toggle - */ -class Toggler extends Component +class Toggler extends FormComponent { /** - * @var array<string, string> + * @var 'base'|'small */ - protected array $attributes = [ - 'id' => '', - 'name' => '', - 'value' => '', - 'class' => '', - ]; + protected string $size = 'base'; protected string $label = ''; @@ -31,26 +19,29 @@ class Toggler extends Component public function setChecked(string $value): void { - $this->checked = $value !== ''; + $this->checked = $value === 'true'; } public function render(): string { unset($this->attributes['checked']); - $wrapperClass = $this->attributes['class']; + $wrapperClass = $this->class; unset($this->attributes['class']); - $this->attributes['class'] = 'form-switch'; + $sizeClass = [ + 'base' => 'form-switch-slider', + 'small' => 'form-switch-slider form-switch-slider--small', + ]; - helper('form'); + $this->attributes['class'] = 'form-switch'; - $checkbox = form_checkbox($this->attributes, $this->attributes['value'], $this->checked); + $checkbox = form_checkbox($this->attributes, $this->value, old($this->name, $this->checked)); $hint = $this->hint === '' ? '' : hint_tooltip($this->hint, 'ml-1'); return <<<HTML <label class="relative inline-flex items-center {$wrapperClass}"> {$checkbox} - <span class="form-switch-slider"></span> + <span class="{$sizeClass[$this->size]}"></span> <span class="ml-2">{$this->slot}{$hint}</span> </label> HTML; diff --git a/app/Views/Components/Forms/XMLEditor.php b/app/Views/Components/Forms/XMLEditor.php index 71e01d242e..c3ec19ba30 100644 --- a/app/Views/Components/Forms/XMLEditor.php +++ b/app/Views/Components/Forms/XMLEditor.php @@ -4,9 +4,7 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use ViewComponents\Component; - -class XMLEditor extends Component +class XMLEditor extends FormComponent { /** * @var array<string, string> diff --git a/app/Views/Components/Heading.php b/app/Views/Components/Heading.php index 8cfa379208..249bc183df 100644 --- a/app/Views/Components/Heading.php +++ b/app/Views/Components/Heading.php @@ -11,7 +11,7 @@ class Heading extends Component protected string $tagName = 'div'; /** - * @var "small"|"base"|"large" + * @var 'small'|'base'|'large' */ protected string $size = 'base'; diff --git a/app/Views/Components/IconButton.php b/app/Views/Components/IconButton.php new file mode 100644 index 0000000000..574cc817a0 --- /dev/null +++ b/app/Views/Components/IconButton.php @@ -0,0 +1,21 @@ +<?php + +declare(strict_types=1); + +namespace App\Views\Components; + +use ViewComponents\Component; + +class IconButton extends Component +{ + public string $glyph = ''; + + public function render(): string + { + $attributes = stringify_attributes($this->attributes); + + return <<<HTML + <Button isSquared="true" title="{$this->slot}" data-toggle="tooltip" data-placement="bottom" {$attributes}><Icon glyph="{$this->glyph}" /></Button> + HTML; + } +} diff --git a/modules/Admin/Language/en/Episode.php b/modules/Admin/Language/en/Episode.php index 6f90e69c49..181e446cc9 100644 --- a/modules/Admin/Language/en/Episode.php +++ b/modules/Admin/Language/en/Episode.php @@ -118,6 +118,7 @@ return [ 'post' => 'Your announcement post', 'post_hint' => "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', 'publication_date' => 'Publication date', 'publication_method' => [ 'now' => 'Now', diff --git a/modules/Admin/Language/en/Person.php b/modules/Admin/Language/en/Person.php index 7306ed270c..334e535154 100644 --- a/modules/Admin/Language/en/Person.php +++ b/modules/Admin/Language/en/Person.php @@ -17,8 +17,6 @@ return [ 'edit' => 'Edit person', 'delete' => 'Delete person', 'form' => [ - 'identity_section_title' => 'Identity', - 'identity_section_subtitle' => 'Who is working on the podcast', 'image' => 'Picture', 'image_size_hint' => 'Image must be squared with at least 400px wide and tall.', @@ -34,8 +32,6 @@ return [ ], 'podcast_form' => [ 'title' => 'Manage persons', - 'manage_section_title' => 'Management', - 'manage_section_subtitle' => 'Remove persons from this podcast', 'add_section_title' => 'Add persons to this podcast', 'add_section_subtitle' => 'You may pick several persons and roles.', 'persons' => 'Persons', @@ -49,8 +45,6 @@ return [ ], 'episode_form' => [ 'title' => 'Manage persons', - 'manage_section_title' => 'Management', - 'manage_section_subtitle' => 'Remove persons from this episode', 'add_section_title' => 'Add persons to this episode', 'add_section_subtitle' => 'You may pick several persons and roles.', 'persons' => 'Persons', diff --git a/modules/Admin/Language/en/Podcast.php b/modules/Admin/Language/en/Podcast.php index 946b0b1be4..cd8d087250 100644 --- a/modules/Admin/Language/en/Podcast.php +++ b/modules/Admin/Language/en/Podcast.php @@ -88,7 +88,6 @@ return [ 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', 'status_section_title' => 'Status', - 'status_section_subtitle' => 'Dead or alive?', 'block' => 'Podcast should be hidden from all platforms', 'complete' => 'Podcast will not be having new episodes', 'lock' => 'Prevent podcast from being copied', diff --git a/modules/Admin/Language/en/PodcastImport.php b/modules/Admin/Language/en/PodcastImport.php index b6e8774c2a..8c70b892c7 100644 --- a/modules/Admin/Language/en/PodcastImport.php +++ b/modules/Admin/Language/en/PodcastImport.php @@ -20,11 +20,7 @@ return [ 'advanced_params_section_title' => 'Advanced parameters', 'advanced_params_section_subtitle' => 'Keep the default values if you have no idea of what the fields are for.', - 'slug_field' => [ - 'label' => 'Which field should be used to calculate episode slug', - 'link' => '<link>', - 'title' => '<title>', - ], + 'slug_field' => 'Field to be used to calculate episode slug', 'description_field' => 'Source field used for episode description / show notes', 'force_renumber' => 'Force episodes renumbering', diff --git a/modules/Admin/Language/fr/Episode.php b/modules/Admin/Language/fr/Episode.php index fc3d49364e..1061e34352 100644 --- a/modules/Admin/Language/fr/Episode.php +++ b/modules/Admin/Language/fr/Episode.php @@ -121,6 +121,7 @@ return [ 'post' => 'Votre message de publication', 'post_hint' => 'Écrivez un message pour annoncer la publication de votre épisode. Le message sera diffusé à toutes les personnes qui vous suivent dans le fédiverse et mis en évidence sur la page d’accueil de votre podcast.', + 'message_placeholder' => 'Entrez votre message…', 'publication_date' => 'Date de publication', 'publication_date_clear' => 'Effacer la date de publication', 'publication_date_hint' => diff --git a/modules/Admin/Language/fr/Person.php b/modules/Admin/Language/fr/Person.php index ad2aeda23c..db2e1ab491 100644 --- a/modules/Admin/Language/fr/Person.php +++ b/modules/Admin/Language/fr/Person.php @@ -17,8 +17,6 @@ return [ 'edit' => 'Modifier l’intervenant', 'delete' => 'Supprimer l’intervenant', 'form' => [ - 'identity_section_title' => 'Identité', - 'identity_section_subtitle' => 'Qui intervient sur le podcast', 'image' => 'Photo', 'image_size_hint' => 'L’image doit être carrée et avoir au moins 400px de largeur et de hauteur.', @@ -34,32 +32,28 @@ return [ ], 'podcast_form' => [ 'title' => 'Gérer les intervenants', - 'manage_section_title' => 'Gestion', - 'manage_section_subtitle' => 'Retirer des intervenants de ce podcast', 'add_section_title' => 'Ajouter des intervenants à ce podcast', 'add_section_subtitle' => 'Vous pouvez sélectionner plusieurs intervenants et rôles.', - 'person' => 'Intervenants', - 'person_hint' => + 'persons' => 'Intervenants', + 'persons_hint' => 'Vous pouvez selectionner un ou plusieurs intervenants ayant les mêmes rôles. Les intervenants doivent avoir été préalablement créés.', - 'group_role' => 'Groupes et rôles', - 'group_role_hint' => + 'roles' => 'Groupes et rôles', + 'roles_hint' => 'Vous pouvez sélectionner aucun, un ou plusieurs groupes et rôles par intervenant.', 'submit_add' => 'Ajouter un/des intervenant(s)', 'remove' => 'Retirer', ], 'episode_form' => [ 'title' => 'Gérer les intervenants', - 'manage_section_title' => 'Gestion', - 'manage_section_subtitle' => 'Retirer des intervenants de cet épisode', 'add_section_title' => 'Ajouter des intervenants à cet épisode', 'add_section_subtitle' => 'Vous pouvez sélectionner plusieurs intervenants et rôles.', - 'person' => 'Intervenants', - 'person_hint' => + 'persons' => 'Intervenants', + 'persons_hint' => 'Vous pouvez selectionner un ou plusieurs intervenants ayant les mêmes rôles. Les intervenants doivent avoir été préalablement créés.', - 'group_role' => 'Groupes et rôles', - 'group_role_hint' => + 'roles' => 'Groupes et rôles', + 'roles_hint' => 'Vous pouvez sélectionner aucun, un ou plusieurs groupes et rôles par intervenant.', 'submit_add' => 'Ajouter un/des intervenant(s)', 'remove' => 'Retirer', diff --git a/modules/Admin/Language/fr/Podcast.php b/modules/Admin/Language/fr/Podcast.php index 1ef22cd776..a4919c6d14 100644 --- a/modules/Admin/Language/fr/Podcast.php +++ b/modules/Admin/Language/fr/Podcast.php @@ -90,7 +90,6 @@ return [ 'partner_link_url_hint' => 'L’adresse générique des liens partenaire', 'partner_image_url_hint' => 'L’adresse générique des images partenaire', 'status_section_title' => 'Statut', - 'status_section_subtitle' => 'Vivant ou mort ?', 'block' => 'Le podcast doit être masqué sur toutes les plateformes', 'complete' => 'Le podcast n’aura plus de nouveaux épisodes.', 'lock' => 'Empêcher la copie du podcast', diff --git a/modules/Admin/Language/fr/PodcastImport.php b/modules/Admin/Language/fr/PodcastImport.php index 94b3167df4..58dd92b8bc 100644 --- a/modules/Admin/Language/fr/PodcastImport.php +++ b/modules/Admin/Language/fr/PodcastImport.php @@ -22,7 +22,7 @@ return [ 'Si vous ne savez pas à quoi servent ces champs, conservez les valeurs par défaut.', 'slug_field' => [ 'label' => - 'Quel champ utiliser pour calculer l’identifiant de l’épisode', + 'Champ à utiliser pour calculer l’identifiant de l’épisode', 'link' => '<link> (adresse)', 'title' => '<title> (titre)', ], diff --git a/themes/cp_admin/_layout.php b/themes/cp_admin/_layout.php index 8da7748788..e77eaf7bd3 100644 --- a/themes/cp_admin/_layout.php +++ b/themes/cp_admin/_layout.php @@ -24,7 +24,7 @@ <a href="<?= route_to( 'admin', ) ?>" class="inline-flex items-center h-full px-2 border-r border-pine-900"> - <?= (isset($podcast) ? icon('arrow-left', 'mr-2') : '') . svg('castopod-logo', 'h-6') ?> + <?= (isset($podcast) ? icon('arrow-left', 'mr-2') : '') . svg('castopod-logo-base', 'h-6') ?> </a> <a href="<?= route_to( 'home', @@ -93,7 +93,7 @@ </div> </header> <div class="container px-2 py-8 mx-auto md:px-12"> - <!-- view('App\Views\_message_block') --> + <?= view('_message_block') ?> <?= $this->renderSection('content') ?> </div> </main> diff --git a/themes/cp_admin/_message_block.php b/themes/cp_admin/_message_block.php new file mode 100644 index 0000000000..3794ba39ac --- /dev/null +++ b/themes/cp_admin/_message_block.php @@ -0,0 +1,20 @@ +<?php declare(strict_types=1); + +if (session()->has('message')): ?> + <Alert variant="success"><?= session('message') ?></Alert> +<?php endif; ?> + +<?php if (session()->has('error')): ?> + <Alert variant="danger"><?= session('error') ?></Alert> +<?php endif; ?> + +<?php if (session()->has('errors')): ?> + <Alert variant="danger"> + <ul> + <?php foreach (session('errors') as $error): ?> + <li><?= $error ?></li> + <?php endforeach; ?> + </ul> + </Alert> +<?php endif; +?> diff --git a/themes/cp_admin/contributor/add.php b/themes/cp_admin/contributor/add.php index 80a812a2b1..e272466db8 100644 --- a/themes/cp_admin/contributor/add.php +++ b/themes/cp_admin/contributor/add.php @@ -11,39 +11,27 @@ <?= $this->section('content') ?> -<?= form_open(route_to('contributor-add', $podcast->id), [ - 'class' => 'flex flex-col max-w-sm', -]) ?> +<form method="POST" action="<?= route_to('contributor-add', $podcast->id) ?>" class="flex flex-col max-w-sm gap-y-4"> <?= csrf_field() ?> -<Forms.Label for="user"><?= lang('Contributor.form.user') ?></Forms.Label> -<?= form_dropdown('user', $userOptions, [old('user', '')], [ - 'id' => 'user', - 'class' => 'form-select mb-4', - 'required' => 'required', - 'placeholder' => lang('Contributor.form.user_placeholder'), -]) ?> - -<Forms.Label for="role"><?= lang('Contributor.form.role') ?></Forms.Label> -<?= form_dropdown('role', $roleOptions, [old('role', '')], [ - 'id' => 'role', - 'class' => 'form-select mb-4', - 'required' => 'required', - 'placeholder' => lang('Contributor.form.role_placeholder'), -]) ?> - -<?= button( - lang('Contributor.form.submit_add'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - -<?= form_close() ?> +<Forms.Field + as="Select" + name="user" + label="<?= lang('Contributor.form.user') ?>" + options="<?= esc(json_encode($userOptions)) ?>" + placeholder="<?= lang('Contributor.form.user_placeholder') ?>" + required="true" /> + +<Forms.Field + as="Select" + name="role" + label="<?= lang('Contributor.form.role') ?>" + options="<?= esc(json_encode($roleOptions)) ?>" + placeholder="<?= lang('Contributor.form.role_placeholder') ?>" + required="true" /> + +<Button type="submit" class="self-end" variant="primary"><?= lang('Contributor.form.submit_add') ?></Button> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/contributor/edit.php b/themes/cp_admin/contributor/edit.php index 4c912acb87..2baa789e13 100644 --- a/themes/cp_admin/contributor/edit.php +++ b/themes/cp_admin/contributor/edit.php @@ -11,30 +11,20 @@ <?= $this->section('content') ?> -<?= form_open(route_to('contributor-edit', $podcast->id, $user->id), [ - 'class' => 'flex flex-col max-w-sm', -]) ?> +<form method="POST" action="<?= route_to('contributor-edit', $podcast->id, $user->id) ?>" class="flex flex-col max-w-sm gap-y-4"> <?= csrf_field() ?> -<Forms.Label for="role"><?= lang('Contributor.form.role') ?></Forms.Label> -<?= form_dropdown('role', $roleOptions, [old('role', $contributorGroupId)], [ - 'id' => 'role', - 'class' => 'form-select mb-4', - 'required' => 'required', -]) ?> - -<?= button( - lang('Contributor.form.submit_edit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - -<?= form_close() ?> +<Forms.Field + as="Select" + name="role" + label="<?= lang('Contributor.form.role') ?>" + selected="<?= $contributorGroupId ?>" + options="<?= esc(json_encode($roleOptions)) ?>" + placeholder="<?= lang('Contributor.form.role_placeholder') ?>" + required="true" /> + +<Button variant="primary" type="submit" class="self-end"><?= lang('Contributor.form.submit_edit') ?></Button> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/create.php b/themes/cp_admin/episode/create.php index 8afc63c0ef..34b3e04ca3 100644 --- a/themes/cp_admin/episode/create.php +++ b/themes/cp_admin/episode/create.php @@ -11,356 +11,203 @@ <?= $this->section('content') ?> -<?= form_open_multipart(route_to('episode-create', $podcast->id), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> +<Alert variant="danger" glyph="alert"><?= lang('Episode.form.warning') ?></Alert> + +<form action="<?= route_to('episode-create', $podcast->id) ?>" method="POST" enctype="multipart/form-data" class="flex flex-col mt-6 gap-y-8"> <?= csrf_field() ?> -<?= form_hidden('client_timezone', 'UTC') ?> -<div class="inline-flex w-full p-2 mb-4 text-sm font-semibold text-yellow-800 bg-red-100 border border-red-300 rounded" role="alert"> - <?= icon('alert', 'mr-2 text-lg flex-shrink-0') . - lang('Episode.form.warning') ?> -</div> -<?= form_section( - lang('Episode.form.info_section_title'), - lang('Episode.form.info_section_subtitle'), - ) ?> - -<Forms.Label for="audio_file" hint="<?= lang('Episode.form.audio_file_hint') ?>"><?= lang('Episode.form.audio_file') ?></Forms.Label> -<?= form_input([ - 'id' => 'audio_file', - 'name' => 'audio_file', - 'class' => 'form-input mb-4', - 'required' => 'required', - 'type' => 'file', - 'accept' => '.mp3,.m4a', -]) ?> - -<Forms.Label for="image" hint="<?= lang('Episode.form.image_hint') ?>" isOptional="true"><?= lang('Episode.form.image') ?></Forms.Label> -<?= form_input([ - 'id' => 'image', - 'name' => 'image', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.jpg,.jpeg,.png', -]) ?> -<small class="mb-4 text-gray-600"><?= lang( - 'Common.forms.image_size_hint', -) ?></small> - -<Forms.Label for="title" hint="<?= lang('Episode.form.title_hint') ?>"><?= lang('Episode.form.title') ?></Forms.Label> -<?= form_input([ - 'id' => 'title', - 'name' => 'title', - 'class' => 'form-input mb-4', - 'value' => old('title'), - 'required' => 'required', - 'data-slugify' => 'title', -]) ?> - -<Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></Forms.Label> -<permalink-edit class="inline-flex items-center mb-4 text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> - <span slot="domain"><?= base_url('/@' . $podcast->handle . '/episodes') . '/' ?></span> - <?= form_input([ - 'id' => 'slug', - 'name' => 'slug', - 'class' => 'form-input flex-1 w-0 text-xs', - 'value' => old('slug'), - 'required' => 'required', - 'data-slugify' => 'slug', - 'slot' => 'slug-input', - ]) ?> -</permalink-edit> - -<div class="flex flex-col mb-4 gap-x-2 gap-y-4 md:flex-row"> - <div class="flex flex-col flex-1"> - <Forms.Label for="season_number"><?= lang('Episode.form.season_number') ?></Forms.Label> - <?= form_input([ - 'id' => 'season_number', - 'name' => 'season_number', - 'class' => 'form-input w-full', - 'value' => old('season_number'), - 'type' => 'number', - ]) ?> - </div> - <div class="flex flex-col flex-1"> - <Forms.Label for="episode_number"><?= lang('Episode.form.episode_number') ?></Forms.Label> - <?= form_input([ - 'id' => 'episode_number', - 'name' => 'episode_number', - 'class' => 'form-input w-full', - 'value' => old('episode_number'), - 'type' => 'number', - ]) ?> - </div> +<Forms.Section title="<?= lang('Episode.form.info_section_title') ?>" > + +<Forms.Field + name="audio_file" + label="<?= lang('Episode.form.audio_file') ?>" + hintText="<?= lang('Episode.form.audio_file_hint') ?>" + type="file" + accept=".mp3,.m4a" + required="true" /> + +<Forms.Field + name="image" + label="<?= lang('Episode.form.image') ?>" + hintText="<?= lang('Episode.form.image_hint') ?>" + helperText="<?= lang('Common.forms.image_size_hint', ) ?>" + type="file" + accept=".jpg,.jpeg,.png" /> + +<Forms.Field + name="title" + label="<?= lang('Episode.form.title') ?>" + hintText="<?= lang('Episode.form.title_hint') ?>" + required="true" + data-slugify="title" /> + +<div> + <Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></Forms.Label> + <permalink-edit class="inline-flex items-center text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> + <span slot="domain"><?= base_url('/@' . $podcast->handle . '/episodes') . '/' ?></span> + <Forms.Input name="slug" required="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" /> + </permalink-edit> </div> +<div class="flex flex-col gap-x-2 gap-y-4 md:flex-row"> + <Forms.Field + class="flex-1 w-0" + name="season_number" + label="<?= lang('Episode.form.season_number') ?>" + type="number" + /> + <Forms.Field + class="flex-1 w-0" + name="episode_number" + label="<?= lang('Episode.form.episode_number') ?>" + type="number" + /> +</div> -<?= form_fieldset('', [ - 'class' => 'mb-4', -]) ?> - <legend> +<fieldset class="flex gap-1"> +<legend> <?= lang('Episode.form.type.label') . hint_tooltip(lang('Episode.form.type.hint'), 'ml-1') ?> - </legend> - <?= form_radio( - [ - 'id' => 'full', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'full', - old('type') ? old('type') === 'full' : true, - ) ?> - <label for="full" class="inline-flex items-center"> - <?= lang('Episode.form.type.full') ?> - </label> - <?= form_radio( - [ - 'id' => 'trailer', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'trailer', - old('type') && old('type') === 'trailer', - ) ?> - <label for="trailer" class="inline-flex items-center"> - <?= lang('Episode.form.type.trailer') ?> - </label> - <?= form_radio( - [ - 'id' => 'bonus', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'bonus', - old('type') && old('type') === 'bonus', - ) ?> - <label for="bonus" class="inline-flex items-center"> - <?= lang('Episode.form.type.bonus') ?> - </label> -<?= form_fieldset_close() ?> - -<?= form_fieldset('', [ - 'class' => 'flex mb-6 gap-1', -]) ?> - <legend> +</legend> +<Forms.RadioButton + value="full" + name="type" + isChecked="true" ><?= lang('Episode.form.type.full') ?></Forms.RadioButton> +<Forms.RadioButton + value="trailer" + name="type" + isChecked="false" ><?= lang('Episode.form.type.trailer') ?></Forms.RadioButton> +<Forms.RadioButton + value="bonus" + name="type" + isChecked="false" ><?= lang('Episode.form.type.bonus') ?></Forms.RadioButton> +</fieldset> + +<fieldset class="flex gap-1"> +<legend> <?= lang('Episode.form.parental_advisory.label') . hint_tooltip(lang('Episode.form.parental_advisory.hint'), 'ml-1') ?> - </legend> - <?= form_radio( - [ - 'id' => 'undefined', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'undefined', - old('parental_advisory') - ? old('parental_advisory') === 'undefined' - : true, - ) ?> - <label for="undefined"><?= lang( - 'Episode.form.parental_advisory.undefined', - ) ?></label> - <?= form_radio( - [ - 'id' => 'clean', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'clean', - old('parental_advisory') && old('parental_advisory') === 'clean', - ) ?> - <label for="clean"><?= lang( - 'Episode.form.parental_advisory.clean', - ) ?></label> - <?= form_radio( - [ - 'id' => 'explicit', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'explicit', - old('parental_advisory') && old('parental_advisory') === 'explicit', - ) ?> - <label for="explicit"><?= lang( - 'Episode.form.parental_advisory.explicit', - ) ?></label> -<?= form_fieldset_close() ?> - -<?= form_section_close() ?> - - -<?= form_section( - lang('Episode.form.show_notes_section_title'), - lang('Episode.form.show_notes_section_subtitle'), - ) ?> - -<div class="mb-4"> - <Forms.Label for="description"><?= lang('Episode.form.description') ?></Forms.Label> - <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', '', false) ?></Forms.MarkdownEditor> -</div> - -<div class="mb-4"> - <Forms.Label for="description_footer" hint="<?= lang('Episode.form.description_footer_hint') ?>" isOptional="true"><?= lang('Episode.form.description_footer') ?></Forms.Label> - <Forms.MarkdownEditor id="description_footer" name="description_footer" rows="6"><?= old('description_footer', $podcast->episode_description_footer_markdown ?? '', false) ?></Forms.MarkdownEditor> -</div> - -<?= form_section_close() ?> - -<?= form_section( - lang('Episode.form.location_section_title'), - lang('Episode.form.location_section_subtitle'), - ) ?> - -<Forms.Label for="location_name" hint="<?= lang('Episode.form.location_name_hint') ?>" isOptional="true"><?= lang('Episode.form.location_name') ?></Forms.Label> -<?= form_input([ - 'id' => 'location_name', - 'name' => 'location_name', - 'class' => 'form-input mb-4', - 'value' => old('location_name'), -]) ?> -<?= form_section_close() ?> - -<?= form_section( - lang('Episode.form.additional_files_section_title'), - lang('Episode.form.additional_files_section_subtitle'), -) ?> - -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> - <legend><?= lang('Episode.form.transcript') . - '<small class="ml-1 lowercase">(' . - lang('Common.optional') . - ')</small>' . - hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend> - <div class="mb-4 form-input-tabs"> - <input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= old( - 'transcript-choice', - ) !== 'remote-url' - ? 'checked' - : '' ?> /> - <label for="transcript-file-upload-choice"><?= lang( - 'Common.forms.upload_file', - ) ?></label> - - <input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= old( - 'transcript-choice', - ) === 'remote-url' - ? 'checked' - : '' ?> /> - <label for="transcript-file-remote-url-choice"><?= lang( - 'Common.forms.remote_url', - ) ?></label> - - <div class="py-2 tab-panels"> - <section id="transcript-file-upload" class="flex items-center tab-panel"> +</legend> +<Forms.RadioButton + value="undefined" + name="parental_advisory" + isChecked="true" ><?= lang('Episode.form.parental_advisory.undefined') ?></Forms.RadioButton> +<Forms.RadioButton + value="clean" + name="parental_advisory" + isChecked="false" ><?= lang('Episode.form.parental_advisory.clean') ?></Forms.RadioButton> +<Forms.RadioButton + value="explicit" + name="parental_advisory" + isChecked="false" ><?= lang('Episode.form.parental_advisory.explicit') ?></Forms.RadioButton> +</fieldset> + +</Forms.Section> + + +<Forms.Section + title="<?= lang('Episode.form.show_notes_section_title') ?>" + subtitle="<?= lang('Episode.form.show_notes_section_subtitle') ?>"> + +<Forms.Field + as="MarkdownEditor" + name="description" + label="<?= lang('Episode.form.description') ?>" + required="true" /> + +<Forms.Field + as="MarkdownEditor" + name="description_footer" + label="<?= lang('Episode.form.description_footer') ?>" + hintText="<?= lang('Episode.form.description_footer_hint') ?>" /> + +</Forms.Section> + +<Forms.Section + title="<?= lang('Episode.form.location_section_title') ?>" + subtitle="<?= lang('Episode.form.location_section_subtitle') ?>" +> +<Forms.Field + name="location_name" + label="<?= lang('Episode.form.location_name') ?>" + hint="<?= lang('Episode.form.location_name_hint') ?>" /> +</Forms.Section> + +<Forms.Section + title="<?= lang('Episode.form.additional_files_section_title') ?>"> + +<fieldset class="flex flex-col"> +<legend><?= lang('Episode.form.transcript') . + '<small class="ml-1 lowercase">(' . + lang('Common.optional') . + ')</small>' . + hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend> +<div class="form-input-tabs"> + <input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= old('transcript-choice') !== 'remote-file' ? 'checked' : '' ?> /> + <label for="transcript-file-upload-choice"><?= lang('Common.forms.upload_file') ?></label> + + <input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= old('transcript-choice') === 'remote-file' ? 'checked' : '' ?> /> + <label for="transcript-file-remote-url-choice"><?= lang('Common.forms.remote_url') ?></label> + + <div class="py-2 tab-panels"> + <section id="transcript-file-upload" class="flex items-center tab-panel"> <Forms.Label class="sr-only" for="transcript_file" isOptional="true"><?= lang('Episode.form.transcript_file') ?></Forms.Label> - <?= form_input([ - 'id' => 'transcript_file', - 'name' => 'transcript_file', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.txt,.html,.srt,.json', - ]) ?> - </section> - <section id="transcript-file-remote-url" class="tab-panel"> + <Forms.Input class="w-full" name="transcript_file" type="file" accept=".txt,.html,.srt,.json" /> + </section> + <section id="transcript-file-remote-url" class="tab-panel"> <Forms.Label class="sr-only" for="transcript_file_remote_url" isOptional="true"><?= lang('Episode.form.transcript_file_remote_url') ?></Forms.Label> - <?= form_input([ - 'id' => 'transcript_file_remote_url', - 'name' => 'transcript_file_remote_url', - 'class' => 'form-input w-full', - 'type' => 'url', - 'placeholder' => 'https://...', - 'value' => old('transcript_file_remote_url'), - ]) ?> - </section> - </div> + <Forms.Input class="w-full" placeholder="https://…" name="transcript_file_remote_url" /> + </section> </div> -<?= form_fieldset_close() ?> - -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> - <legend><?= lang('Episode.form.chapters') . - '<small class="ml-1 lowercase">(' . - lang('Common.optional') . - ')</small>' . - hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?></legend> - <div class="mb-4 form-input-tabs"> - <input type="radio" name="chapters-choice" id="chapters-file-upload-choice" aria-controls="chapters-file-upload-choice" value="upload-file" <?= old( - 'chapters-choice', - ) !== 'remote-url' - ? 'checked' - : '' ?> /> - <label for="chapters-file-upload-choice"><?= lang( - 'Common.forms.upload_file', - ) ?></label> - - <input type="radio" name="chapters-choice" id="chapters-file-remote-url-choice" aria-controls="chapters-file-remote-url-choice" value="remote-url" <?= old( - 'chapters-choice', - ) === 'remote-url' - ? 'checked' - : '' ?> /> - <label for="chapters-file-remote-url-choice"><?= lang( - 'Common.forms.remote_url', - ) ?></label> - - <div class="py-2 tab-panels"> - <section id="chapters-file-upload" class="flex items-center tab-panel"> +</div> +</fieldset> + + +<fieldset class="flex flex-col"> +<legend><?= lang('Episode.form.chapters') . + '<small class="ml-1 lowercase">(' . + lang('Common.optional') . + ')</small>' . + hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?></legend> +<div class="form-input-tabs"> + <input type="radio" name="chapters-choice" id="chapters-file-upload-choice" aria-controls="chapters-file-upload-choice" value="upload-file" <?= old('chapters-choice') !== 'remote-file' ? 'checked' : '' ?> /> + <label for="chapters-file-upload-choice"><?= lang('Common.forms.upload_file') ?></label> + + <input type="radio" name="chapters-choice" id="chapters-file-remote-url-choice" aria-controls="chapters-file-remote-url-choice" value="remote-url" <?= old('chapters-choice') === 'remote-file' ? 'checked' : '' ?> /> + <label for="chapters-file-remote-url-choice"><?= lang('Common.forms.remote_url') ?></label> + + <div class="py-2 tab-panels"> + <section id="chapters-file-upload" class="flex items-center tab-panel"> <Forms.Label class="sr-only" for="chapters_file" isOptional="true"><?= lang('Episode.form.chapters_file') ?></Forms.Label> - <?= form_input([ - 'id' => 'chapters_file', - 'name' => 'chapters_file', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.json', - ]) ?> - </section> - <section id="chapters-file-remote-url" class="tab-panel"> + <Forms.Input class="w-full" name="chapters_file" type="file" accept=".json" /> + </section> + <section id="chapters-file-remote-url" class="tab-panel"> <Forms.Label class="sr-only" for="chapters_file_remote_url" isOptional="true"><?= lang('Episode.form.chapters_file_remote_url') ?></Forms.Label> - <?= form_input([ - 'id' => 'chapters_file_remote_url', - 'name' => 'chapters_file_remote_url', - 'class' => 'form-input w-full', - 'type' => 'url', - 'placeholder' => 'https://...', - 'value' => old('chapters_file_remote_url'), - ]) ?> - </section> - </div> + <Forms.Input class="w-full" placeholder="https://…" name="chapters_file_remote_url" /> + </section> </div> -<?= form_fieldset_close() ?> - -<?= form_section_close() ?> - -<?= form_section( - lang('Episode.form.advanced_section_title'), - lang('Episode.form.advanced_section_subtitle'), - ) ?> -<Forms.Label for="custom_rss" hint="<?= lang('Episode.form.custom_rss_hint') ?>" isOptional="true"><?= lang('Episode.form.custom_rss') ?></Forms.Label> -<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', '', false) ?></Forms.XMLEditor> +</div> +</fieldset> +</Forms.Section> -<?= form_section_close() ?> +<Forms.Section + title="<?= lang('Episode.form.advanced_section_title') ?>" + subtitle="<?= lang('Episode.form.advanced_section_subtitle') ?>" +> +<Forms.Field + as="XMLEditor" + name="custom_rss" + label="<?= lang('Episode.form.custom_rss') ?>" + hint="<?= lang('Episode.form.custom_rss_hint') ?>" +/> -<Forms.Toggler id="block" name="block" value="yes" checked="<?= old('block', false) ?>" hint="<?= lang('Episode.form.block_hint') ?>"><?= lang('Episode.form.block') ?></Forms.Toggler> +</Forms.Section> -<?= button( - lang('Episode.form.submit_create'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], - ) ?> +<Forms.Toggler name="block" value="yes" checked="false" hint="<?= lang('Episode.form.block_hint') ?>"><?= lang('Episode.form.block') ?></Forms.Toggler> -<?= form_close() ?> +<Button class="self-end" variant="primary" type="submit"><?= lang('Episode.form.submit_create') ?></Button> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/edit.php b/themes/cp_admin/episode/edit.php index 87d64d75e6..87e4cd1886 100644 --- a/themes/cp_admin/episode/edit.php +++ b/themes/cp_admin/episode/edit.php @@ -8,277 +8,171 @@ <?= lang('Episode.edit') ?> <?= $this->endSection() ?> +<?= $this->section('headerRight') ?> +<Button variant="primary" type="submit" form="episode-edit-form"><?= lang('Episode.form.submit_edit') ?></Button> +<?= $this->endSection() ?> + <?= $this->section('content') ?> -<?= form_open_multipart(route_to('episode-edit', $podcast->id, $episode->id), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> +<Alert variant="danger" glyph="alert"><?= lang('Episode.form.warning') ?></Alert> + +<form id="episode-edit-form" action="<?= route_to('episode-edit', $podcast->id, $episode->id) ?>" method="POST" enctype="multipart/form-data" class="flex flex-col mt-6 gap-y-8"> <?= csrf_field() ?> -<div class="inline-flex w-full p-2 mb-4 text-sm font-semibold text-yellow-800 bg-red-100 border border-red-300 rounded" role="alert"> - <?= icon('alert', 'mr-2 text-lg flex-shrink-0') . - lang('Episode.form.warning') ?> + +<Forms.Section title="<?= lang('Episode.form.info_section_title') ?>" > + +<Forms.Field + name="audio_file" + label="<?= lang('Episode.form.audio_file') ?>" + hintText="<?= lang('Episode.form.audio_file_hint') ?>" + type="file" + accept=".mp3,.m4a" /> + +<Forms.Field + name="image" + label="<?= lang('Episode.form.image') ?>" + hintText="<?= lang('Episode.form.image_hint') ?>" + helperText="<?= lang('Common.forms.image_size_hint', ) ?>" + type="file" + accept=".jpg,.jpeg,.png" /> + +<Forms.Field + name="title" + label="<?= lang('Episode.form.title') ?>" + hintText="<?= lang('Episode.form.title_hint') ?>" + value="<?= $episode->title ?>" + required="true" + data-slugify="title" /> + +<div> + <Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></Forms.Label> + <permalink-edit class="inline-flex items-center text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> + <span slot="domain"><?= base_url('/@' . $podcast->handle . '/episodes') . '/' ?></span> + <Forms.Input name="slug" value="<?= $episode->slug ?>" required="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" /> + </permalink-edit> </div> -<?= form_section( - lang('Episode.form.info_section_title'), - '<img - src="' . - $episode->image->medium_url . - '" - alt="' . - $episode->title . - '" - class="w-48" -/>', - ) ?> - -<Forms.Label for="audio_file" hint="<?= lang('Episode.form.audio_file_hint') ?>"><?= lang('Episode.form.audio_file') ?></Forms.Label> -<?= form_input([ - 'id' => 'audio_file', - 'name' => 'audio_file', - 'class' => 'form-input mb-4', - 'type' => 'file', - 'accept' => '.mp3,.m4a', -]) ?> - -<Forms.Label for="image" hint="<?= lang('Episode.form.image_hint') ?>" isOptional="true"><?= lang('Episode.form.image') ?></Forms.Label> -<?= form_input([ - 'id' => 'image', - 'name' => 'image', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.jpg,.jpeg,.png', -]) ?> -<small class="mb-4 text-gray-600"><?= lang( - 'Common.forms.image_size_hint', -) ?></small> - -<Forms.Label for="title" hint="<?= lang('Episode.form.title_hint') ?>"><?= lang('Episode.form.title') ?></Forms.Label> -<?= form_input([ - 'id' => 'title', - 'name' => 'title', - 'class' => 'form-input mb-4', - 'value' => old('title', $episode->title), - 'required' => 'required', - 'data-slugify' => 'title', -]) ?> - -<Forms.Label for="slug"><?= lang('Episode.form.permalink') ?></Forms.Label> -<permalink-edit class="inline-flex items-center mb-4 text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> - <span slot="domain"><?= base_url('/@' . $podcast->handle . '/episodes') . '/' ?></span> - <?= form_input([ - 'id' => 'slug', - 'name' => 'slug', - 'class' => 'form-input flex-1 w-0 text-xs', - 'value' => old('slug', $episode->slug), - 'required' => 'required', - 'data-slugify' => 'slug', - 'slot' => 'slug-input', - ]) ?> -</permalink-edit> - -<div class="flex flex-col mb-4 gap-x-2 gap-y-4 md:flex-row"> - <div class="flex flex-col flex-1"> - <Forms.Label for="season_number"><?= lang('Episode.form.season_number') ?></Forms.Label> - <?= form_input([ - 'id' => 'season_number', - 'name' => 'season_number', - 'class' => 'form-input w-full', - 'value' => old('season_number', $episode->season_number), - 'type' => 'number', - ]) ?> - </div> - <div class="flex flex-col flex-1"> - <Forms.Label for="episode_number"><?= lang('Episode.form.episode_number') ?></Forms.Label> - <?= form_input([ - 'id' => 'episode_number', - 'name' => 'episode_number', - 'class' => 'form-input w-full', - 'value' => old('episode_number', $episode->number), - 'type' => 'number', - ]) ?> - </div> +<div class="flex flex-col gap-x-2 gap-y-4 md:flex-row"> + <Forms.Field + class="flex-1 w-0" + name="season_number" + label="<?= lang('Episode.form.season_number') ?>" + type="number" + value="<?= $episode->season_number ?>" + /> + <Forms.Field + class="flex-1 w-0" + name="episode_number" + label="<?= lang('Episode.form.episode_number') ?>" + type="number" + value="<?= $episode->number ?>" + /> </div> -<?= form_fieldset('', [ - 'class' => 'flex mb-4 gap-1', -]) ?> +<fieldset class="flex gap-1"> <legend> <?= lang('Episode.form.type.label') . hint_tooltip(lang('Episode.form.type.hint'), 'ml-1') ?> </legend> -<?= form_radio( - [ - 'id' => 'full', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'full', - old('type') ? old('type') === 'full' : $episode->type === 'full', - ) ?> -<label for="full" class="inline-flex items-center"> - <?= lang('Episode.form.type.full') ?> -</label> -<?= form_radio( - [ - 'id' => 'trailer', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'trailer', - old('type') ? old('type') === 'trailer' : $episode->type === 'trailer', - ) ?> -<label for="trailer" class="inline-flex items-center"> - <?= lang('Episode.form.type.trailer') ?> -</label> -<?= form_radio( - [ - 'id' => 'bonus', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'bonus', - old('type') ? old('type') === 'bonus' : $episode->type === 'bonus', - ) ?> -<label for="bonus" class="inline-flex items-center"> - <?= lang('Episode.form.type.bonus') ?> -</label> -<?= form_fieldset_close() ?> - -<?= form_fieldset('', [ - 'class' => 'mb-6', -]) ?> +<Forms.RadioButton + value="full" + name="type" + isChecked="<?= $episode->type === 'full' ? 'true' : 'false' ?>" ><?= lang('Episode.form.type.full') ?></Forms.RadioButton> +<Forms.RadioButton + value="trailer" + name="type" + isChecked="<?= $episode->type === 'trailer' ? 'true' : 'false' ?>" ><?= lang('Episode.form.type.trailer') ?></Forms.RadioButton> +<Forms.RadioButton + value="bonus" + name="type" + isChecked="<?= $episode->type === 'bonus' ? 'true' : 'false' ?>" ><?= lang('Episode.form.type.bonus') ?></Forms.RadioButton> +</fieldset> + +<fieldset class="flex gap-1"> <legend> <?= lang('Episode.form.parental_advisory.label') . hint_tooltip(lang('Episode.form.parental_advisory.hint'), 'ml-1') ?> </legend> -<?= form_radio( - [ - 'id' => 'undefined', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'undefined', - old('parental_advisory') - ? old('parental_advisory') === 'undefined' - : $episode->parental_advisory === null, - ) ?> -<label for="undefined"><?= lang( - 'Episode.form.parental_advisory.undefined', - ) ?></label> -<?= form_radio( - [ - 'id' => 'clean', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'clean', - old('parental_advisory') - ? old('parental_advisory') === 'clean' - : $episode->parental_advisory === 'clean', - ) ?> -<label for="clean"><?= lang( - 'Episode.form.parental_advisory.clean', - ) ?></label> -<?= form_radio( - [ - 'id' => 'explicit', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'explicit', - old('parental_advisory') - ? old('parental_advisory') === 'explicit' - : $episode->parental_advisory === 'explicit', - ) ?> -<label for="explicit"><?= lang( - 'Episode.form.parental_advisory.explicit', - ) ?></label> -<?= form_fieldset_close() ?> - -<?= form_section_close() ?> - - -<?= form_section( - lang('Episode.form.show_notes_section_title'), - lang('Episode.form.show_notes_section_subtitle'), - ) ?> - -<div class="mb-4"> - <Forms.Label for="description"><?= lang('Episode.form.description') ?></Forms.Label> - <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', $episode->description_markdown, false) ?></Forms.MarkdownEditor> -</div> - -<div class="mb-4"> - <Forms.Label for="description_footer" hint="<?= lang('Episode.form.description_footer_hint') ?>" isOptional="true"><?= lang('Episode.form.description_footer') ?></Forms.Label> - <Forms.MarkdownEditor id="description_footer" name="description_footer" rows="6"><?= old('description_footer', $podcast->episode_description_footer_markdown ?? '', false) ?></Forms.MarkdownEditor> -</div> - -<?= form_section_close() ?> - -<?= form_section( - lang('Episode.form.location_section_title'), - lang('Episode.form.location_section_subtitle'), - ) ?> - -<Forms.Label for="location_name" hint="<?= lang('Episode.form.location_name_hint') ?>" isOptional="true"><?= lang('Episode.form.location_name') ?></Forms.Label> -<?= form_input([ - 'id' => 'location_name', - 'name' => 'location_name', - 'class' => 'form-input mb-4', - 'value' => old('location_name', $episode->location_name), -]) ?> -<?= form_section_close() ?> - - -<?= form_section( - lang('Episode.form.additional_files_section_title'), - lang('Episode.form.additional_files_section_subtitle', [ - 'podcastNamespaceLink' => - '“<a href="https://github.com/Podcastindex-org/podcast-namespace" target="_blank" rel="noreferrer noopener" style="text-decoration: underline;">podcast namespace</a>â€', - ]), -) ?> - -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> +<Forms.RadioButton + value="undefined" + name="parental_advisory" + isChecked="<?= $episode->parental_advisory === null ? 'true' : 'false' ?>" ><?= lang('Episode.form.parental_advisory.undefined') ?></Forms.RadioButton> +<Forms.RadioButton + value="clean" + name="parental_advisory" + isChecked="<?= $episode->parental_advisory === 'clean' ? 'true' : 'false' ?>" ><?= lang('Episode.form.parental_advisory.clean') ?></Forms.RadioButton> +<Forms.RadioButton + value="explicit" + name="parental_advisory" + isChecked="<?= $episode->parental_advisory === 'explicit' ? 'true' : 'false' ?>" ><?= lang('Episode.form.parental_advisory.explicit') ?></Forms.RadioButton> +</fieldset> + +</Forms.Section> + + +<Forms.Section + title="<?= lang('Episode.form.show_notes_section_title') ?>" + subtitle="<?= lang('Episode.form.show_notes_section_subtitle') ?>"> + +<Forms.Field + as="MarkdownEditor" + name="description" + label="<?= lang('Episode.form.description') ?>" + value="<?= $episode->description_markdown ?>" + required="true" /> + +<Forms.Field + as="MarkdownEditor" + name="description_footer" + label="<?= lang('Episode.form.description_footer') ?>" + hintText="<?= lang('Episode.form.description_footer_hint') ?>" + value="<?= $podcast->episode_description_footer_markdown ?? '' ?>" /> + +</Forms.Section> + +<Forms.Section + title="<?= lang('Episode.form.location_section_title') ?>" + subtitle="<?= lang('Episode.form.location_section_subtitle') ?>" +> +<Forms.Field + name="location_name" + label="<?= lang('Episode.form.location_name') ?>" + hint="<?= lang('Episode.form.location_name_hint') ?>" + value="<?= $episode->location_name ?>" /> +</Forms.Section> + +<Forms.Section + title="<?= lang('Episode.form.additional_files_section_title') ?>"> + +<fieldset class="flex flex-col"> <legend><?= lang('Episode.form.transcript') . '<small class="ml-1 lowercase">(' . lang('Common.optional') . ')</small>' . hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?></legend> -<div class="mb-4 form-input-tabs"> - <input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= $episode->transcript_file_remote_url - ? '' - : 'checked' ?> /> - <label for="transcript-file-upload-choice"><?= lang( - 'Common.forms.upload_file', - ) ?></label> - - <input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= $episode->transcript_file_remote_url - ? 'checked' - : '' ?> /> - <label for="transcript-file-remote-url-choice"><?= lang( - 'Common.forms.remote_url', - ) ?></label> +<div class="form-input-tabs"> + <input type="radio" name="transcript-choice" id="transcript-file-upload-choice" aria-controls="transcript-file-upload-choice" value="upload-file" <?= $episode->transcript_file_remote_url ? '' : 'checked' ?> /> + <label for="transcript-file-upload-choice"><?= lang('Common.forms.upload_file') ?></label> + + <input type="radio" name="transcript-choice" id="transcript-file-remote-url-choice" aria-controls="transcript-file-remote-url-choice" value="remote-url" <?= $episode->transcript_file_remote_url ? 'checked' : '' ?> /> + <label for="transcript-file-remote-url-choice"><?= lang('Common.forms.remote_url') ?></label> <div class="py-2 tab-panels"> <section id="transcript-file-upload" class="flex items-center tab-panel"> <?php if ($episode->transcript_file) : ?> <div class="flex justify-between"> <?= anchor( - $episode->transcript_file_url, - icon('file', 'mr-2 text-gray-500') . + $episode->transcript_file_url, + icon('file', 'mr-2 text-gray-500') . $episode->transcript_file, - [ - 'class' => 'inline-flex items-center text-xs', - 'target' => '_blank', - 'rel' => 'noreferrer noopener', - ], - ) . + [ + 'class' => 'inline-flex items-center text-xs', + 'target' => '_blank', + 'rel' => 'noreferrer noopener', + ], + ) . anchor( route_to( 'transcript-delete', @@ -299,68 +193,43 @@ </div> <?php endif; ?> <Forms.Label class="sr-only" for="transcript_file" isOptional="true"><?= lang('Episode.form.transcript_file') ?></Forms.Label> - <?= form_input([ - 'id' => 'transcript_file', - 'name' => 'transcript_file', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.txt,.html,.srt,.json', - ]) ?> + <Forms.Input class="w-full" name="transcript_file" type="file" accept=".txt,.html,.srt,.json" /> </section> <section id="transcript-file-remote-url" class="tab-panel"> <Forms.Label class="sr-only" for="transcript_file_remote_url" isOptional="true"><?= lang('Episode.form.transcript_file_remote_url') ?></Forms.Label> - <?= form_input([ - 'id' => 'transcript_file_remote_url', - 'name' => 'transcript_file_remote_url', - 'class' => 'form-input w-full', - 'type' => 'url', - 'placeholder' => 'https://...', - 'value' => old( - 'transcript_file_remote_url', - $episode->transcript_file_remote_url, - ), - ]) ?> + <Forms.Input class="w-full" placeholder="https://…" name="transcript_file_remote_url" value="<?= $episode->transcript_file_remote_url ?>" /> </section> </div> </div> -<?= form_fieldset_close() ?> +</fieldset> -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> + +<fieldset class="flex flex-col"> <legend><?= lang('Episode.form.chapters') . '<small class="ml-1 lowercase">(' . lang('Common.optional') . ')</small>' . hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?></legend> -<div class="mb-4 form-input-tabs"> - <input type="radio" name="chapters-choice" id="chapters-file-upload-choice" aria-controls="chapters-file-upload-choice" value="upload-file" <?= $episode->chapters_file_remote_url - ? '' - : 'checked' ?> /> - <label for="chapters-file-upload-choice"><?= lang( - 'Common.forms.upload_file', - ) ?></label> - - <input type="radio" name="chapters-choice" id="chapters-file-remote-url-choice" aria-controls="chapters-file-remote-url-choice" value="remote-url" <?= $episode->chapters_file_remote_url - ? 'checked' - : '' ?> /> - <label for="chapters-file-remote-url-choice"><?= lang( - 'Common.forms.remote_url', - ) ?></label> +<div class="form-input-tabs"> + <input type="radio" name="chapters-choice" id="chapters-file-upload-choice" aria-controls="chapters-file-upload-choice" value="upload-file" <?= $episode->chapters_file_remote_url ? '' : 'checked' ?> /> + <label for="chapters-file-upload-choice"><?= lang('Common.forms.upload_file') ?></label> + + <input type="radio" name="chapters-choice" id="chapters-file-remote-url-choice" aria-controls="chapters-file-remote-url-choice" value="remote-url" <?= $episode->chapters_file_remote_url ? 'checked' : '' ?> /> + <label for="chapters-file-remote-url-choice"><?= lang('Common.forms.remote_url') ?></label> <div class="py-2 tab-panels"> <section id="chapters-file-upload" class="flex items-center tab-panel"> <?php if ($episode->chapters_file) : ?> <div class="flex justify-between"> <?= anchor( - $episode->chapters_file_url, - icon('file', 'mr-2') . $episode->chapters_file, - [ - 'class' => 'inline-flex items-center text-xs', - 'target' => '_blank', - 'rel' => 'noreferrer noopener', - ], - ) . + $episode->chapters_file_url, + icon('file', 'mr-2') . $episode->chapters_file, + [ + 'class' => 'inline-flex items-center text-xs', + 'target' => '_blank', + 'rel' => 'noreferrer noopener', + ], + ) . anchor( route_to( 'chapters-delete', @@ -381,69 +250,36 @@ </div> <?php endif; ?> <Forms.Label class="sr-only" for="chapters_file" isOptional="true"><?= lang('Episode.form.chapters_file') ?></Forms.Label> - <?= form_input([ - 'id' => 'chapters_file', - 'name' => 'chapters_file', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.json', - ]) ?> + <Forms.Input class="w-full" name="chapters_file" type="file" accept=".json" /> </section> <section id="chapters-file-remote-url" class="tab-panel"> <Forms.Label class="sr-only" for="chapters_file_remote_url" isOptional="true"><?= lang('Episode.form.chapters_file_remote_url') ?></Forms.Label> - <?= form_input([ - 'id' => 'chapters_file_remote_url', - 'name' => 'chapters_file_remote_url', - 'class' => 'form-input w-full', - 'type' => 'url', - 'placeholder' => 'https://...', - 'value' => old( - 'chapters_file_remote_url', - $episode->chapters_file_remote_url, - ), - ]) ?> + <Forms.Input class="w-full" placeholder="https://…" name="chapters_file_remote_url" value="<?= $episode->chapters_file_remote_url ?>" /> </section> </div> </div> -<?= form_fieldset_close() ?> +</fieldset> +</Forms.Section> -<?= form_section_close() ?> +<Forms.Section + title="<?= lang('Episode.form.advanced_section_title') ?>" + subtitle="<?= lang('Episode.form.advanced_section_subtitle') ?>" +> +<Forms.Field + as="XMLEditor" + name="custom_rss" + label="<?= lang('Episode.form.custom_rss') ?>" + hint="<?= lang('Episode.form.custom_rss_hint') ?>" + value="<?= $episode->custom_rss_string ?>" +/> -<?= form_section( - lang('Episode.form.advanced_section_title'), - lang('Episode.form.advanced_section_subtitle'), - ) ?> -<Forms.Label for="custom_rss" hint="<?= lang('Episode.form.custom_rss_hint') ?>" isOptional="true"><?= lang('Episode.form.custom_rss') ?></Forms.Label> -<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', $episode->custom_rss_string, false) ?></Forms.XMLEditor> +</Forms.Section> -<?= form_section_close() ?> +<Forms.Toggler id="block" name="block" value="yes" checked="<?= $episode->is_blocked ? 'true' : 'false' ?>" hint="<?= lang('Episode.form.block_hint') ?>"><?= lang('Episode.form.block') ?></Forms.Toggler> -<Forms.Toggler id="block" name="block" value="yes" checked="<?= old('block', $episode->is_blocked) ?>" hint="<?= lang('Episode.form.block_hint') ?>"><?= lang('Episode.form.block') ?></Forms.Toggler> - -<div class="flex items-center justify-between"> - <?= button( - lang('Episode.delete'), - route_to('episode-delete', $podcast->id, $episode->id), - [ - 'variant' => 'danger', - 'iconLeft' => 'delete-bin', - ], - ) ?> - - <?= button( - lang('Episode.form.submit_edit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], - ) ?> -</div> +</form> -<?= form_close() ?> +<Button class="mt-8" variant="danger" uri="<?= route_to('episode-delete', $podcast->id, $episode->id) ?>" iconLeft="delete-bin"><?= lang('Episode.delete') ?></Button> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/embeddable_player.php b/themes/cp_admin/episode/embeddable_player.php index 89a5db6aeb..b6d40ed877 100644 --- a/themes/cp_admin/episode/embeddable_player.php +++ b/themes/cp_admin/episode/embeddable_player.php @@ -12,7 +12,7 @@ <p><?= lang('Episode.embeddable_player.label') ?></p> -<div class="flex w-full mt-6 mb-6"> +<div class="flex w-full mt-6"> <?php foreach ($themes as $themeKey => $theme): ?> <button style="<?= $theme[ 'style' @@ -24,52 +24,16 @@ <?php endforeach; ?> </div> -<iframe name="embeddable_player" id="embeddable_player" class="w-full max-w-xl h-36" frameborder="0" scrolling="no" style="width: 100%; overflow: hidden;" src="<?= $episode->embeddable_player_url ?>"></iframe> +<iframe name="embeddable_player" id="embeddable_player" class="w-full max-w-xl mt-6 h-36" frameborder="0" scrolling="no" style="width: 100%; overflow: hidden;" src="<?= $episode->embeddable_player_url ?>"></iframe> -<div class="flex items-center w-full mt-8"> - <?= form_textarea( - [ - 'id' => 'iframe', - 'name' => 'iframe', - 'class' => 'form-textarea w-full h-20 mr-2', - ], - "<iframe width=\"100%\" height=\"280\" frameborder=\"0\" scrolling=\"no\" style=\"width: 100%; height: 280px; overflow: hidden;\" src=\"{$episode->embeddable_player_url}\"></iframe>", - ) ?> - <?= icon_button( - 'file-copy', - lang('Episode.embeddable_player.clipboard_iframe'), - '', - [ - 'variant' => 'default', - ], - [ - 'data-type' => 'clipboard-copy', - 'data-clipboard-target' => 'iframe', - ], - ) ?> +<div class="flex items-center mt-8 gap-x-2"> + <Forms.Textarea readonly="true" class="w-full max-w-xl" name="iframe" rows="2" value="<?= esc("<iframe width=\"100%\" height=\"280\" frameborder=\"0\" scrolling=\"no\" style=\"width: 100%; height: 280px; overflow: hidden;\" src=\"{$episode->embeddable_player_url}\"></iframe>") ?>" /> + <IconButton glyph="file-copy" data-type="clipboard-copy" data-clipboard-target="iframe"><?= lang('Episode.embeddable_player.clipboard_iframe') ?></IconButton> </div> -<div class="flex items-center w-full mt-4"> - <?= form_textarea( - [ - 'id' => 'url', - 'name' => 'url', - 'class' => 'form-textarea w-full h-10 mr-2', - ], - $episode->embeddable_player_url, - ) ?> - <?= icon_button( - 'file-copy', - lang('Episode.embeddable_player.clipboard_url'), - '', - [ - 'variant' => 'default', - ], - [ - 'data-type' => 'clipboard-copy', - 'data-clipboard-target' => 'url', - ], - ) ?> +<div class="flex items-center mt-4 gap-x-2"> + <Forms.Input readonly="true" class="w-full max-w-xl" name="url" value="<?= $episode->embeddable_player_url ?>" /> + <IconButton glyph="file-copy" data-type="clipboard-copy" data-clipboard-target="url"><?= lang('Episode.embeddable_player.clipboard_url') ?></IconButton> </div> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/persons.php b/themes/cp_admin/episode/persons.php index 71aa255a8a..204f322a9f 100644 --- a/themes/cp_admin/episode/persons.php +++ b/themes/cp_admin/episode/persons.php @@ -9,38 +9,15 @@ <?= $this->endSection() ?> <?= $this->section('headerRight') ?> -<?= button( - lang('Person.create'), - route_to('person-create'), - [ - 'variant' => 'primary', - 'iconLeft' => 'add', - ], - [ - 'class' => 'mr-2', - ], -) ?> +<Button variant="primary" uri="<?= route_to('person-create') ?>" iconLeft="add"><?= lang('Person.create') ?></Button> <?= $this->endSection() ?> <?= $this->section('content') ?> -<?= form_open(route_to('episode-person-edit', $episode->id), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> -<?= csrf_field() ?> - - -<?= form_section( - lang('Person.episode_form.manage_section_title'), - lang('Person.episode_form.manage_section_subtitle'), -) ?> - - <?= data_table( [ [ - 'header' => lang('Person.episode_form.person'), + 'header' => lang('Person.episode_form.persons'), 'cell' => function ($person) { return '<div class="flex">' . '<a href="' . @@ -92,32 +69,40 @@ $episode->persons, ) ?> -<?= form_section_close() ?> - - -<?= form_section( - lang('Person.episode_form.add_section_title'), - lang('Person.episode_form.add_section_subtitle'), -) ?> - -<Forms.Label for="persons" hint="<?= lang('Person.episode_form.persons_hint') ?>"><?= lang('Person.episode_form.persons') ?></Forms.Label> -<Forms.MultiSelect id="persons" name="persons[]" class="mb-4" required="required" options="<?= htmlspecialchars(json_encode($personOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('persons', []))) ?>"/> - -<Forms.Label for="roles" hint="<?= lang('Person.episode_form.roles_hint') ?>" isOptional="true"><?= lang('Person.episode_form.roles') ?></Forms.Label> -<Forms.MultiSelect id="roles" name="roles[]" class="mb-4" options="<?= htmlspecialchars(json_encode($taxonomyOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('roles', []))) ?>"/> +<form action="<?= route_to('episode-person-edit', $episode->id) ?>" method="POST" class="mt-6"> +<?= csrf_field() ?> -<?= form_section_close() ?> -<?= button( - lang('Person.episode_form.submit_add'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> -<?= form_close() ?> +<Forms.Section + title="<?= lang('Person.episode_form.add_section_title') ?>" + subtitle="<?= lang('Person.episode_form.add_section_subtitle') ?>" +> + +<Forms.Field + as="MultiSelect" + id="persons" + name="persons[]" + label="<?= lang('Person.episode_form.persons') ?>" + hintText="<?= lang('Person.episode_form.persons_hint') ?>" + options="<?= htmlspecialchars(json_encode($personOptions)) ?>" + selected="<?= htmlspecialchars(json_encode(old('persons', []))) ?>" + required="true" +/> + +<Forms.Field + as="MultiSelect" + id="roles" + name="roles[]" + label="<?= lang('Person.episode_form.roles') ?>" + hintText="<?= lang('Person.episode_form.roles_hint') ?>" + options="<?= htmlspecialchars(json_encode($taxonomyOptions)) ?>" + selected="<?= htmlspecialchars(json_encode(old('roles', []))) ?>" + required="true" +/> + +<Button variant="primary" type="submit" class="self-end"><?= lang('Person.episode_form.submit_add') ?></Button> + +</Forms.Section> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/publish.php b/themes/cp_admin/episode/publish.php index 1f8dd44210..c0c330ba58 100644 --- a/themes/cp_admin/episode/publish.php +++ b/themes/cp_admin/episode/publish.php @@ -8,7 +8,6 @@ <?= lang('Episode.publish') ?> <?= $this->endSection() ?> - <?= $this->section('content') ?> <?= anchor( @@ -19,14 +18,9 @@ ], ) ?> -<?= form_open(route_to('episode-publish', $podcast->id, $episode->id), [ - 'method' => 'post', - 'class' => 'mx-auto flex flex-col max-w-xl items-start', - 'data-submit' => 'validate-message', -]) ?> +<form action="<?= route_to('episode-publish', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col items-start max-w-xl mx-auto" data-submit="validate-message"> <?= csrf_field() ?> -<?= form_hidden('client_timezone', 'UTC') ?> - +<input type="hidden" name="client_timezone" value="UTC" /> <label for="message" class="text-lg font-semibold"><?= lang( 'Episode.publish_form.post', @@ -34,34 +28,22 @@ <small class="max-w-md mb-2 text-gray-600"><?= lang('Episode.publish_form.post_hint') ?></small> <div class="mb-8 overflow-hidden bg-white shadow-md rounded-xl"> <div class="flex px-4 py-3"> - <img src="<?= $podcast->actor->avatar_image_url ?>" alt="<?= $podcast - ->actor->display_name ?>" class="w-12 h-12 mr-4 rounded-full" /> - <p class="flex items-baseline min-w-0"> - <span class="mr-2 font-semibold truncate"><?= $podcast->actor - ->display_name ?></span> - <span class="text-sm text-gray-500 truncate">@<?= $podcast->actor - ->username ?></span> - </p> + <img src="<?= $podcast->actor->avatar_image_url ?>" alt="<?= $podcast->actor->display_name ?>" class="w-12 h-12 mr-4 rounded-full" /> + <div class="flex flex-col min-w-0"> + <p class="flex items-baseline min-w-0"> + <span class="mr-2 font-semibold truncate"><?= $podcast->actor->display_name ?></span> + <span class="text-sm text-gray-500 truncate">@<?= $podcast->actor->username ?></span> + </p> + </div> </div> <div class="px-4 mb-2"> - <?= form_textarea( - [ - 'id' => 'message', - 'name' => 'message', - 'class' => 'form-textarea min-w-0 w-full', - 'placeholder' => 'Write your message...', - 'autofocus' => '', - ], - old('message', '', false), - [ - 'rows' => 2, - ], - ) ?> + <Forms.Textarea name="message" placeholder="<?= lang('Episode.publish_form.message_placeholder') ?>" autofocus="" rows="2" /> </div> - <div class="flex"> - <img src="<?= $episode->image->thumbnail_url ?>" alt="<?= $episode->title ?>" class="w-24 h-24" /> + <div class="flex border-t border-b"> + <img src="<?= $episode->image + ->thumbnail_url ?>" alt="<?= $episode->title ?>" class="w-24 h-24" /> <div class="flex flex-col flex-1"> - <a href="<?= $episode->link ?>" class="flex-1 px-4 py-2 bg-gray-100"> + <a href="<?= $episode->link ?>" class="flex-1 px-4 py-2"> <div class="flex items-baseline"> <span class="flex-1 w-0 mr-2 text-sm font-semibold truncate"><?= $episode->title ?></span> <?= episode_numbering( @@ -81,104 +63,47 @@ </div> </div> <footer class="flex justify-around px-6 py-3"> - <span class="inline-flex items-center"><?= icon( - 'chat', - 'text-xl mr-1 text-gray-400', - ) . '0' ?></span> - <span class="inline-flex items-center"><?= icon( - 'repeat', - 'text-xl mr-1 text-gray-400', - ) . '0' ?></span> - <span class="inline-flex items-center"><?= icon( - 'heart', - 'text-xl mr-1 text-gray-400', - ) . '0' ?></span> + <span class="inline-flex items-center"><Icon glyph="chat" class="mr-1 text-xl text-gray-400" />0</span> + <span class="inline-flex items-center"><Icon glyph="repeat" class="mr-1 text-xl text-gray-400" />0</span> + <span class="inline-flex items-center"><Icon glyph="heart" class="mr-1 text-xl text-gray-400" />0</span> </footer> </div> -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> +<fieldset class="flex flex-col"> <legend class="text-lg font-semibold"><?= lang( - 'Episode.publish_form.publication_date', -) ?></legend> -<label for="now" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'now', - 'name' => 'publication_method', - 'class' => 'text-pine-700', - ], - 'now', - old('publication_method') ? old('publish') === 'now' : true, -) ?> - <span class="ml-2"><?= lang( - 'Episode.publish_form.publication_method.now', -) ?></span> -</label> -<div class="inline-flex flex-wrap items-center radio-toggler"> - <?= form_radio( - [ - 'id' => 'schedule', - 'name' => 'publication_method', - 'class' => 'text-pine-700', - ], - 'schedule', - old('publication_method') && - old('publication_method') === 'schedule', -) ?> - <label for="schedule" class="ml-2"><?= lang( - 'Episode.publish_form.publication_method.schedule', -) ?></label> - <div class="w-full mt-2 radio-toggler-element"> - <?= form_label( - lang('Episode.publish_form.scheduled_publication_date'), - 'scheduled_publication_date', - [], - lang('Episode.publish_form.scheduled_publication_date_hint'), -) ?> - <div class="flex" data-picker="datetime"> - <?= form_input([ - 'id' => 'scheduled_publication_date', - 'name' => 'scheduled_publication_date', - 'class' => 'form-input rounded-r-none flex-1', - 'value' => old('scheduled_publication_date', ''), - 'data-input' => '', - ]) ?> - <button class="p-3 border border-l-0 border-gray-500 bg-pine-100 focus:outline-none rounded-r-md hover:bg-pine-200 focus:ring" type="button" title="<?= lang( - 'Episode.publish_form.scheduled_publication_date_clear', - ) ?>" data-clear=""><?= icon('close') ?></button> + 'Episode.publish_form.publication_date', + ) ?></legend> + <Forms.Radio id="now" name="publication_method" isChecked="<?= old('publication_method') ? old('publish') === 'now' : true ?>"><?= lang('Episode.publish_form.publication_method.now') ?></Forms.Radio> + <div class="inline-flex flex-wrap items-center radio-toggler"> + <?= form_radio( + [ + 'id' => 'schedule', + 'name' => 'publication_method', + 'class' => 'text-pine-500 border-black border-3 focus:ring-2 focus:ring-pine-500 focus:ring-offset-2 focus:ring-offset-pine-100 w-6 h-6', + ], + 'schedule', + old('publication_method') && old('publication_method') === 'schedule', + ) ?> + <Label for="schedule" class="pl-2 leading-8"><?= lang('Episode.publish_form.publication_method.schedule') ?></label> + <div class="w-full mt-2 radio-toggler-element"> + <Forms.Field + as="DatetimePicker" + name="scheduled_publication_date" + label="<?= lang('Episode.publish_form.scheduled_publication_date') ?>" + hintText="<?= lang('Episode.publish_form.scheduled_publication_date_hint') ?>" + value="<?= $episode->published_at ?>" + /> </div> </div> -</div> -<?= form_fieldset_close() ?> +</fieldset> -<div id="publish-warning" class="inline-flex flex-col hidden p-4 text-black bg-yellow-300 border-2 border-yellow-900 rounded-md" role="alert"> - <p class="flex items-baseline font-semibold"> - <?= icon('alert', 'mr-2 text-lg flex-shrink-0') . lang( - 'Episode.publish_form.message_warning', - ) ?></p> - <p> - <?= lang( - 'Episode.publish_form.message_warning_hint', - ) ?> - </p> -</div> +<Alert id="publish-warning" variant="warning" glyph="alert" class="hidden mt-2" title="<?= lang('Episode.publish_form.message_warning') ?>"><?= lang('Episode.publish_form.message_warning_hint') ?></Alert> -<?= button( - lang('Episode.publish_form.submit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'class' => 'self-end mt-4', - 'type' => 'submit', - 'data-btn-text-warning' => lang('Episode.publish_form.message_warning_submit'), - 'data-btn-text' => lang('Episode.publish_form.submit_edit'), - ], - ) ?> +<div class="flex items-center justify-between w-full mt-4"> + <Button uri="<?= route_to('episode-publish-cancel', $podcast->id, $episode->id) ?>" variant="danger"><?= lang('Episode.publish_form.cancel_publication') ?></Button> + <Button variant="primary" type="submit" data-btn-text-warning="<?= lang('Episode.publish_form.message_warning_submit') ?>" data-btn-text="<?= lang('Episode.publish_form.submit') ?>"><?= lang('Episode.publish_form.submit') ?></Button> +</div> -<?= form_close() ?> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/publish_edit.php b/themes/cp_admin/episode/publish_edit.php index 112180d859..75cba86499 100644 --- a/themes/cp_admin/episode/publish_edit.php +++ b/themes/cp_admin/episode/publish_edit.php @@ -18,15 +18,10 @@ ], ) ?> -<?= form_open(route_to('episode-publish_edit', $podcast->id, $episode->id), [ - 'method' => 'post', - 'class' => 'mx-auto flex flex-col max-w-xl items-start', - 'data-submit' => 'validate-message', -]) ?> +<form action="<?= route_to('episode-publish_edit', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col items-start max-w-xl mx-auto" data-submit="validate-message"> <?= csrf_field() ?> -<?= form_hidden('client_timezone', 'UTC') ?> -<?= form_hidden('post_id', $post->id) ?> - +<input type="hidden" name="client_timezone" value="UTC" /> +<input type="hidden" name="post_id" value="<?= $post->id ?>" /> <label for="message" class="text-lg font-semibold"><?= lang( 'Episode.publish_form.post', @@ -44,33 +39,21 @@ </div> </div> <div class="px-4 mb-2"> - <?= form_textarea( - [ - 'id' => 'message', - 'name' => 'message', - 'class' => 'form-textarea', - 'placeholder' => 'Write your message...', - 'autofocus' => '', - ], - old('message', $post->message, false), - [ - 'rows' => 2, - ], -) ?> + <Forms.Textarea name="message" placeholder="<?= lang('Episode.publish_form.message_placeholder') ?>" autofocus="" value="<?= $post->message ?>" rows="2" /> </div> - <div class="flex"> + <div class="flex border-t border-b"> <img src="<?= $episode->image - ->thumbnail_url ?>" alt="<?= $episode->title ?>" class="w-24 h-24" /> + ->thumbnail_url ?>" alt="<?= $episode->title ?>" class="w-24 h-24" /> <div class="flex flex-col flex-1"> - <a href="<?= $episode->link ?>" class="flex-1 px-4 py-2 bg-gray-100"> + <a href="<?= $episode->link ?>" class="flex-1 px-4 py-2"> <div class="flex items-baseline"> <span class="flex-1 w-0 mr-2 text-sm font-semibold truncate"><?= $episode->title ?></span> <?= episode_numbering( - $episode->number, - $episode->season_number, - 'text-xs font-semibold text-gray-600', - true, - ) ?> + $episode->number, + $episode->season_number, + 'text-xs font-semibold text-gray-600', + true, + ) ?> </div> <div class="text-xs text-gray-600"> <?= relative_time($episode->published_at) ?> @@ -84,119 +67,47 @@ </div> </div> <footer class="flex justify-around px-6 py-3"> - <span class="inline-flex items-center"><?= icon( - 'chat', - 'text-xl mr-1 text-gray-400', - ) . '0' ?></span> - <span class="inline-flex items-center"><?= icon( - 'repeat', - 'text-xl mr-1 text-gray-400', - ) . '0' ?></span> - <span class="inline-flex items-center"><?= icon( - 'heart', - 'text-xl mr-1 text-gray-400', - ) . '0' ?></span> + <span class="inline-flex items-center"><Icon glyph="chat" class="mr-1 text-xl text-gray-400" />0</span> + <span class="inline-flex items-center"><Icon glyph="repeat" class="mr-1 text-xl text-gray-400" />0</span> + <span class="inline-flex items-center"><Icon glyph="heart" class="mr-1 text-xl text-gray-400" />0</span> </footer> </div> -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> +<fieldset class="flex flex-col"> <legend class="text-lg font-semibold"><?= lang( - 'Episode.publish_form.publication_date', -) ?></legend> -<label for="now" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'now', - 'name' => 'publication_method', - 'class' => 'text-pine-700', - ], - 'now', - old('publication_method') && old('publish') === 'now', -) ?> - <span class="ml-2"><?= lang( - 'Episode.publish_form.publication_method.now', -) ?></span> -</label> -<div class="inline-flex flex-wrap items-center radio-toggler"> - <?= form_radio( - [ - 'id' => 'schedule', - 'name' => 'publication_method', - 'class' => 'text-pine-700', - ], - 'schedule', - old('publication_method') - ? old('publication_method') === 'schedule' - : true, -) ?> - <label for="schedule" class="ml-2"><?= lang( - 'Episode.publish_form.publication_method.schedule', -) ?></label> - <div class="w-full mt-2 radio-toggler-element"> - <?= form_label( - lang('Episode.publish_form.scheduled_publication_date'), - 'scheduled_publication_date', - [], - lang('Episode.publish_form.scheduled_publication_date_hint'), -) ?> - <div class="flex" data-picker="datetime"> - <?= form_input([ - 'id' => 'scheduled_publication_date', - 'name' => 'scheduled_publication_date', - 'class' => 'form-input rounded-r-none flex-1', - 'value' => old( - 'scheduled_publication_date', - $episode->published_at, - ), - 'data-input' => '', - ]) ?> - <button class="p-3 border border-l-0 border-gray-500 bg-pine-100 focus:outline-none rounded-r-md hover:bg-pine-200 focus:ring" type="button" aria-label="<?= lang( - 'Episode.publish_form.scheduled_publication_date_clear', - ) ?>" title="<?= lang( - 'Episode.publish_form.scheduled_publication_date_clear', - ) ?>" data-clear=""><?= icon('close') ?></button> + 'Episode.publish_form.publication_date', + ) ?></legend> + <Forms.Radio id="now" name="publication_method" isChecked="<?= old('publication_method') && old('publish') === 'now' ?>"><?= lang('Episode.publish_form.publication_method.now') ?></Forms.Radio> + <div class="inline-flex flex-wrap items-center radio-toggler"> + <?= form_radio( + [ + 'id' => 'schedule', + 'name' => 'publication_method', + 'class' => 'text-pine-500 border-black border-3 focus:ring-2 focus:ring-pine-500 focus:ring-offset-2 focus:ring-offset-pine-100 w-6 h-6', + ], + 'schedule', + old('publication_method') ? old('publication_method') === 'schedule' : true, + ) ?> + <Label for="schedule" class="pl-2 leading-8"><?= lang('Episode.publish_form.publication_method.schedule') ?></label> + <div class="w-full mt-2 radio-toggler-element"> + <Forms.Field + as="DatetimePicker" + name="scheduled_publication_date" + label="<?= lang('Episode.publish_form.scheduled_publication_date') ?>" + hintText="<?= lang('Episode.publish_form.scheduled_publication_date_hint') ?>" + value="<?= $episode->published_at ?>" + /> </div> </div> -</div> -<?= form_fieldset_close() ?> +</fieldset> -<div id="publish-warning" class="inline-flex flex-col hidden p-4 text-black bg-yellow-300 border-2 border-yellow-900 rounded-md" role="alert"> - <p class="flex items-baseline font-semibold"> - <?= icon('alert', 'mr-2 text-lg flex-shrink-0') . lang( - 'Episode.publish_form.message_warning', - ) ?></p> - <p> - <?= lang( - 'Episode.publish_form.message_warning_hint', - ) ?> - </p> -</div> +<Alert id="publish-warning" variant="warning" glyph="alert" class="hidden mt-2" title="<?= lang('Episode.publish_form.message_warning') ?>"><?= lang('Episode.publish_form.message_warning_hint') ?></Alert> <div class="flex items-center justify-between w-full mt-4"> - <?= anchor( - route_to('episode-publish-cancel', $podcast->id, $episode->id), - lang('Episode.publish_form.cancel_publication'), - [ - 'class' => 'py-2 px-3 rounded-full bg-red-100 text-red-900 font-semibold mr-4', - ], - ) ?> - - <?= button( - lang('Episode.publish_form.submit_edit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'data-btn-text-warning' => lang('Episode.publish_form.message_warning_submit'), - 'data-btn-text' => lang('Episode.publish_form.submit_edit'), - ], - ) ?> + <Button uri="<?= route_to('episode-publish-cancel', $podcast->id, $episode->id) ?>" variant="danger"><?= lang('Episode.publish_form.cancel_publication') ?></Button> + <Button variant="primary" type="submit" data-btn-text-warning="<?= lang('Episode.publish_form.message_warning_submit') ?>" data-btn-text="<?= lang('Episode.publish_form.submit_edit') ?>"><?= lang('Episode.publish_form.submit_edit') ?></Button> </div> -<?= form_close() ?> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/episode/soundbites.php b/themes/cp_admin/episode/soundbites.php index f7195de7bb..a09a950afc 100644 --- a/themes/cp_admin/episode/soundbites.php +++ b/themes/cp_admin/episode/soundbites.php @@ -11,7 +11,7 @@ <?= $this->section('content') ?> -<?= form_open_multipart( +<?= form_open( route_to('episode-soundbites-edit', $podcast->id, $episode->id), [ 'method' => 'post', diff --git a/themes/cp_admin/episode/unpublish.php b/themes/cp_admin/episode/unpublish.php index ab5d44eb72..8f8f4ce9dd 100644 --- a/themes/cp_admin/episode/unpublish.php +++ b/themes/cp_admin/episode/unpublish.php @@ -10,48 +10,18 @@ <?= $this->section('content') ?> -<?= form_open(route_to('episode-unpublish', $podcast->id, $episode->id), [ - 'class' => 'flex flex-col max-w-xl mx-auto', -]) ?> - -<p class="flex max-w-xl p-2 mb-4 font-semibold text-red-900 bg-red-100 border border-red-300"><?= icon( - 'alert', - 'mr-4 text-2xl flex-shrink-0 text-red-500', -) . lang('Episode.unpublish_form.disclaimer') ?></p> - -<label for="understand" class="inline-flex items-center mb-4"> - <?= form_checkbox( - [ - 'id' => 'understand', - 'name' => 'understand', - 'class' => 'text-pine-700', - 'required' => 'required', - ], - 'yes', - old('understand', false), -) ?> - <span class="ml-2"><?= lang('Episode.unpublish_form.understand') ?></span> -</label> - -<div class="self-end"> -<?= button( - lang('Common.cancel'), - route_to('episode-view', $podcast->id, $episode->id), -) ?> - -<?= button( - lang('Episode.unpublish_form.submit'), - '', - [ - 'variant' => 'danger', - ], - [ - 'type' => 'submit', - ], -) ?> -</div> +<form action="<?= route_to('episode-unpublish', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col max-w-xl mx-auto"> +<?= csrf_field() ?> + +<Alert variant="danger" glyph="alert" class="font-semibold"><?= lang('Episode.unpublish_form.disclaimer') ?></Alert> +<Forms.Checkbox name="understand" required="true" isChecked="false"><?= lang('Episode.unpublish_form.understand') ?></Forms.Checkbox> + +<div class="self-end mt-4"> + <Button uri="<?= route_to('episode-view', $podcast->id, $episode->id) ?>"><?= lang('Common.cancel') ?></Button> + <Button type="submit" variant="danger"><?= lang('Episode.unpublish_form.submit') ?></Button> +</div> -<?= form_close() ?> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/fediverse/blocked_actors.php b/themes/cp_admin/fediverse/blocked_actors.php index b785349b4f..beffc5d263 100644 --- a/themes/cp_admin/fediverse/blocked_actors.php +++ b/themes/cp_admin/fediverse/blocked_actors.php @@ -11,41 +11,10 @@ <?= $this->section('content') ?> -<?= form_open(route_to('fediverse-attempt-block-actor'), [ - 'method' => 'post', - 'class' => 'flex flex-col max-w-md mb-8', -]) ?> - -<?= form_label( - lang('Fediverse.block_lists_form.handle'), - 'blocked_users', - [], - lang('Fediverse.block_lists_form.handle_hint'), -) ?> -<?= form_input( - [ - 'id' => 'handle', - 'name' => 'handle', - 'class' => 'form-input mb-4', - 'type' => 'text', - ], - old('handle', ''), -) ?> - -<?= button( - lang('Fediverse.block_lists_form.submit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - -<?= form_close() ?> - +<form action="<?= route_to('fediverse-attempt-block-actor') ?>" method="POST" class="flex flex-col max-w-md"> + <Forms.Field name="handle" label="<?= lang('Fediverse.block_lists_form.handle') ?>" hintText="<?= lang('Fediverse.block_lists_form.handle_hint') ?>" /> + <Button variant="primary" type="submit" class="self-end"><?= lang('Fediverse.block_lists_form.submit') ?></Button> +</form> <?= data_table( [ diff --git a/themes/cp_admin/fediverse/blocked_domains.php b/themes/cp_admin/fediverse/blocked_domains.php index de8f4fd9c2..fe9bc509bf 100644 --- a/themes/cp_admin/fediverse/blocked_domains.php +++ b/themes/cp_admin/fediverse/blocked_domains.php @@ -11,39 +11,10 @@ <?= $this->section('content') ?> -<?= form_open(route_to('fediverse-attempt-block-domain'), [ - 'method' => 'post', - 'class' => 'flex flex-col max-w-md mb-8', -]) ?> - -<?= form_label( - lang('Fediverse.block_lists_form.domain'), - 'blocked_users', - [], -) ?> -<?= form_input( - [ - 'id' => 'domain', - 'name' => 'domain', - 'class' => 'form-input mb-4', - 'type' => 'text', - ], - old('domain', ''), -) ?> - -<?= button( - lang('Fediverse.block_lists_form.submit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - -<?= form_close() ?> +<form action="<?= route_to('fediverse-attempt-block-domain') ?>" method="POST" class="flex flex-col max-w-md"> + <Forms.Field name="domain" label="<?= lang('Fediverse.block_lists_form.domain') ?>" /> + <Button variant="primary" type="submit" class="self-end"><?= lang('Fediverse.block_lists_form.submit') ?></Button> +</form> <?= data_table( [ @@ -83,6 +54,7 @@ ], ], $blockedDomains, + 'mt-8' ) ?> <?= $this->endSection() ?> diff --git a/themes/cp_admin/my_account/change_password.php b/themes/cp_admin/my_account/change_password.php index 7ebdd3e430..944c4f247d 100644 --- a/themes/cp_admin/my_account/change_password.php +++ b/themes/cp_admin/my_account/change_password.php @@ -11,43 +11,20 @@ <?= $this->section('content') ?> -<?= form_open(route_to('change-password'), [ - 'class' => 'flex flex-col max-w-sm', -]) ?> -<?= csrf_field() ?> - -<?= form_label(lang('User.form.password'), 'password') ?> -<?= form_input([ - 'id' => 'password', - 'name' => 'password', - 'class' => 'form-input mb-4', - 'required' => 'required', - 'type' => 'password', -]) ?> - -<?= form_label(lang('User.form.new_password'), 'new_password') ?> -<?= form_input([ - 'id' => 'new_password', - 'name' => 'new_password', - 'class' => 'form-input mb-4', - 'required' => 'required', - 'type' => 'password', - - 'autocomplete' => 'new-password', -]) ?> - -<?= button( - lang('User.form.submit_password_change'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - -<?= form_close() ?> +<form action="<?= route_to('change-password') ?>" method="POST" class="flex flex-col max-w-sm"> + <?= csrf_field() ?> + <Forms.Field + name="password" + label="<?= lang('User.form.password') ?>" + required="true" + type="password" /> + <Forms.Field + name="new_password" + label="<?= lang('User.form.new_password') ?>" + required="true" + type="password" + autocomplete="new-password" /> + <Button variant="primary" class="self-end" type="submit"><?= lang('User.form.submit_password_change') ?></Button> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/page/create.php b/themes/cp_admin/page/create.php index d1dd679cdd..ef349fffe6 100644 --- a/themes/cp_admin/page/create.php +++ b/themes/cp_admin/page/create.php @@ -14,56 +14,32 @@ <?= form_open(route_to('page-create'), [ 'class' => 'flex flex-col max-w-3xl', ]) ?> +<form action="<?= route_to('page-create') ?>" method="POST" class="flex flex-col max-w-3xl"> <?= csrf_field() ?> -<?= form_label(lang('Page.form.title'), 'title', [ - 'class' => 'max-w-sm', -]) ?> -<?= form_input([ - 'id' => 'title', - 'name' => 'title', - 'class' => 'form-input mb-4 max-w-sm', - 'value' => old('title'), - 'required' => 'required', - 'data-slugify' => 'title', -]) ?> - -<?= form_label( - lang('Page.form.permalink'), - 'slug', - [], -) ?> -<permalink-edit class="inline-flex items-center w-full max-w-sm mb-4 text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> -<span slot="domain" class="flex-shrink-0"><?= base_url('pages') . '/' ?></span> -<?= form_input([ - 'id' => 'slug', - 'name' => 'slug', - 'class' => 'form-input flex-1 w-0 text-xs', - 'value' => old('slug'), - 'required' => 'required', - 'data-slugify' => 'slug', - 'slot' => 'slug-input', -]) ?> -</permalink-edit> - -<div class="mb-4"> - <?= form_label(lang('Page.form.content'), 'content') ?> - <Forms.MarkdownEditor id="content" name="content" required="required" rows="20"><?= old('content', '', false) ?></Forms.MarkdownEditor> +<Forms.Field + name="title" + label="<?= lang('Page.form.title') ?>" + required="true" + data-slugify="title" /> + +<div> + <Forms.Label for="slug"><?= lang('Page.form.permalink') ?></Forms.Label> + <permalink-edit class="inline-flex items-center text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> + <span slot="domain"><?= base_url('pages') . '/' ?></span> + <Forms.Input name="slug" value="<?= $episode->slug ?>" required="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" /> + </permalink-edit> </div> +<Forms.Field + as="MarkdownEditor" + name="content" + label="<?= lang('Page.form.content') ?>" + required="true" + rows="20" /> -<?= button( - lang('Page.form.submit_create'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> +<Button variant="primary" type="submit" class="self-end"><?= lang('Page.form.submit_create') ?></Button> -<?= form_close() ?> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/page/edit.php b/themes/cp_admin/page/edit.php index 43bb8016b5..14ac283eec 100644 --- a/themes/cp_admin/page/edit.php +++ b/themes/cp_admin/page/edit.php @@ -11,58 +11,36 @@ <?= $this->section('content') ?> -<?= form_open(route_to('page-edit', $page->id), [ - 'class' => 'flex flex-col max-w-3xl', -]) ?> +<form action="<?= route_to('page-edit', $page->id) ?>" method="POST" class="flex flex-col max-w-3xl"> <?= csrf_field() ?> -<?= form_label(lang('Page.form.title'), 'title', [ - 'class' => 'max-w-sm', -]) ?> -<?= form_input([ - 'id' => 'title', - 'name' => 'title', - 'class' => 'form-input mb-4 max-w-sm', - 'value' => old('title', $page->title), - 'required' => 'required', - 'data-slugify' => 'title', - 'slot' => 'slug-input', -]) ?> -<?= form_label( - lang('Page.form.permalink'), - 'slug', - [], -) ?> -<permalink-edit class="inline-flex items-center max-w-sm mb-4 text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> -<span slot="domain" class="flex-shrink-0"><?= base_url('pages') . '/' ?></span> -<?= form_input([ - 'id' => 'slug', - 'name' => 'slug', - 'class' => 'form-input flex-1 w-0 text-xs', - 'value' => old('slug', $page->slug), - 'required' => 'required', - 'data-slugify' => 'slug', -]) ?> -</permalink-edit> - -<div class="mb-4"> - <?= form_label(lang('Page.form.content'), 'content') ?> - <Forms.MarkdownEditor id="content" name="content" required="required"><?= old('content', $page->content_markdown, false) ?></Forms.MarkdownEditor> +<Forms.Field + name="title" + label="<?= lang('Page.form.title') ?>" + required="true" + data-slugify="title" + value="<?= $page->title ?>" + slot="slug-input" /> + +<div> + <Forms.Label for="slug"><?= lang('Page.form.permalink') ?></Forms.Label> + <permalink-edit class="inline-flex items-center text-xs" edit-label="<?= lang('Common.edit') ?>" copy-label="<?= lang('Common.copy') ?>" copied-label="<?= lang('Common.copied') ?>"> + <span slot="domain"><?= base_url('pages') . '/' ?></span> + <Forms.Input name="slug" value="<?= $episode->slug ?>" required="true" data-slugify="slug" slot="slug-input" class="flex-1 text-xs" value="<?= $page->slug ?>"/> + </permalink-edit> </div> -<?= button( - lang('Page.form.submit_edit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> +<Forms.Field + as="MarkdownEditor" + name="content" + label="<?= lang('Page.form.content') ?>" + value="<?= $page->content_markdown ?>" + required="true" + rows="20" /> + +<Button variant="primary" type="submit" class="self-end"><?= lang('Page.form.submit_edit') ?></Button> -<?= form_close() ?> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/person/create.php b/themes/cp_admin/person/create.php index 29c6359e07..acc0b97e9e 100644 --- a/themes/cp_admin/person/create.php +++ b/themes/cp_admin/person/create.php @@ -11,89 +11,36 @@ <?= $this->section('content') ?> -<?= form_open_multipart(route_to('person-create'), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> +<form action="<?= route_to('person-create') ?>" method="POST" class="flex flex-col" enctype="multipart/form-data"> <?= csrf_field() ?> -<?= form_section( - lang('Person.form.identity_section_title'), - lang('Person.form.identity_section_subtitle'), -) ?> - -<?= form_label(lang('Person.form.image'), 'image') ?> -<?= form_input([ - 'id' => 'image', - 'name' => 'image', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.jpg,.jpeg,.png', -]) ?> -<small class="mb-4 text-gray-600"><?= lang( - 'Person.form.image_size_hint', -) ?></small> - -<?= form_label( - lang('Person.form.full_name'), - 'full_name', - [], - lang('Person.form.full_name_hint'), -) ?> -<?= form_input([ - 'id' => 'full_name', - 'name' => 'full_name', - 'class' => 'form-input mb-4', - 'value' => old('full_name'), - 'required' => 'required', - 'data-slugify' => 'title', -]) ?> - -<?= form_label( - lang('Person.form.unique_name'), - 'unique_name', - [], - lang('Person.form.unique_name_hint'), -) ?> -<?= form_input([ - 'id' => 'unique_name', - 'name' => 'unique_name', - 'class' => 'form-input mb-4', - 'value' => old('unique_name'), - 'required' => 'required', - 'data-slugify' => 'slug', -]) ?> - -<?= form_label( - lang('Person.form.information_url'), - 'information_url', - [], - lang('Person.form.information_url_hint'), - true, -) ?> -<?= form_input([ - 'id' => 'information_url', - 'name' => 'information_url', - 'class' => 'form-input mb-4', - 'value' => old('information_url'), -]) ?> - -<?= form_section_close() ?> - -<?= button( - lang('Person.form.submit_create'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - - -<?= form_close() ?> - +<Forms.Field + name="image" + label="<?= lang('Person.form.image') ?>" + helperText="<?= lang('Person.form.image_size_hint') ?>" + type="file" + required="true" + accept=".jpg,.jpeg,.png" /> + +<Forms.Field + name="full_name" + label="<?= lang('Person.form.full_name') ?>" + hintText="<?= lang('Person.form.full_name_hint') ?>" + required="true" + data-slugify="title" /> + +<Forms.Field + name="unique_name" + label="<?= lang('Person.form.unique_name') ?>" + hintText="<?= lang('Person.form.unique_name_hint') ?>" + required="true" /> +<Forms.Field + name="information_url" + label="<?= lang('Person.form.information_url') ?>" + hintText="<?= lang('Person.form.information_url_hint') ?>" /> + +<Button variant="primary" class="self-end" type="submit"><?= lang('Person.form.submit_create') ?></Button> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/person/edit.php b/themes/cp_admin/person/edit.php index 9fef817f18..72b41e6c03 100644 --- a/themes/cp_admin/person/edit.php +++ b/themes/cp_admin/person/edit.php @@ -11,90 +11,40 @@ <?= $this->section('content') ?> -<?= form_open_multipart(route_to('person-edit', $person->id), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> +<form action="<?= route_to('person-edit', $person->id) ?>" method="POST" class="flex flex-col" enctype="multipart/form-data"> <?= csrf_field() ?> -<?= form_section( - lang('Person.form.identity_section_title'), - lang('Person.form.identity_section_subtitle') . - "<img src=\"{$person->image->thumbnail_url}\" alt=\"{$person->full_name}\" class=\"object-cover w-32 h-32 mt-3 rounded\" />", -) ?> - -<?= form_label(lang('Person.form.image'), 'image') ?> -<?= form_input([ - 'id' => 'image', - 'name' => 'image', - 'class' => 'form-input', - 'type' => 'file', - 'accept' => '.jpg,.jpeg,.png', -]) ?> -<small class="mb-4 text-gray-600"><?= lang( - 'Person.form.image_size_hint', -) ?></small> - -<?= form_label( - lang('Person.form.full_name'), - 'full_name', - [], - lang('Person.form.full_name_hint'), -) ?> -<?= form_input([ - 'id' => 'full_name', - 'name' => 'full_name', - 'class' => 'form-input mb-4', - 'value' => old('full_name', $person->full_name), - 'required' => 'required', - 'data-slugify' => 'title', -]) ?> - -<?= form_label( - lang('Person.form.unique_name'), - 'unique_name', - [], - lang('Person.form.unique_name_hint'), -) ?> -<?= form_input([ - 'id' => 'unique_name', - 'name' => 'unique_name', - 'class' => 'form-input mb-4', - 'value' => old('unique_name', $person->unique_name), - 'required' => 'required', - 'data-slugify' => 'slug', -]) ?> - -<?= form_label( - lang('Person.form.information_url'), - 'information_url', - [], - lang('Person.form.information_url_hint'), - true, -) ?> -<?= form_input([ - 'id' => 'information_url', - 'name' => 'information_url', - 'class' => 'form-input mb-4', - 'value' => old('information_url', $person->information_url), -]) ?> - -<?= form_section_close() ?> - -<?= button( - lang('Person.form.submit_edit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - - -<?= form_close() ?> - +<img src="<?= $person->image->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-32 h-32 mt-3 rounded" /> + +<Forms.Field + name="image" + label="<?= lang('Person.form.image') ?>" + helperText="<?= lang('Person.form.image_size_hint') ?>" + type="file" + accept=".jpg,.jpeg,.png" /> + +<Forms.Field + name="full_name" + value="<?= $person->full_name ?>" + label="<?= lang('Person.form.full_name') ?>" + hintText="<?= lang('Person.form.full_name_hint') ?>" + required="true" + data-slugify="title" /> + +<Forms.Field + name="unique_name" + value="<?= $person->unique_name ?>" + label="<?= lang('Person.form.unique_name') ?>" + hintText="<?= lang('Person.form.unique_name_hint') ?>" + required="true" /> +<Forms.Field + name="information_url" + label="<?= lang('Person.form.information_url') ?>" + hintText="<?= lang('Person.form.information_url_hint') ?>" + value="<?= $person->information_url ?>" /> + +<Button variant="primary" class="self-end" type="submit"><?= lang('Person.form.submit_edit') ?></Button> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/podcast/create.php b/themes/cp_admin/podcast/create.php index cbac35759f..3629681520 100644 --- a/themes/cp_admin/podcast/create.php +++ b/themes/cp_admin/podcast/create.php @@ -12,380 +12,206 @@ <?= lang('Podcast.create') ?> <?= $this->endSection() ?> - <?= $this->section('content') ?> -<?= form_open_multipart(route_to('podcast-create'), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> +<form action="<?= route_to('podcast-create') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col"> <?= csrf_field() ?> -<?= form_section( - lang('Podcast.form.identity_section_title'), - lang('Podcast.form.identity_section_subtitle'), -) ?> - -<?= form_label(lang('Podcast.form.image'), 'image') ?> -<?= form_input([ - 'id' => 'image', - 'name' => 'image', - 'class' => 'form-input', - 'required' => 'required', - 'type' => 'file', - 'accept' => '.jpg,.jpeg,.png', -]) ?> -<small class="mb-4 text-gray-600"><?= lang( - 'Common.forms.image_size_hint', -) ?></small> - -<?= form_label(lang('Podcast.form.title'), 'title') ?> -<?= form_input([ - 'id' => 'title', - 'name' => 'title', - 'class' => 'form-input mb-4', - 'value' => old('title'), - 'required' => 'required', -]) ?> - -<?= form_label( - lang('Podcast.form.handle'), - 'handle', - [], - lang('Podcast.form.handle_hint'), -) ?> -<div class="relative mb-4"> - <?= icon('at', 'absolute text-xl h-full inset-0 text-gray-400 left-3') ?> - <?= form_input([ - 'id' => 'handle', - 'name' => 'handle', - 'class' => 'form-input w-full pl-8', - 'value' => old('handle'), - 'required' => 'required', - ]) ?> -</div> - -<?= form_fieldset('', [ - 'class' => 'mb-4', -]) ?> - <legend> - <?= lang('Podcast.form.type.label') . - hint_tooltip(lang('Podcast.form.type.hint'), 'ml-1') ?> - </legend> - <?= form_radio( - [ - 'id' => 'episodic', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'episodic', - old('type') ? old('type') === 'episodic' : true, - ) ?> - <label for="episodic"><?= lang('Podcast.form.type.episodic') ?></label> - <?= form_radio( - [ - 'id' => 'serial', - 'name' => 'type', - 'class' => 'form-radio-btn', - ], - 'serial', - old('type') && old('type') === 'serial', - ) ?> - <label for="serial"><?= lang('Podcast.form.type.serial') ?></label> -<?= form_fieldset_close() ?> - -<div class="mb-4"> - <Forms.Label for="description"><?= lang('Podcast.form.description') ?></Forms.Label> - <Forms.MarkdownEditor id="description" name="description" required="required"><?= old('description', '', false) ?></Forms.MarkdownEditor> +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.identity_section_title') ?>" + subtitle="<?= lang('Podcast.form.identity_section_subtitle') ?>" > + +<Forms.Field + name="image" + label="<?= lang('Podcast.form.image') ?>" + helperText="<?= lang('Common.forms.image_size_hint') ?>" + type="file" + required="true" + accept=".jpg,.jpeg,.png" /> + +<Forms.Field + name="title" + label="<?= lang('Podcast.form.title') ?>" + required="true" /> + +<div class="flex flex-col"> + <Forms.Label for="handle" hint="<?= lang('Podcast.form.handle_hint') ?>"><?= lang('Podcast.form.handle') ?></Forms.Label> + <div class="relative"> + <Icon glyph="at" class="absolute inset-0 h-full text-xl text-gray-400 left-3" /> + <Forms.Input name="handle" class="w-full pl-8" required="true" /> + </div> </div> -<?= form_section_close() ?> - - -<?= form_section( - lang('Podcast.form.classification_section_title'), - lang('Podcast.form.classification_section_subtitle'), - ) ?> - -<?= form_label(lang('Podcast.form.language'), 'language') ?> -<?= form_dropdown('language', $languageOptions, [old('language', $browserLang)], [ - 'id' => 'language', - 'class' => 'form-select mb-4', - 'required' => 'required', -]) ?> - -<?= form_label(lang('Podcast.form.category'), 'category') ?> -<?= form_dropdown('category', $categoryOptions, [old('category', '')], [ - 'id' => 'category', - 'class' => 'form-select mb-4', - 'required' => 'required', - 'placeholder' => lang('Podcast.form.category_placeholder'), -]) ?> - -<?= form_label( - lang('Podcast.form.other_categories'), - 'other_categories', - [], - '', - true, -) ?> -<Forms.MultiSelect - id="other_categories" - name="other_categories[]" - class="mb-4" - data-max-item-count="2" - selected="<?= htmlspecialchars(json_encode(old('other_categories', []))) ?>" - options="<?= htmlspecialchars(json_encode($categoryOptions)) ?>" /> - -<?= form_fieldset('', [ - 'class' => 'mb-4', -]) ?> - <legend> - <?= lang('Podcast.form.parental_advisory.label') . - hint_tooltip(lang('Podcast.form.parental_advisory.hint'), 'ml-1') ?> - </legend> - <?= form_radio( - [ - 'id' => 'undefined', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'undefined', - old('parental_advisory') - ? old('parental_advisory') === 'undefined' - : true, - ) ?> - <label for="undefined"><?= lang( - 'Podcast.form.parental_advisory.undefined', - ) ?></label> - <?= form_radio( - [ - 'id' => 'clean', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'clean', - old('parental_advisory') && old('parental_advisory') === 'clean', - ) ?> - <label for="clean"><?= lang( - 'Podcast.form.parental_advisory.clean', - ) ?></label> - <?= form_radio( - [ - 'id' => 'explicit', - 'name' => 'parental_advisory', - 'class' => 'form-radio-btn', - ], - 'explicit', - old('parental_advisory') && old('parental_advisory') === 'explicit', - ) ?> - <label for="explicit"><?= lang( - 'Podcast.form.parental_advisory.explicit', - ) ?></label> -<?= form_fieldset_close() ?> - -<?= form_section_close() ?> - - -<?= form_section( - lang('Podcast.form.author_section_title'), - lang('Podcast.form.author_section_subtitle'), - ) ?> - -<?= form_label( - lang('Podcast.form.owner_name'), - 'owner_name', - [], - lang('Podcast.form.owner_name_hint'), - ) ?> -<?= form_input([ - 'id' => 'owner_name', - 'name' => 'owner_name', - 'class' => 'form-input mb-4', - 'value' => old('owner_name'), - 'required' => 'required', - ]) ?> - -<?= form_label( - lang('Podcast.form.owner_email'), - 'owner_email', - [], - lang('Podcast.form.owner_email_hint'), - ) ?> -<?= form_input([ - 'id' => 'owner_email', - 'name' => 'owner_email', - 'class' => 'form-input mb-4', - 'value' => old('owner_email'), - 'type' => 'email', - 'required' => 'required', - ]) ?> - -<?= form_label( - lang('Podcast.form.publisher'), - 'publisher', - [], - lang('Podcast.form.publisher_hint'), - true, - ) ?> -<?= form_input([ - 'id' => 'publisher', - 'name' => 'publisher', - 'class' => 'form-input mb-4', - 'value' => old('publisher'), - ]) ?> - -<?= form_label(lang('Podcast.form.copyright'), 'copyright', [], '', true) ?> -<?= form_input([ - 'id' => 'copyright', - 'name' => 'copyright', - 'class' => 'form-input mb-4', - 'value' => old('copyright'), -]) ?> - -<?= form_section_close() ?> - -<?= form_section( - lang('Podcast.form.location_section_title'), - lang('Podcast.form.location_section_subtitle'), -) ?> - -<?= form_label( - lang('Podcast.form.location_name'), - 'location_name', - [], - lang('Podcast.form.location_name_hint'), - true, -) ?> -<?= form_input([ - 'id' => 'location_name', - 'name' => 'location_name', - 'class' => 'form-input mb-4', - 'value' => old('location_name'), -]) ?> -<?= form_section_close() ?> - -<?= form_section( - lang('Podcast.form.monetization_section_title'), - lang('Podcast.form.monetization_section_subtitle'), -) ?> - -<?= form_label( - lang('Podcast.form.payment_pointer'), - 'payment_pointer', - [], - lang('Podcast.form.payment_pointer_hint'), - true, -) ?> -<?= form_input([ - 'id' => 'payment_pointer', - 'name' => 'payment_pointer', - 'class' => 'form-input mb-4', - 'value' => old('payment_pointer'), -]) ?> - -<?= form_label(lang('Podcast.form.partnership')) ?> -<div class="flex flex-col mb-4 gap-x-2 gap-y-4 md:flex-row"> - <div class="flex flex-col flex-shrink"> - <?= form_label( - lang('Podcast.form.partner_id'), - 'partner_id', - [ - 'class' => 'text-sm', - ], - lang('Podcast.form.partner_id_hint'), - true, -) ?> - <?= form_input([ - 'id' => 'partner_id', - 'name' => 'partner_id', - 'class' => 'form-input w-full', - 'value' => old('partner_id'), - ]) ?> +<Forms.Field + as="MarkdownEditor" + name="description" + label="<?= lang('Podcast.form.description') ?>" + required="true" /> + +<fieldset> + <legend><?= lang('Podcast.form.type.label') . + hint_tooltip(lang('Podcast.form.type.hint'), 'ml-1') ?></legend> + <div class="flex gap-2"> + <Forms.RadioButton + value="episodic" + name="type" + isChecked="true'" ><?= lang('Podcast.form.type.episodic') ?></Forms.RadioButton> + <Forms.RadioButton + value="serial" + name="type" + isChecked="false" ><?= lang('Podcast.form.type.serial') ?></Forms.RadioButton> </div> - <div class="flex flex-col"> - <?= form_label( - lang('Podcast.form.partner_link_url'), - 'partner_link_url', - [ - 'class' => 'text-sm', - ], - lang('Podcast.form.partner_link_url_hint'), - true, - ) ?> - <?= form_input([ - 'id' => 'partner_link_url', - 'name' => 'partner_link_url', - 'class' => 'form-input w-full', - 'value' => old('partner_link_url'), - ]) ?> +</fieldset> + +</Forms.Section> + +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.classification_section_title') ?>" + subtitle="<?= lang('Podcast.form.classification_section_subtitle') ?>" > + + <Forms.Field + as="Select" + name="language" + label="<?= lang('Podcast.form.language') ?>" + selected="<?= $browserLang ?>" + required="true" + options="<?= esc(json_encode($languageOptions)) ?>" /> + + <Forms.Field + as="Select" + name="category" + label="<?= lang('Podcast.form.category') ?>" + required="true" + options="<?= esc(json_encode($categoryOptions)) ?>" /> + + <Forms.Field + as="MultiSelect" + name="other_categories[]" + label="<?= lang('Podcast.form.other_categories') ?>" + data-max-item-count="2" + options="<?= esc(json_encode($categoryOptions)) ?>" /> + + <fieldset class="mb-4"> + <legend><?= lang('Podcast.form.parental_advisory.label') . + hint_tooltip(lang('Podcast.form.parental_advisory.hint'), 'ml-1') ?></legend> + <div class="flex gap-2"> + <Forms.RadioButton + value="undefined" + name="parental_advisory" + isChecked="true" ><?= lang('Podcast.form.parental_advisory.undefined') ?></Forms.RadioButton> + <Forms.RadioButton + value="clean" + name="parental_advisory" + isChecked="false" ><?= lang('Podcast.form.parental_advisory.clean', ) ?></Forms.RadioButton> + <Forms.RadioButton + value="explicit" + name="parental_advisory" + isChecked="false" ><?= lang('Podcast.form.parental_advisory.explicit', ) ?></Forms.RadioButton> + </div> + </fieldset> +</Forms.Section> + +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.author_section_title') ?>" + subtitle="<?= lang('Podcast.form.author_section_subtitle') ?>" > + +<Forms.Field + name="owner_name" + label="<?= lang('Podcast.form.owner_name') ?>" + hintText="<?= lang('Podcast.form.owner_name_hint') ?>" + required="true" /> + +<Forms.Field + name="owner_email" + type="email" + label="<?= lang('Podcast.form.owner_email') ?>" + hintText="<?= lang('Podcast.form.owner_email_hint') ?>" + required="true" /> + +<Forms.Field + name="publisher" + label="<?= lang('Podcast.form.publisher') ?>" + hintText="<?= lang('Podcast.form.publisher_hint') ?>" /> + +<Forms.Field + name="copyright" + label="<?= lang('Podcast.form.copyright') ?>" /> + +</Forms.Section> + +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.location_section_title') ?>" + subtitle="<?= lang('Podcast.form.location_section_subtitle') ?>" > + +<Forms.Field + name="location_name" + label="<?= lang('Podcast.form.location_name') ?>" + hintText="<?= lang('Podcast.form.location_name_hint') ?>" /> + +</Forms.Section> + +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.monetization_section_title') ?>" + subtitle="<?= lang('Podcast.form.monetization_section_subtitle') ?>" > + +<Forms.Field + name="payment_pointer" + label="<?= lang('Podcast.form.payment_pointer') ?>" + hintText="<?= lang('Podcast.form.payment_pointer_hint') ?>" /> + +<fieldset class="flex flex-col items-start p-4 bg-gray-100 rounded"> + <Heading tagName="legend" class="float-left" size="small"><?= lang('Podcast.form.partnership') ?></Heading> + <div class="flex flex-col w-full clear-left gap-x-2 gap-y-4 md:flex-row"> + <div class="flex flex-col flex-shrink w-32"> + <Forms.Label for="partner_id" hint="<?= lang('Podcast.form.partner_id_hint') ?>" isOptional="true"><?= lang('Podcast.form.partner_id') ?></Forms.Label> + <Forms.Input name="partner_id" /> + </div> + <div class="flex flex-col flex-1"> + <Forms.Label for="partner_link_url" hint="<?= lang('Podcast.form.partner_link_url_hint') ?>" isOptional="true"><?= lang('Podcast.form.partner_link_url') ?></Forms.Label> + <Forms.Input name="partner_link_url" /> + </div> </div> - <div class="flex flex-col"> - <?= form_label( - lang('Podcast.form.partner_image_url'), - 'partner_image_url', - [ - 'class' => 'text-sm', - ], - lang('Podcast.form.partner_image_url_hint'), - true, - ) ?> - <?= form_input([ - 'id' => 'partner_image_url', - 'name' => 'partner_image_url', - 'class' => 'form-input w-full', - 'value' => old('partner_image_url'), - ]) ?> + <div class="flex flex-col w-full mt-2"> + <Forms.Label for="partner_image_url" hint="<?= lang('Podcast.form.partner_image_url_hint') ?>" isOptional="true"><?= lang('Podcast.form.partner_image_url') ?></Forms.Label> + <Forms.Input name="partner_image_url" /> </div> -</div> - -<?= form_section_close() ?> - -<?= form_section( - lang('Podcast.form.advanced_section_title'), - lang('Podcast.form.advanced_section_subtitle'), - ) ?> -<?= form_label( - lang('Podcast.form.custom_rss'), - 'custom_rss', - [], - lang('Podcast.form.custom_rss_hint'), - true, - ) ?> -<Forms.XMLEditor id="custom_rss" name="custom_rss"><?= old('custom_rss', '', false) ?></Forms.XMLEditor> - -<?= form_section_close() ?> - -<?= form_section( - lang('Podcast.form.status_section_title'), - lang('Podcast.form.status_section_subtitle'), - ) ?> - -<Forms.Toggler class="mb-2" id="lock" name="lock" value="yes" checked="<?= old('complete', true) ?>" hint="<?= lang('Podcast.form.lock_hint') ?>"> - <?= lang('Podcast.form.lock') ?> -</Forms.Toggler> -<Forms.Toggler class="mb-2" id="block" name="block" value="yes" checked="<?= old('complete', false) ?>"> - <?= lang('Podcast.form.block') ?> -</Forms.Toggler> -<Forms.Toggler id="complete" name="complete" value="yes" checked="<?= old('complete', false) ?>"> - <?= lang('Podcast.form.complete') ?> -</Forms.Toggler> - -<?= form_section_close() ?> - -<?= button( - lang('Podcast.form.submit_create'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], - ) ?> - -<?= form_close() ?> - +</fieldset> +</Forms.Section> + +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.advanced_section_title') ?>" + subtitle="<?= lang('Podcast.form.advanced_section_subtitle') ?>" > + +<Forms.Field + as="XMLEditor" + name="custom_rss" + label="<?= lang('Podcast.form.custom_rss') ?>" + hintText="<?= lang('Podcast.form.custom_rss_hint') ?>" /> + +</Forms.Section> + +<Forms.Section + class="mb-8" + title="<?= lang('Podcast.form.status_section_title') ?>" > + <Forms.Toggler class="mb-2" name="lock" value="yes" checked="true" hint="<?= lang('Podcast.form.lock_hint') ?>"> + <?= lang('Podcast.form.lock') ?> + </Forms.Toggler> + <Forms.Toggler class="mb-2" name="block" value="yes" checked="false"> + <?= lang('Podcast.form.block') ?> + </Forms.Toggler> + <Forms.Toggler name="complete" value="yes" checked="false"> + <?= lang('Podcast.form.complete') ?> + </Forms.Toggler> +</Forms.Section> + +<Button variant="primary" type="submit" class="self-end"><?= lang('Podcast.form.submit_create') ?></Button> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/podcast/edit.php b/themes/cp_admin/podcast/edit.php index 717409bd34..ddfb2aecde 100644 --- a/themes/cp_admin/podcast/edit.php +++ b/themes/cp_admin/podcast/edit.php @@ -18,12 +18,7 @@ <?= $this->section('content') ?> -<?= form_open_multipart((string) route_to('podcast-edit', $podcast->id), [ - 'id' => 'podcast-edit-form', - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> - +<form id="podcast-edit-form" action="<?= route_to('podcast-edit', $podcast->id) ?>" method="POST" enctype='multipart/form-data' class="flex flex-col"> <?= csrf_field() ?> <Forms.Section @@ -210,19 +205,18 @@ <Forms.Section class="mb-8" - title="<?= lang('Podcast.form.status_section_title') ?>" - subtitle="<?= lang('Podcast.form.status_section_subtitle') ?>" > - <Forms.Toggler class="mb-2" id="lock" name="lock" value="yes" checked="<?= old('complete', $podcast->is_locked) ?>" hint="<?= lang('Podcast.form.lock_hint') ?>"> + title="<?= lang('Podcast.form.status_section_title') ?>" > + <Forms.Toggler class="mb-2" name="lock" value="yes" checked="<?= $podcast->is_locked ? 'true' : 'false' ?>" hint="<?= lang('Podcast.form.lock_hint') ?>"> <?= lang('Podcast.form.lock') ?> </Forms.Toggler> - <Forms.Toggler class="mb-2" id="block" name="block" value="yes" checked="<?= old('complete', $podcast->is_blocked) ?>"> + <Forms.Toggler class="mb-2" name="block" value="yes" checked="<?= $podcast->is_blocked ? 'true' : 'false' ?>"> <?= lang('Podcast.form.block') ?> </Forms.Toggler> - <Forms.Toggler id="complete" name="complete" value="yes" checked="<?= old('complete', $podcast->is_completed) ?>"> + <Forms.Toggler name="complete" value="yes" checked="<?= $podcast->is_completed ? 'true' : 'false' ?>"> <?= lang('Podcast.form.complete') ?> </Forms.Toggler> </Forms.Section> -<?= form_close() ?> +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/podcast/import.php b/themes/cp_admin/podcast/import.php index cc74371e65..8306c5f94d 100644 --- a/themes/cp_admin/podcast/import.php +++ b/themes/cp_admin/podcast/import.php @@ -10,231 +10,90 @@ <?= $this->section('content') ?> -<?= form_open_multipart(route_to('podcast-import'), [ - 'method' => 'post', - 'class' => 'flex flex-col items-start', -]) ?> -<?= csrf_field() ?> +<Alert glyph="alert" variant="danger"><?= lang('PodcastImport.warning') ?></Alert> -<div class="inline-flex w-full p-2 mb-6 text-sm font-semibold text-yellow-800 bg-red-100 border border-red-300 rounded" role="alert"> - <?= icon('alert', 'mr-2 text-lg flex-shrink-0') . - lang('PodcastImport.warning') ?> -</div> +<form action="<?= route_to('podcast-import') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col mt-6 gap-y-8"> +<?= csrf_field() ?> -<?= form_section( - lang('PodcastImport.old_podcast_section_title'), - icon('scales', 'mr-2 text-lg flex-shrink-0') . - lang('PodcastImport.old_podcast_section_subtitle'), - [], - 'inline-flex text-xs p-2 text-blue-800 font-semibold bg-blue-100 border border-blue-300 rounded', - ) ?> - -<?= form_label( - lang('PodcastImport.imported_feed_url'), - 'imported_feed_url', - [], - lang('PodcastImport.imported_feed_url_hint'), - ) ?> -<?= form_input([ - 'id' => 'imported_feed_url', - 'name' => 'imported_feed_url', - 'class' => 'form-input', - 'value' => old('imported_feed_url'), - 'placeholder' => 'https://...', - 'type' => 'url', - 'required' => 'required', - ]) ?> - -<?= form_section_close() ?> - - -<?= form_section(lang('PodcastImport.new_podcast_section_title'), '') ?> - -<?= form_label( - lang('Podcast.form.handle'), - 'handle', - [], - lang('Podcast.form.handle_hint'), - ) ?> -<div class="relative mb-4"> - <?= icon('at', 'absolute text-xl h-full inset-0 text-gray-400 left-3') ?> - <?= form_input([ - 'id' => 'handle', - 'name' => 'handle', - 'class' => 'form-input w-full pl-8', - 'value' => old('handle'), - 'required' => 'required', - ]) ?> +<Forms.Section + title="<?= lang('PodcastImport.old_podcast_section_title') ?>" + subtitle="<?= lang('PodcastImport.old_podcast_section_subtitle') ?>" + subtitleClass="inline-flex text-xs p-2 mt-2 text-blue-800 font-semibold bg-blue-100 border border-blue-300 rounded"> +<Forms.Field + name="imported_feed_url" + label="<?= lang('PodcastImport.imported_feed_url') ?>" + hintText="<?= lang('PodcastImport.imported_feed_url_hint') ?>" + placeholder="https://…" + type="url" + required="true" /> +</Forms.Section> + + +<Forms.Section + title="<?= lang('PodcastImport.new_podcast_section_title') ?>" > + +<div class="flex flex-col"> + <Forms.Label for="handle" hint="<?= lang('Podcast.form.handle_hint') ?>"><?= lang('Podcast.form.handle') ?></Forms.Label> + <div class="relative"> + <Icon glyph="at" class="absolute inset-0 h-full text-xl text-gray-400 left-3" /> + <Forms.Input name="handle" class="w-full pl-8" required="true" /> + </div> </div> -<?= form_label(lang('Podcast.form.language'), 'language') ?> -<?= form_dropdown('language', $languageOptions, [old('language', $browserLang)], [ - 'id' => 'language', - 'class' => 'form-select mb-4', - 'required' => 'required', -]) ?> - -<?= form_label(lang('Podcast.form.category'), 'category') ?> -<?= form_dropdown('category', $categoryOptions, [old('category', '')], [ - 'id' => 'category', - 'class' => 'form-select mb-4', - 'required' => 'required', - 'placeholder' => lang('Podcast.form.category_placeholder'), -]) ?> - -<?= form_section_close() ?> - - -<?= form_section( - lang('PodcastImport.advanced_params_section_title'), - lang('PodcastImport.advanced_params_section_subtitle'), -) ?> - -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> - <legend><?= lang('PodcastImport.slug_field.label') ?></legend> - <label for="link" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'title', - 'name' => 'slug_field', - 'class' => 'form-radio text-pine-700', - ], - 'title', - old('slug_field') ? old('slug_field') === 'title' : true, -) ?> - <span class="ml-2"><?= lang('PodcastImport.slug_field.title') ?></span> - </label> - <label for="title" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'link', - 'name' => 'slug_field', - 'class' => 'form-radio text-pine-700', - ], - 'link', - old('slug_field') && old('slug_field') === 'link', -) ?> - <span class="ml-2"><?= lang('PodcastImport.slug_field.link') ?></span> - </label> -<?= form_fieldset_close() ?> - -<?= form_fieldset('', [ - 'class' => 'flex flex-col mb-4', -]) ?> +<Forms.Field + as="Select" + name="language" + label="<?= lang('Podcast.form.language') ?>" + selected="<?= $browserLang ?>" + required="true" + options="<?= esc(json_encode($languageOptions)) ?>" /> + +<Forms.Field + as="Select" + name="category" + label="<?= lang('Podcast.form.category') ?>" + required="true" + options="<?= esc(json_encode($categoryOptions)) ?>" /> + +</Forms.Section> + +<Forms.Section + title="<?= lang('PodcastImport.advanced_params_section_title') ?>" + subtitle="<?= lang('PodcastImport.advanced_params_section_subtitle') ?>" > + +<fieldset class="flex flex-col mb-4"> + <legend><?= lang('PodcastImport.slug_field') ?></legend> + <Forms.Radio id="title" name="slug_field" isChecked="true"><title></span></Forms.Radio> + <Forms.Radio id="link" name="slug_field"><link></span></Forms.Radio> +</fieldset> + +<fieldset class="flex flex-col mb-4"> <legend><?= lang('PodcastImport.description_field') ?></legend> - <label for="description" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'description', - 'name' => 'description_field', - 'class' => 'form-radio text-pine-700', - ], - 'description', - old('description_field') - ? old('description_field') === 'description' - : true, -) ?> - <span class="ml-2"><description></span> - </label> - <label for="summary" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'summary', - 'name' => 'description_field', - 'class' => 'form-radio text-pine-600', - ], - 'summary', - old('description_field') && old('description_field') === 'summary', -) ?> - <span class="ml-2"><itunes:summary></span> - </label> - <label for="subtitle_summary" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'subtitle_summary', - 'name' => 'description_field', - 'class' => 'form-radio text-pine-700', - ], - 'subtitle_summary', - old('description_field') && - old('description_field') === 'subtitle_summary', -) ?> - <span class="ml-2"><itunes:subtitle> + <itunes:summary></span> - </label> - <label for="content" class="inline-flex items-center"> - <?= form_radio( - [ - 'id' => 'content', - 'name' => 'description_field', - 'class' => 'form-radio text-pine-700', - ], - 'content', - old('description_field') && old('description_field') === 'content', -) ?> - <span class="ml-2"><content:encoded></span> - </label> -<?= form_fieldset_close() ?> - - -<label class="inline-flex items-center mb-4"> - <?= form_checkbox( - [ - 'id' => 'force_renumber', - 'name' => 'force_renumber', - 'class' => 'form-checkbox text-pine-700', - ], - 'yes', - old('force_renumber', false), -) ?> - <span class="ml-2"><?= lang('PodcastImport.force_renumber') ?></span> - <?= hint_tooltip(lang('PodcastImport.force_renumber_hint'), 'ml-1') ?> -</label> - -<?= form_label( - lang('PodcastImport.season_number'), - 'season_number', - [], - lang('PodcastImport.season_number_hint'), -) ?> -<?= form_input([ - 'id' => 'season_number', - 'name' => 'season_number', - 'class' => 'form-input mb-4', - 'value' => old('season_number'), - 'type' => 'number', -]) ?> - -<?= form_label( - lang('PodcastImport.max_episodes'), - 'max_episodes', - [], - lang('PodcastImport.max_episodes_hint'), -) ?> -<?= form_input([ - 'id' => 'max_episodes', - 'name' => 'max_episodes', - 'class' => 'form-input mb-4', - 'value' => old('max_episodes'), - 'type' => 'number', -]) ?> - -<?= form_section_close() ?> - -<?= button( - lang('PodcastImport.submit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> - -<?= form_close() ?> + <Forms.Radio id="description" name="description_field" isChecked="true"><description></Forms.Radio> + <Forms.Radio id="summary" name="description_field"><itunes:summary></Forms.Radio> + <Forms.Radio id="subtitle_summary" name="description_field"><itunes:subtitle> + <itunes:summary></Forms.Radio> + <Forms.Radio id="content" name="description_field"><content:encoded></Forms.Radio> +</fieldset> + +<Forms.Checkbox name="force_renumber" hint="<?= lang('PodcastImport.force_renumber_hint') ?>"><?= lang('PodcastImport.force_renumber') ?></Forms.Checkbox> + +<Forms.Field + name="season_number" + type="number" + label="<?= lang('PodcastImport.season_number') ?>" + hintText="<?= lang('PodcastImport.season_number_hint') ?>" /> + +<Forms.Field + name="max_episodes" + type="number" + label="<?= lang('PodcastImport.max_episodes') ?>" + hintText="<?= lang('PodcastImport.max_episodes_hint') ?>" /> + +</Forms.Section> + +<Button variant="primary" type="submit" class="self-end"><?= lang('PodcastImport.submit') ?></Button> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/podcast/persons.php b/themes/cp_admin/podcast/persons.php index 39de64a4d4..44a9f55ca4 100644 --- a/themes/cp_admin/podcast/persons.php +++ b/themes/cp_admin/podcast/persons.php @@ -24,22 +24,10 @@ <?= $this->section('content') ?> -<?= form_open(route_to('podcast-person-edit', $podcast->id), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> -<?= csrf_field() ?> - -<?= form_section( - lang('Person.podcast_form.manage_section_title'), - lang('Person.podcast_form.manage_section_subtitle'), -) ?> - - <?= data_table( [ [ - 'header' => lang('Person.podcast_form.person'), + 'header' => lang('Person.podcast_form.persons'), 'cell' => function ($person) { return '<div class="flex">' . '<a href="' . @@ -90,43 +78,24 @@ $podcast->persons, ) ?> -<?= form_section_close() ?> +<form action="<?= route_to('podcast-person-edit', $podcast->id) ?>" method="POST" class="mt-6"> +<?= csrf_field() ?> +<Forms.Section + title="<?= lang('Person.podcast_form.add_section_title') ?>" + subtitle="<?= lang('Person.podcast_form.add_section_subtitle') ?>" +> -<?= form_section( - lang('Person.podcast_form.add_section_title'), - lang('Person.podcast_form.add_section_subtitle'), -) ?> +<Forms.Label for="persons" hint="<?= lang('Person.podcast_form.persons_hint') ?>"><?= lang('Person.podcast_form.persons') ?></Forms.Label> +<Forms.MultiSelect id="persons" name="persons[]" class="mb-4" required="required" options="<?= esc(json_encode($personOptions)) ?>" selected="<?= esc(json_encode(old('persons', []))) ?>"/> -<?= form_label( - lang('Person.podcast_form.persons'), - 'persons', - [], - lang('Person.podcast_form.persons_hint'), -) ?> -<Forms.MultiSelect id="persons" name="persons[]" class="mb-4" required="required" options="<?= htmlspecialchars(json_encode($personOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('persons', []))) ?>"/> +<Forms.Label for="roles" hint="<?= lang('Person.podcast_form.roles_hint') ?>" isOptional="true"><?= lang('Person.podcast_form.roles') ?></Forms.Label> +<Forms.MultiSelect id="roles" name="roles[]" class="mb-4" options="<?= esc(json_encode($taxonomyOptions)) ?>" selected="<?= esc(json_encode(old('roles', []))) ?>"/> -<?= form_label( - lang('Person.podcast_form.roles'), - 'roles', - [], - lang('Person.podcast_form.roles_hint'), - true, -) ?> -<Forms.MultiSelect id="roles" name="roles[]" class="mb-4" options="<?= htmlspecialchars(json_encode($taxonomyOptions)) ?>" selected="<?= htmlspecialchars(json_encode(old('roles', []))) ?>"/> +<Button variant="primary" class="self-end" type="submit"><?= lang('Person.podcast_form.submit_add') ?></Button> -<?= form_section_close() ?> -<?= button( - lang('Person.podcast_form.submit_add'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> -<?= form_close() ?> +</Forms.Section> + +</form> <?= $this->endSection() ?> diff --git a/themes/cp_admin/podcast/platforms.php b/themes/cp_admin/podcast/platforms.php index 001546d04e..e8d0202098 100644 --- a/themes/cp_admin/podcast/platforms.php +++ b/themes/cp_admin/podcast/platforms.php @@ -81,46 +81,30 @@ ], ) : '' ?> - <?= form_label($platform->label, $platform->slug, [ - 'class' => 'font-semibold mb-2', - ]) ?> - <?= form_input([ - 'id' => $platform->slug . '_link_url', - 'name' => 'platforms[' . $platform->slug . '][url]', - 'class' => 'form-input mb-1 w-full', - 'value' => old($platform->slug . '_link_url', $platform->link_url), - 'type' => 'url', - 'placeholder' => 'https://...', - ]) ?> - <?= form_input([ - 'id' => $platform->slug . '_link_content', - 'name' => 'platforms[' . $platform->slug . '][content]', - 'class' => 'form-input mb-1 w-full', - 'value' => old( - $platform->slug . '_link_content', - $platform->link_content, - ), - 'type' => 'text', - 'placeholder' => lang("Platforms.description.{$platform->type}"), - ]) ?> - <Forms.Toggler class="mb-1 text-sm" id="<?= $platform->slug . '_visible' ?>" name="<?= 'platforms[' . $platform->slug . '][visible]'?>" value="yes" checked="<?= old($platform->slug . '_visible', $platform->is_visible ? $platform->is_visible : false) ?>"><?= lang('Platforms.visible') ?></Forms.Toggler> - <Forms.Toggler class="text-sm" id="<?= $platform->slug . '_on_embeddable_player' ?>" name="<?= 'platforms[' . $platform->slug . '][on_embeddable_player]'?>" value="yes" checked="<?= old($platform->slug . '_on_embeddable_player', $platform->is_on_embeddable_player ? $platform->is_on_embeddable_player : false) ?>"><?= lang('Platforms.on_embeddable_player') ?></Forms.Toggler> + <fieldset> + <legend class="mb-2 font-semibold"><?= $platform->label ?></legend> + <Forms.Input + class="w-full mb-1" + id="<?= $platform->slug . '_link_url' ?>" + name="<?= 'platforms[' . $platform->slug . '][url]' ?>" + value="<?= $platform->link_url ?>" + type="url" + placeholder="https://…" /> + <Forms.Input + class="w-full mb-1" + id="<?= $platform->slug . '_link_content' ?>" + name="<?= 'platforms[' . $platform->slug . '][content]' ?>" + value="<?= $platform->link_content ?>" + placeholder="<?= lang("Platforms.description.{$platform->type}") ?>" /> + <Forms.Toggler size="small" class="text-sm" id="<?= $platform->slug . '_visible' ?>" name="<?= 'platforms[' . $platform->slug . '][visible]'?>" value="yes" checked="<?= old($platform->slug . '_visible', $platform->is_visible ? $platform->is_visible : false) ?>"><?= lang('Platforms.visible') ?></Forms.Toggler> + <Forms.Toggler size="small" class="text-sm" id="<?= $platform->slug . '_on_embeddable_player' ?>" name="<?= 'platforms[' . $platform->slug . '][on_embeddable_player]'?>" value="yes" checked="<?= old($platform->slug . '_on_embeddable_player', $platform->is_on_embeddable_player ? $platform->is_on_embeddable_player : false) ?>"><?= lang('Platforms.on_embeddable_player') ?></Forms.Toggler> + </fieldset> </div> </div> <?php endforeach; ?> -<?= button( - lang('Platforms.submit'), - '', - [ - 'variant' => 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], - ) ?> +<Button variant="primary" type="submit" class="self-end"><?= lang('Platforms.submit') ?></Button> <?= form_close() ?> diff --git a/themes/cp_app/home.php b/themes/cp_app/home.php index edd6d7e695..cae58aadc0 100644 --- a/themes/cp_app/home.php +++ b/themes/cp_app/home.php @@ -19,7 +19,7 @@ <a href="<?= route_to( 'home', ) ?>" class="inline-flex items-baseline text-3xl font-semibold font-display"><?= 'castopod' . - svg('castopod-logo', 'h-6 ml-2') ?></a> + svg('castopod-logo-base', 'h-6 ml-2') ?></a> </div> </header> <main class="container flex-1 px-4 py-10 mx-auto"> diff --git a/themes/cp_app/podcast/_layout_authenticated.php b/themes/cp_app/podcast/_layout_authenticated.php index 9999dd805d..57ec0bed07 100644 --- a/themes/cp_app/podcast/_layout_authenticated.php +++ b/themes/cp_app/podcast/_layout_authenticated.php @@ -26,7 +26,7 @@ <div class="fixed top-0 left-0 z-50 flex items-center justify-between w-full h-12 px-4 text-white shadow bg-pine-800"> <?= anchor( route_to('admin'), - 'castopod' . svg('castopod-logo', 'h-5 ml-1'), + 'castopod' . svg('castopod-logo-base', 'h-5 ml-1'), [ 'class' => 'text-2xl inline-flex items-baseline font-bold font-display', diff --git a/themes/cp_app/podcast/_partials/comment_actions_authenticated.php b/themes/cp_app/podcast/_partials/comment_actions_authenticated.php index 3d98ba9fb6..2f4951c3ce 100644 --- a/themes/cp_app/podcast/_partials/comment_actions_authenticated.php +++ b/themes/cp_app/podcast/_partials/comment_actions_authenticated.php @@ -1,5 +1,5 @@ <footer> - <form action="<?= route_to('comment-attempt-like', interact_as_actor()->username, $episode->slug, $comment->id) ?>" method="POST" class="flex items-center gap-x-4"> + <form action="<?= route_to('comment-attempt-like', interact_as_actor()->username, $comment->episode->slug, $comment->id) ?>" method="POST" class="flex items-center gap-x-4"> <button type="submit" name="action" class="inline-flex items-center hover:underline group" title="<?= lang( 'Comment.likes', [ @@ -8,7 +8,7 @@ ) ?>"><?= icon('heart', 'text-xl mr-1 text-gray-400 group-hover:text-red-600') . $comment->likes_count ?></button> <?= button( lang('Comment.reply'), - route_to('comment', $podcast->handle, $episode->slug, $comment->id), + route_to('comment', $podcast->handle, $comment->episode->slug, $comment->id), [ 'size' => 'small', ], @@ -16,7 +16,7 @@ </form> <?php if ($comment->replies_count): ?> <?= anchor( - route_to('comment', $podcast->handle, $episode->slug, $comment->id), + route_to('comment', $podcast->handle, $comment->episode->slug, $comment->id), icon('caret-down', 'text-xl mr-1') . lang('Comment.view_replies', [ 'numberOfReplies' => $comment->replies_count, ]), diff --git a/themes/cp_app/podcast/_partials/episode_preview_card.php b/themes/cp_app/podcast/_partials/episode_preview_card.php index 1dc8a4d202..6ad4b9092b 100644 --- a/themes/cp_app/podcast/_partials/episode_preview_card.php +++ b/themes/cp_app/podcast/_partials/episode_preview_card.php @@ -21,6 +21,6 @@ </div> <?= relative_time($episode->published_at, 'text-xs whitespace-nowrap') ?> </a> - <?= play_episode_button($episode->id, $episode->image->thumbnail_url, $episode->title, $podcast->title, $episode->audio_file_web_url, $episode->audio_file_mimetype, 'mt-auto') ?> + <?= play_episode_button($episode->id, $episode->image->thumbnail_url, $episode->title, $episode->podcast->title, $episode->audio_file_web_url, $episode->audio_file_mimetype, 'mt-auto') ?> </div> </div> diff --git a/themes/cp_app/podcast/activity.php b/themes/cp_app/podcast/activity.php index 4daffdeb49..332605910f 100644 --- a/themes/cp_app/podcast/activity.php +++ b/themes/cp_app/podcast/activity.php @@ -45,12 +45,14 @@ <?php foreach ($posts as $post): ?> <?php if ($post->reblog_of_id !== null): ?> <?= view('podcast/_partials/reblog', [ - 'post' => $post->reblog_of_post, - ]) ?> + 'post' => $post->reblog_of_post, + 'podcast' => $podcast, +]) ?> <?php else: ?> <?= view('podcast/_partials/post', [ - 'post' => $post, - ]) ?> + 'post' => $post, + 'podcast' => $podcast, +]) ?> <?php endif; ?> <?php endforeach; ?> </section> diff --git a/themes/cp_app/podcast/activity_authenticated.php b/themes/cp_app/podcast/activity_authenticated.php index 255f170bd9..06bec8558d 100644 --- a/themes/cp_app/podcast/activity_authenticated.php +++ b/themes/cp_app/podcast/activity_authenticated.php @@ -100,10 +100,12 @@ <?php if ($post->reblog_of_id !== null): ?> <?= view('podcast/_partials/reblog_authenticated', [ 'post' => $post->reblog_of_post, + 'podcast' => $podcast, ]) ?> <?php else: ?> <?= view('podcast/_partials/post_authenticated', [ 'post' => $post, + 'podcast' => $podcast, ]) ?> <?php endif; ?> <?php endforeach; ?> diff --git a/themes/cp_app/podcast/episode.php b/themes/cp_app/podcast/episode.php index 485a907396..dcccf80c17 100644 --- a/themes/cp_app/podcast/episode.php +++ b/themes/cp_app/podcast/episode.php @@ -98,6 +98,7 @@ <?php foreach ($episode->posts as $post): ?> <?= view('podcast/_partials/post', [ 'post' => $post, + 'podcast' => $podcast, ]) ?> <?php endforeach; ?> </section> diff --git a/themes/cp_app/podcast/episode_authenticated.php b/themes/cp_app/podcast/episode_authenticated.php index 77fd6e3ebe..f1a2b79a0a 100644 --- a/themes/cp_app/podcast/episode_authenticated.php +++ b/themes/cp_app/podcast/episode_authenticated.php @@ -132,6 +132,7 @@ <?php foreach ($episode->comments as $comment): ?> <?= view('podcast/_partials/comment_authenticated', [ 'comment' => $comment, + 'podcast' => $podcast, ]) ?> <?php endforeach; ?> </section> @@ -186,6 +187,7 @@ <?php foreach ($episode->posts as $post): ?> <?= view('podcast/_partials/post_authenticated', [ 'post' => $post, + 'podcast' => $podcast, ]) ?> <?php endforeach; ?> </section> -- GitLab