mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
fix(ux): allow for empty message upon episode publication and warn user on submit
- clarify distiction between the announcement post and the show notes - change "note" occurences in UI by "post" - show warning message explaining why the podcaster should fill the message area - the podcaster can choose to publish the episode with an empty message anyways - redirect user to episode dashboard with error message when episode publication pages are inaccessible instead of showing a 404 error - add a cancel publication button in publish-edit form when episode is scheduled closes #129
This commit is contained in:
parent
8f3e9d90c1
commit
33d01b8d4f
@ -310,6 +310,15 @@ $routes->group(
|
||||
'permission:podcast-manage_publications',
|
||||
],
|
||||
);
|
||||
$routes->get(
|
||||
'publish-cancel',
|
||||
'EpisodeController::publishCancel/$1/$2',
|
||||
[
|
||||
'as' => 'episode-publish-cancel',
|
||||
'filter' =>
|
||||
'permission:podcast-manage_publications',
|
||||
],
|
||||
);
|
||||
$routes->get(
|
||||
'unpublish',
|
||||
'EpisodeController::unpublish/$1/$2',
|
||||
|
@ -388,7 +388,7 @@ class EpisodeController extends BaseController
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function publish(): string
|
||||
public function publish(): string | RedirectResponse
|
||||
{
|
||||
if ($this->episode->publication_status === 'not_published') {
|
||||
helper(['form']);
|
||||
@ -405,7 +405,10 @@ class EpisodeController extends BaseController
|
||||
return view('admin/episode/publish', $data);
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
|
||||
'error',
|
||||
lang('Episode.publish_error')
|
||||
);
|
||||
}
|
||||
|
||||
public function attemptPublish(): RedirectResponse
|
||||
@ -478,7 +481,7 @@ class EpisodeController extends BaseController
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
|
||||
}
|
||||
|
||||
public function publishEdit(): string
|
||||
public function publishEdit(): string | RedirectResponse
|
||||
{
|
||||
if ($this->episode->publication_status === 'scheduled') {
|
||||
helper(['form']);
|
||||
@ -500,7 +503,11 @@ class EpisodeController extends BaseController
|
||||
]);
|
||||
return view('admin/episode/publish_edit', $data);
|
||||
}
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
|
||||
'error',
|
||||
lang('Episode.publish_edit_error')
|
||||
);
|
||||
}
|
||||
|
||||
public function attemptPublishEdit(): RedirectResponse
|
||||
@ -572,7 +579,44 @@ class EpisodeController extends BaseController
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
|
||||
}
|
||||
|
||||
public function unpublish(): string
|
||||
public function publishCancel(): RedirectResponse
|
||||
{
|
||||
if ($this->episode->publication_status === 'scheduled') {
|
||||
$db = db_connect();
|
||||
$db->transStart();
|
||||
|
||||
$statusModel = new StatusModel();
|
||||
$status = $statusModel
|
||||
->where([
|
||||
'actor_id' => $this->podcast->actor_id,
|
||||
'episode_id' => $this->episode->id,
|
||||
])
|
||||
->first();
|
||||
$statusModel->removeStatus($status);
|
||||
|
||||
$this->episode->published_at = null;
|
||||
|
||||
$episodeModel = new EpisodeModel();
|
||||
if (! $episodeModel->update($this->episode->id, $this->episode)) {
|
||||
$db->transRollback();
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
->with('errors', $episodeModel->errors());
|
||||
}
|
||||
|
||||
$db->transComplete();
|
||||
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
|
||||
}
|
||||
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
|
||||
'error',
|
||||
lang('Episode.publish_cancel_error')
|
||||
);
|
||||
}
|
||||
|
||||
public function unpublish(): string | RedirectResponse
|
||||
{
|
||||
if ($this->episode->publication_status === 'published') {
|
||||
helper(['form']);
|
||||
@ -589,7 +633,10 @@ class EpisodeController extends BaseController
|
||||
return view('admin/episode/unpublish', $data);
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
|
||||
'error',
|
||||
lang('Episode.unpublish_error')
|
||||
);
|
||||
}
|
||||
|
||||
public function attemptUnpublish(): RedirectResponse
|
||||
|
@ -86,11 +86,11 @@ if (! function_exists('button')) {
|
||||
}
|
||||
|
||||
if ($options['iconLeft']) {
|
||||
$label = icon($options['iconLeft'], 'mr-2') . $label;
|
||||
$label = icon((string) $options['iconLeft'], 'mr-2') . $label;
|
||||
}
|
||||
|
||||
if ($options['iconRight']) {
|
||||
$label .= icon($options['iconRight'], 'ml-2');
|
||||
$label .= icon((string) $options['iconRight'], 'ml-2');
|
||||
}
|
||||
|
||||
if ($uri !== '') {
|
||||
|
@ -27,8 +27,8 @@ return [
|
||||
other {# total shares}
|
||||
}',
|
||||
'total_statuses' => '{numberOfTotalStatuses, plural,
|
||||
one {# note}
|
||||
other {# total notes}
|
||||
one {# total post}
|
||||
other {# total posts}
|
||||
}',
|
||||
'all_podcast_episodes' => 'All podcast episodes',
|
||||
'back_to_podcast' => 'Go back to podcast',
|
||||
@ -36,6 +36,10 @@ return [
|
||||
'publish' => 'Publish',
|
||||
'publish_edit' => 'Edit publication',
|
||||
'unpublish' => 'Unpublish',
|
||||
'publish_error' => 'Episode is already published.',
|
||||
'publish_edit_error' => 'Episode is already published.',
|
||||
'publish_cancel_error' => 'Episode is already published.',
|
||||
'unpublish_error' => 'Episode is not published.',
|
||||
'delete' => 'Delete',
|
||||
'go_to_page' => 'Go to page',
|
||||
'create' => 'Add an episode',
|
||||
@ -112,9 +116,10 @@ return [
|
||||
'submit_edit' => 'Save episode',
|
||||
],
|
||||
'publish_form' => [
|
||||
'status' => 'Your note',
|
||||
'back_to_episode_dashboard' => 'Back to episode dashboard',
|
||||
'status' => 'Your announcement post',
|
||||
'status_hint' =>
|
||||
'The message you write will be broadcasted to all your followers in the fediverse.',
|
||||
"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.",
|
||||
'publication_date' => 'Publication date',
|
||||
'publication_method' => [
|
||||
'now' => 'Now',
|
||||
@ -126,6 +131,10 @@ return [
|
||||
'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm',
|
||||
'submit' => 'Publish',
|
||||
'submit_edit' => 'Edit publication',
|
||||
'cancel_publication' => 'Cancel publication',
|
||||
'message_warning' => 'You did not write a message for your announcement post!',
|
||||
'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.',
|
||||
'message_warning_submit' => 'Publish anyways',
|
||||
],
|
||||
'unpublish_form' => [
|
||||
'disclaimer' =>
|
||||
|
@ -224,8 +224,8 @@ return [
|
||||
other {<span class="font-semibold">#</span> followers}
|
||||
}',
|
||||
'statuses' => '{numberOfStatuses, plural,
|
||||
one {<span class="font-semibold">#</span> note}
|
||||
other {<span class="font-semibold">#</span> notes}
|
||||
one {<span class="font-semibold">#</span> post}
|
||||
other {<span class="font-semibold">#</span> posts}
|
||||
}',
|
||||
'activity' => 'Activity',
|
||||
'episodes' => 'Episodes',
|
||||
|
@ -27,8 +27,8 @@ return [
|
||||
other {# partages en tout}
|
||||
}',
|
||||
'total_statuses' => '{numberOfTotalStatuses, plural,
|
||||
one {# note}
|
||||
other {# notes}
|
||||
one {# message}
|
||||
other {# messages}
|
||||
}',
|
||||
'all_podcast_episodes' => 'Tous les épisodes du podcast',
|
||||
'back_to_podcast' => 'Revenir au podcast',
|
||||
@ -36,6 +36,10 @@ return [
|
||||
'publish' => 'Publier',
|
||||
'publish_edit' => 'Modifier la publication',
|
||||
'unpublish' => 'Dépublier',
|
||||
'publish_error' => 'L’épisode est déjà publié.',
|
||||
'publish_edit_error' => 'L’épisode est déjà publié.',
|
||||
'publish_cancel_error' => 'L’épisode est déjà publié.',
|
||||
'unpublish_error' => 'L’épisode n’est pas publié.',
|
||||
'delete' => 'Supprimer',
|
||||
'go_to_page' => 'Voir',
|
||||
'create' => 'Ajouter un épisode',
|
||||
@ -115,9 +119,10 @@ return [
|
||||
'submit_edit' => 'Enregistrer l’épisode',
|
||||
],
|
||||
'publish_form' => [
|
||||
'status' => 'Votre note',
|
||||
'back_to_episode_dashboard' => 'Retour au tableau de bord de l’épisode',
|
||||
'status' => 'Votre message de publication',
|
||||
'status_hint' =>
|
||||
'Le message que vous écrirez sera diffusé à toutes les personnes qui vous suivent dans le fédiverse.',
|
||||
'É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.',
|
||||
'publication_date' => 'Date de publication',
|
||||
'publication_date_clear' => 'Effacer la date de publication',
|
||||
'publication_date_hint' =>
|
||||
@ -132,6 +137,10 @@ return [
|
||||
'Vous pouvez planifier la sortie de l’épisode en saisissant une date de publication future. Ce champ doit être au format YYYY-MM-DD HH:mm',
|
||||
'submit' => 'Publier',
|
||||
'submit_edit' => 'Modifier la publication',
|
||||
'cancel_publication' => 'Annuler la publication',
|
||||
'message_warning' => 'Vous n’avez pas saisi de message pour l’annonce de votre épisode !',
|
||||
'message_warning_hint' => 'Ajouter un message augmente l’engagement social, menant à une meilleure visibilité pour votre épisode.',
|
||||
'message_warning_submit' => 'Publish quand même',
|
||||
],
|
||||
'soundbites' => 'Extraits sonores',
|
||||
'soundbites_form' => [
|
||||
|
@ -226,8 +226,8 @@ return [
|
||||
other {<span class="font-semibold">#</span> abonné·e·s}
|
||||
}',
|
||||
'notes' => '{numberOfStatuses, plural,
|
||||
one {<span class="font-semibold">#</span> note}
|
||||
other {<span class="font-semibold">#</span> notes}
|
||||
one {<span class="font-semibold">#</span> message}
|
||||
other {<span class="font-semibold">#</span> messages}
|
||||
}',
|
||||
'activity' => 'Activité',
|
||||
'episodes' => 'Épisodes',
|
||||
|
@ -81,7 +81,7 @@ class StatusModel extends UuidModel
|
||||
*/
|
||||
protected $validationRules = [
|
||||
'actor_id' => 'required',
|
||||
'message_html' => 'required_without[reblog_of_id]|max_length[500]',
|
||||
'message_html' => 'max_length[500]',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,7 @@ import DateTimePicker from "./modules/DateTimePicker";
|
||||
import Dropdown from "./modules/Dropdown";
|
||||
import MarkdownEditor from "./modules/MarkdownEditor";
|
||||
import MultiSelect from "./modules/MultiSelect";
|
||||
import PublishMessageWarning from "./modules/PublishMessageWarning";
|
||||
import SidebarToggler from "./modules/SidebarToggler";
|
||||
import Slugify from "./modules/Slugify";
|
||||
import Soundbites from "./modules/Soundbites";
|
||||
@ -23,3 +24,4 @@ Time();
|
||||
Soundbites();
|
||||
Clipboard();
|
||||
ThemePicker();
|
||||
PublishMessageWarning();
|
||||
|
51
app/Views/_assets/modules/PublishMessageWarning.ts
Normal file
51
app/Views/_assets/modules/PublishMessageWarning.ts
Normal file
@ -0,0 +1,51 @@
|
||||
const PublishMessageWarning = (): void => {
|
||||
const publishForm: HTMLFormElement | null = document.querySelector(
|
||||
"form[data-submit='validate-message']"
|
||||
);
|
||||
|
||||
if (publishForm) {
|
||||
const messageTextArea: HTMLTextAreaElement | null = publishForm.querySelector(
|
||||
"[name='message']"
|
||||
);
|
||||
const submitButton: HTMLButtonElement | null = publishForm.querySelector(
|
||||
"button[type='submit']"
|
||||
);
|
||||
const publishMessageWarning: HTMLDivElement | null = publishForm.querySelector(
|
||||
"[id='publish-warning']"
|
||||
);
|
||||
|
||||
if (
|
||||
messageTextArea &&
|
||||
submitButton &&
|
||||
submitButton.dataset.btnTextWarning &&
|
||||
submitButton.dataset.btnText &&
|
||||
publishMessageWarning
|
||||
) {
|
||||
publishForm.addEventListener("submit", (event) => {
|
||||
if (
|
||||
messageTextArea.value === "" &&
|
||||
publishMessageWarning.classList.contains("hidden")
|
||||
) {
|
||||
event.preventDefault();
|
||||
|
||||
publishMessageWarning.classList.remove("hidden");
|
||||
messageTextArea.focus();
|
||||
submitButton.innerText = submitButton.dataset
|
||||
.btnTextWarning as string;
|
||||
}
|
||||
});
|
||||
|
||||
messageTextArea.addEventListener("input", () => {
|
||||
if (
|
||||
submitButton.innerText !== submitButton.dataset.btnText &&
|
||||
messageTextArea.value !== ""
|
||||
) {
|
||||
publishMessageWarning.classList.add("hidden");
|
||||
submitButton.innerText = submitButton.dataset.btnText as string;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default PublishMessageWarning;
|
@ -11,26 +11,34 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<?= anchor(
|
||||
route_to('episode-view', $podcast->id, $episode->id),
|
||||
icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'),
|
||||
['class' => 'inline-flex items-center font-semibold mr-4 text-sm'],
|
||||
) ?>
|
||||
|
||||
<?= form_open(route_to('episode-publish', $podcast->id, $episode->id), [
|
||||
'method' => 'post',
|
||||
'class' => 'flex flex-col max-w-xl items-start',
|
||||
'class' => 'mx-auto flex flex-col max-w-xl items-start',
|
||||
'data-submit' => 'validate-message'
|
||||
]) ?>
|
||||
<?= csrf_field() ?>
|
||||
<?= form_hidden('client_timezone', 'UTC') ?>
|
||||
|
||||
|
||||
<label for="message" class="text-lg font-semibold"><?= lang(
|
||||
'Episode.publish_form.status',
|
||||
) . hint_tooltip(lang('Episode.publish_form.status_hint'), 'ml-1') ?></label>
|
||||
'Episode.publish_form.status',
|
||||
) ?></label>
|
||||
<small class="max-w-md mb-2 text-gray-600"><?= lang('Episode.publish_form.status_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"/>
|
||||
->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>
|
||||
->display_name ?></span>
|
||||
<span class="text-sm text-gray-500 truncate">@<?= $podcast->actor
|
||||
->username ?></span>
|
||||
->username ?></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="px-4 mb-2">
|
||||
@ -39,17 +47,15 @@
|
||||
'id' => 'message',
|
||||
'name' => 'message',
|
||||
'class' => 'form-textarea min-w-0 w-full',
|
||||
'required' => 'required',
|
||||
'placeholder' => 'Write your message...',
|
||||
'autofocus' => ''
|
||||
],
|
||||
old('message', '', false),
|
||||
['rows' => 2],
|
||||
) ?>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<img
|
||||
src="<?= $episode->image->thumbnail_url ?>"
|
||||
alt="<?= $episode->title ?>" class="w-24 h-24"/>
|
||||
<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">
|
||||
<div class="flex items-baseline">
|
||||
@ -68,34 +74,32 @@
|
||||
</div>
|
||||
</a>
|
||||
<audio controls preload="none" class="w-full mt-auto">
|
||||
<source
|
||||
src="<?= $episode->audio_file_url ?>"
|
||||
type="<?= $episode->audio_file_mimetype ?>">
|
||||
<source src="<?= $episode->audio_file_url ?>" type="<?= $episode->audio_file_mimetype ?>">
|
||||
Your browser does not support the audio tag.
|
||||
</audio>
|
||||
</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>
|
||||
'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>
|
||||
'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>
|
||||
'heart',
|
||||
'text-xl mr-1 text-gray-400',
|
||||
) . '0' ?></span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?>
|
||||
<legend class="text-lg font-semibold"><?= lang(
|
||||
'Episode.publish_form.publication_date',
|
||||
) ?></legend>
|
||||
<label for="now" class="inline-flex items-center">
|
||||
<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',
|
||||
@ -105,65 +109,70 @@
|
||||
'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 mb-4 radio-toggler">
|
||||
<?= form_radio(
|
||||
[
|
||||
'id' => 'schedule',
|
||||
'name' => 'publication_method',
|
||||
'class' => 'text-pine-700',
|
||||
],
|
||||
'schedule',
|
||||
old('publication_method') &&
|
||||
old('publication_method') === 'schedule',
|
||||
<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'),
|
||||
) ?>
|
||||
<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 mb-4" 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>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= form_fieldset_close() ?>
|
||||
|
||||
<div class="self-end">
|
||||
<?= anchor(
|
||||
route_to('episode-view', $podcast->id, $episode->id),
|
||||
lang('Common.cancel'),
|
||||
['class' => 'font-semibold mr-4'],
|
||||
) ?>
|
||||
<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>
|
||||
|
||||
<?= button(
|
||||
lang('Episode.publish_form.submit'),
|
||||
'',
|
||||
['variant' => 'primary'],
|
||||
['type' => 'submit'],
|
||||
[
|
||||
'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>
|
||||
|
||||
<?= form_close() ?>
|
||||
|
||||
|
@ -1,19 +1,26 @@
|
||||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('Episode.publish') ?>
|
||||
<?= lang('Episode.publish_edit') ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('pageTitle') ?>
|
||||
<?= lang('Episode.publish') ?>
|
||||
<?= lang('Episode.publish_edit') ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<?= anchor(
|
||||
route_to('episode-view', $podcast->id, $episode->id),
|
||||
icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'),
|
||||
['class' => 'inline-flex items-center font-semibold mr-4 text-sm'],
|
||||
) ?>
|
||||
|
||||
<?= form_open(route_to('episode-publish_edit', $podcast->id, $episode->id), [
|
||||
'method' => 'post',
|
||||
'class' => 'flex flex-col max-w-xl items-start',
|
||||
'class' => 'mx-auto flex flex-col max-w-xl items-start',
|
||||
'data-submit' => 'validate-message'
|
||||
]) ?>
|
||||
<?= csrf_field() ?>
|
||||
<?= form_hidden('client_timezone', 'UTC') ?>
|
||||
@ -21,25 +28,26 @@
|
||||
|
||||
|
||||
<label for="message" class="text-lg font-semibold"><?= lang(
|
||||
'Episode.publish_form.status',
|
||||
) . hint_tooltip(lang('Episode.publish_form.status_hint'), 'ml-1') ?></label>
|
||||
'Episode.publish_form.status',
|
||||
) ?></label>
|
||||
<small class="max-w-md mb-2 text-gray-600"><?= lang('Episode.publish_form.status_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"/>
|
||||
<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>
|
||||
->display_name ?></span>
|
||||
<span class="text-sm text-gray-500 truncate">@<?= $podcast
|
||||
->actor->username ?></span>
|
||||
->actor->username ?></span>
|
||||
</p>
|
||||
<time class="text-xs text-gray-500" itemprop="published" datetime="<?= $status->published_at->format(
|
||||
DateTime::ATOM,
|
||||
) ?>" title="<?= $status->published_at ?>"><?= lang(
|
||||
'Common.mediumDate',
|
||||
[$status->published_at],
|
||||
) ?></time>
|
||||
DateTime::ATOM,
|
||||
) ?>" title="<?= $status->published_at ?>"><?= lang(
|
||||
'Common.mediumDate',
|
||||
[$status->published_at],
|
||||
) ?></time>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 mb-2">
|
||||
@ -48,8 +56,8 @@
|
||||
'id' => 'message',
|
||||
'name' => 'message',
|
||||
'class' => 'form-textarea',
|
||||
'required' => 'required',
|
||||
'placeholder' => 'Write your message...',
|
||||
'autofocus' => ''
|
||||
],
|
||||
old('message', $status->message, false),
|
||||
['rows' => 2],
|
||||
@ -57,7 +65,7 @@
|
||||
</div>
|
||||
<div class="flex">
|
||||
<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">
|
||||
<div class="flex items-baseline">
|
||||
@ -71,8 +79,8 @@
|
||||
</div>
|
||||
<div class="text-xs text-gray-600">
|
||||
<time itemprop="published" datetime="<?= $episode->published_at->format(
|
||||
DateTime::ATOM,
|
||||
) ?>" title="<?= $episode->published_at ?>">
|
||||
DateTime::ATOM,
|
||||
) ?>" title="<?= $episode->published_at ?>">
|
||||
<?= lang('Common.mediumDate', [
|
||||
$episode->published_at,
|
||||
]) ?>
|
||||
@ -91,24 +99,24 @@
|
||||
</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>
|
||||
'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>
|
||||
'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>
|
||||
'heart',
|
||||
'text-xl mr-1 text-gray-400',
|
||||
) . '0' ?></span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<?= form_fieldset('', ['class' => 'flex flex-col mb-4']) ?>
|
||||
<legend class="text-lg font-semibold"><?= lang(
|
||||
'Episode.publish_form.publication_date',
|
||||
) ?></legend>
|
||||
'Episode.publish_form.publication_date',
|
||||
) ?></legend>
|
||||
<label for="now" class="inline-flex items-center">
|
||||
<?= form_radio(
|
||||
[
|
||||
@ -120,10 +128,10 @@
|
||||
old('publication_method') && old('publish') === 'now',
|
||||
) ?>
|
||||
<span class="ml-2"><?= lang(
|
||||
'Episode.publish_form.publication_method.now',
|
||||
) ?></span>
|
||||
'Episode.publish_form.publication_method.now',
|
||||
) ?></span>
|
||||
</label>
|
||||
<div class="inline-flex flex-wrap items-center mb-4 radio-toggler">
|
||||
<div class="inline-flex flex-wrap items-center radio-toggler">
|
||||
<?= form_radio(
|
||||
[
|
||||
'id' => 'schedule',
|
||||
@ -136,8 +144,8 @@
|
||||
: true,
|
||||
) ?>
|
||||
<label for="schedule" class="ml-2"><?= lang(
|
||||
'Episode.publish_form.publication_method.schedule',
|
||||
) ?></label>
|
||||
'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'),
|
||||
@ -145,7 +153,7 @@
|
||||
[],
|
||||
lang('Episode.publish_form.scheduled_publication_date_hint'),
|
||||
) ?>
|
||||
<div class="flex mb-4" data-picker="datetime">
|
||||
<div class="flex" data-picker="datetime">
|
||||
<?= form_input([
|
||||
'id' => 'scheduled_publication_date',
|
||||
'name' => 'scheduled_publication_date',
|
||||
@ -157,30 +165,46 @@
|
||||
'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.scheduled_publication_date_clear',
|
||||
) ?>" title="<?= lang(
|
||||
'Episode.publish_form.scheduled_publication_date_clear',
|
||||
) ?>" data-clear=""><?= icon('close') ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= form_fieldset_close() ?>
|
||||
|
||||
<div class="self-end">
|
||||
<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>
|
||||
|
||||
<div class="flex items-center justify-between w-full mt-4">
|
||||
<?= anchor(
|
||||
route_to('episode-view', $podcast->id, $episode->id),
|
||||
lang('Common.cancel'),
|
||||
['class' => 'font-semibold mr-4'],
|
||||
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'],
|
||||
[
|
||||
'type' => 'submit',
|
||||
'data-btn-text-warning' => lang('Episode.publish_form.message_warning_submit'),
|
||||
'data-btn-text' => lang('Episode.publish_form.submit_edit')
|
||||
],
|
||||
) ?>
|
||||
</div>
|
||||
|
||||
<?= form_close() ?>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
<?= $this->endSection() ?>
|
Loading…
x
Reference in New Issue
Block a user