From e64548b982ba47ff35f2272e2e30dd85eeba950b Mon Sep 17 00:00:00 2001 From: Yassine Doghri 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 | 46 +- themes/cp_admin/contributor/edit.php | 32 +- themes/cp_admin/episode/create.php | 477 ++++++---------- themes/cp_admin/episode/edit.php | 488 ++++++---------- themes/cp_admin/episode/embeddable_player.php | 52 +- themes/cp_admin/episode/persons.php | 79 ++- 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 | 46 +- 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 | 64 +-- themes/cp_admin/page/edit.php | 70 +-- themes/cp_admin/person/create.php | 103 +--- themes/cp_admin/person/edit.php | 106 +--- themes/cp_admin/podcast/create.php | 540 ++++++------------ themes/cp_admin/podcast/edit.php | 18 +- themes/cp_admin/podcast/import.php | 277 +++------ 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, 1391 insertions(+), 2501 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 764477fc..184825ad 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 cb39152c..b7670d82 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 a4457247..6477b70e 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 fa6b4897..886181be 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 2aa0a913..47dc2625 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 00000000..482eebfe --- /dev/null +++ b/app/Resources/images/castopod-logo-base.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/Resources/images/castopod-logo.svg b/app/Resources/images/castopod-logo.svg index 444036e3..039deb74 100644 --- a/app/Resources/images/castopod-logo.svg +++ b/app/Resources/images/castopod-logo.svg @@ -1,39 +1,6 @@ - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/app/Resources/images/castopod-mascot_confused.svg b/app/Resources/images/castopod-mascot_confused.svg index b4ff04f5..5d6f9d32 100644 --- a/app/Resources/images/castopod-mascot_confused.svg +++ b/app/Resources/images/castopod-mascot_confused.svg @@ -1,234 +1,68 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/Resources/js/modules/Clipboard.ts b/app/Resources/js/modules/Clipboard.ts index 09718bcf..defb176a 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 e7a2b13a..57b0a75b 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 ac4a3fab..44716ece 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 b124f0f4..be217ecf 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 00000000..478c42c2 --- /dev/null +++ b/app/Views/Components/Alert.php @@ -0,0 +1,39 @@ + '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 ? '' : ''; + $title = $this->title === null ? '' : '
' . $this->title . '
'; + $class = 'inline-flex w-full p-2 text-sm border rounded ' . $variantClasses[$this->variant] . ' ' . $this->class; + + $attributes = stringify_attributes($this->attributes); + + return <<{$glyph}
{$title}{$this->slot}
+ HTML; + } +} diff --git a/app/Views/Components/Button.php b/app/Views/Components/Button.php index 3c29a3a3..34473df4 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 .= ''; } + 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 <<{$this->slot} + <{$tagName} class="{$buttonClass}" {$attributes}>{$this->slot} HTML; } } diff --git a/app/Views/Components/Forms/Checkbox.php b/app/Views/Components/Forms/Checkbox.php new file mode 100644 index 00000000..440300b7 --- /dev/null +++ b/app/Views/Components/Forms/Checkbox.php @@ -0,0 +1,39 @@ +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 << + {$checkboxInput} + {$this->slot}{$hint} + + HTML; + } +} diff --git a/app/Views/Components/Forms/DatetimePicker.php b/app/Views/Components/Forms/DatetimePicker.php new file mode 100644 index 00000000..19229b28 --- /dev/null +++ b/app/Views/Components/Forms/DatetimePicker.php @@ -0,0 +1,29 @@ +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 << + {$dateInput} + + + HTML; + } +} diff --git a/app/Views/Components/Forms/FormComponent.php b/app/Views/Components/Forms/FormComponent.php index 785c0496..818f1ff5 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 05174678..158fd3de 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 7d771099..2379ab42 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 609780f6..49bbac3e 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 ? '(' . lang('Common.optional') . ')' : ''; $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 <<{$this->slot}{$optionalText}{$hint} HTML; diff --git a/app/Views/Components/Forms/MultiSelect.php b/app/Views/Components/Forms/MultiSelect.php index f9c25c07..9ae032aa 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 @@ -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 00000000..cdbcd650 --- /dev/null +++ b/app/Views/Components/Forms/Radio.php @@ -0,0 +1,32 @@ +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 <<{$radioInput}{$this->slot} + HTML; + } +} diff --git a/app/Views/Components/Forms/RadioButton.php b/app/Views/Components/Forms/RadioButton.php index 222afa1f..6d354421 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 38adec87..7458f643 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 ? '' : '

' . $this->subtitle . '

'; + $subtitle = $this->subtitle === null ? '' : '

' . $this->subtitle . '

'; return << diff --git a/app/Views/Components/Forms/Select.php b/app/Views/Components/Forms/Select.php index 983a6be0..2b8f4521 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 00000000..31bc45de --- /dev/null +++ b/app/Views/Components/Forms/Textarea.php @@ -0,0 +1,31 @@ +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 << + * @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']); + $sizeClass = [ + 'base' => 'form-switch-slider', + 'small' => 'form-switch-slider form-switch-slider--small', + ]; + $this->attributes['class'] = 'form-switch'; - helper('form'); - - $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 << {$checkbox} - + {$this->slot}{$hint} HTML; diff --git a/app/Views/Components/Forms/XMLEditor.php b/app/Views/Components/Forms/XMLEditor.php index 71e01d24..c3ec19ba 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 diff --git a/app/Views/Components/Heading.php b/app/Views/Components/Heading.php index 8cfa3792..249bc183 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 00000000..574cc817 --- /dev/null +++ b/app/Views/Components/IconButton.php @@ -0,0 +1,21 @@ +attributes); + + return << + HTML; + } +} diff --git a/modules/Admin/Language/en/Episode.php b/modules/Admin/Language/en/Episode.php index 6f90e69c..181e446c 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 7306ed27..334e5351 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 946b0b1b..cd8d0872 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 b6e8774c..8c70b892 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 fc3d4936..1061e343 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 ad2aeda2..db2e1ab4 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 1ef22cd7..a4919c6d 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 94b3167d..58dd92b8 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 8da77487..e77eaf7b 100644 --- a/themes/cp_admin/_layout.php +++ b/themes/cp_admin/_layout.php @@ -24,7 +24,7 @@ - + - + renderSection('content') ?> diff --git a/themes/cp_admin/_message_block.php b/themes/cp_admin/_message_block.php new file mode 100644 index 00000000..3794ba39 --- /dev/null +++ b/themes/cp_admin/_message_block.php @@ -0,0 +1,20 @@ +has('message')): ?> + + + +has('error')): ?> + + + +has('errors')): ?> + +
    + +
  • + +
+
+ diff --git a/themes/cp_admin/contributor/add.php b/themes/cp_admin/contributor/add.php index 80a812a2..e272466d 100644 --- a/themes/cp_admin/contributor/add.php +++ b/themes/cp_admin/contributor/add.php @@ -11,39 +11,27 @@ section('content') ?> -id), [ - 'class' => 'flex flex-col max-w-sm', -]) ?> +
- - 'user', - 'class' => 'form-select mb-4', - 'required' => 'required', - 'placeholder' => lang('Contributor.form.user_placeholder'), -]) ?> + - - 'role', - 'class' => 'form-select mb-4', - 'required' => 'required', - 'placeholder' => lang('Contributor.form.role_placeholder'), -]) ?> + - 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> + - + endSection() ?> diff --git a/themes/cp_admin/contributor/edit.php b/themes/cp_admin/contributor/edit.php index 4c912acb..2baa789e 100644 --- a/themes/cp_admin/contributor/edit.php +++ b/themes/cp_admin/contributor/edit.php @@ -11,30 +11,20 @@ section('content') ?> -id, $user->id), [ - 'class' => 'flex flex-col max-w-sm', -]) ?> +
- - 'role', - 'class' => 'form-select mb-4', - 'required' => 'required', -]) ?> + - 'primary', - ], - [ - 'type' => 'submit', - 'class' => 'self-end', - ], -) ?> + - + endSection() ?> diff --git a/themes/cp_admin/episode/create.php b/themes/cp_admin/episode/create.php index 8afc63c0..34b3e04c 100644 --- a/themes/cp_admin/episode/create.php +++ b/themes/cp_admin/episode/create.php @@ -11,356 +11,203 @@ section('content') ?> -id), [ - 'method' => 'post', - 'class' => 'flex flex-col', -]) ?> + + +
- -