mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
fix(episodes): add publication status + set publication date to null when none has been set
- replace $is_published attribute by $publication_status to better handle episode's publication state - update publication date datepicker to include a clear button fixes #70
This commit is contained in:
parent
5dc0f19656
commit
d882981b3a
@ -117,6 +117,7 @@ class Episode extends BaseController
|
||||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
$publicationDate = $this->request->getPost('publication_date');
|
||||
$newEpisode = new \App\Entities\Episode([
|
||||
'podcast_id' => $this->podcast->id,
|
||||
'title' => $this->request->getPost('title'),
|
||||
@ -141,11 +142,13 @@ class Episode extends BaseController
|
||||
'is_blocked' => $this->request->getPost('block') == 'yes',
|
||||
'created_by' => user(),
|
||||
'updated_by' => user(),
|
||||
'published_at' => Time::createFromFormat(
|
||||
'Y-m-d H:i',
|
||||
$this->request->getPost('publication_date'),
|
||||
$this->request->getPost('client_timezone')
|
||||
)->setTimezone('UTC'),
|
||||
'published_at' => $publicationDate
|
||||
? Time::createFromFormat(
|
||||
'Y-m-d H:i',
|
||||
$publicationDate,
|
||||
$this->request->getPost('client_timezone')
|
||||
)->setTimezone('UTC')
|
||||
: null,
|
||||
]);
|
||||
|
||||
$episodeModel = new EpisodeModel();
|
||||
@ -231,11 +234,16 @@ class Episode extends BaseController
|
||||
: null;
|
||||
$this->episode->type = $this->request->getPost('type');
|
||||
$this->episode->is_blocked = $this->request->getPost('block') == 'yes';
|
||||
$this->episode->published_at = Time::createFromFormat(
|
||||
'Y-m-d H:i',
|
||||
$this->request->getPost('publication_date'),
|
||||
$this->request->getPost('client_timezone')
|
||||
)->setTimezone('UTC');
|
||||
|
||||
$publicationDate = $this->request->getPost('publication_date');
|
||||
$this->episode->published_at = $publicationDate
|
||||
? Time::createFromFormat(
|
||||
'Y-m-d H:i',
|
||||
$publicationDate,
|
||||
$this->request->getPost('client_timezone')
|
||||
)->setTimezone('UTC')
|
||||
: null;
|
||||
|
||||
$this->episode->updated_by = user();
|
||||
|
||||
$enclosure = $this->request->getFile('enclosure');
|
||||
|
@ -89,9 +89,9 @@ class Episode extends Entity
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @var string
|
||||
*/
|
||||
protected $is_published;
|
||||
protected $publication_status;
|
||||
|
||||
protected $dates = [
|
||||
'published_at',
|
||||
@ -462,16 +462,21 @@ class Episode extends Entity
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsPublished()
|
||||
public function getPublicationStatus()
|
||||
{
|
||||
if ($this->is_published) {
|
||||
return $this->is_published;
|
||||
if ($this->publication_status) {
|
||||
return $this->publication_status;
|
||||
}
|
||||
|
||||
if (!$this->published_at) {
|
||||
return 'not_published';
|
||||
}
|
||||
|
||||
helper('date');
|
||||
if ($this->published_at->isBefore(Time::now())) {
|
||||
return 'published';
|
||||
}
|
||||
|
||||
$this->is_published = $this->published_at->isBefore(Time::now());
|
||||
|
||||
return $this->is_published;
|
||||
return 'scheduled';
|
||||
}
|
||||
}
|
||||
|
@ -271,27 +271,30 @@ if (!function_exists('publication_pill')) {
|
||||
*/
|
||||
function publication_pill(
|
||||
$publicationDate,
|
||||
$isPublished,
|
||||
$publicationStatus,
|
||||
$customClass = ''
|
||||
): string {
|
||||
$class = $isPublished
|
||||
? 'text-green-500 border-green-500'
|
||||
: 'text-orange-600 border-orange-600';
|
||||
$class =
|
||||
$publicationStatus === 'published'
|
||||
? 'text-green-500 border-green-500'
|
||||
: 'text-orange-600 border-orange-600';
|
||||
|
||||
$label = lang(
|
||||
$isPublished ? 'Episode.published' : 'Episode.scheduled',
|
||||
[
|
||||
'<time
|
||||
pubdate
|
||||
datetime="' .
|
||||
$transParam = [];
|
||||
if ($publicationDate) {
|
||||
$transParam = [
|
||||
'<time pubdate datetime="' .
|
||||
$publicationDate->format(DateTime::ATOM) .
|
||||
'"
|
||||
title="' .
|
||||
'" title="' .
|
||||
$publicationDate .
|
||||
'">' .
|
||||
lang('Common.mediumDate', [$publicationDate]) .
|
||||
'</time>',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
$label = lang(
|
||||
'Episode.publication_status.' . $publicationStatus,
|
||||
$transParam
|
||||
);
|
||||
|
||||
return '<span class="px-1 border ' .
|
||||
|
@ -23,8 +23,11 @@ return [
|
||||
'delete' => 'Delete',
|
||||
'go_to_page' => 'Go to page',
|
||||
'create' => 'Add an episode',
|
||||
'published' => 'Published on {0}',
|
||||
'scheduled' => 'Scheduled for {0}',
|
||||
'publication_status' => [
|
||||
'published' => 'Published on {0}',
|
||||
'scheduled' => 'Scheduled for {0}',
|
||||
'not_published' => 'Not published',
|
||||
],
|
||||
'form' => [
|
||||
'enclosure' => 'Audio file',
|
||||
'enclosure_hint' => 'Choose an .mp3 or .m4a audio file.',
|
||||
@ -58,6 +61,7 @@ return [
|
||||
'publication_section_title' => 'Publication info',
|
||||
'publication_section_subtitle' => '',
|
||||
'publication_date' => 'Publication date',
|
||||
'publication_date_clear' => 'Clear publication date',
|
||||
'publication_date_hint' =>
|
||||
'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm',
|
||||
'parental_advisory' => [
|
||||
|
@ -23,8 +23,11 @@ return [
|
||||
'delete' => 'Supprimer',
|
||||
'go_to_page' => 'Voir',
|
||||
'create' => 'Ajouter un épisode',
|
||||
'published' => 'Publié le {0}',
|
||||
'scheduled' => 'Planifié pour le {0}',
|
||||
'publication_status' => [
|
||||
'published' => 'Publié le {0}',
|
||||
'scheduled' => 'Planifié pour le {0}',
|
||||
'not_published' => 'Non publié',
|
||||
],
|
||||
'form' => [
|
||||
'enclosure' => 'Fichier audio',
|
||||
'enclosure_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
|
||||
@ -58,6 +61,7 @@ return [
|
||||
'publication_section_title' => 'Information de publication',
|
||||
'publication_section_subtitle' => '',
|
||||
'publication_date' => 'Date de publication',
|
||||
'publication_date_clear' => 'Effacer la date de publication',
|
||||
'publication_date_hint' =>
|
||||
'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',
|
||||
'parental_advisory' => [
|
||||
|
6
app/Views/_assets/icons/close.svg
Normal file
6
app/Views/_assets/icons/close.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g>
|
||||
<path fill="none" d="M0 0h24v24H0z"/>
|
||||
<path d="M12 10.586l4.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"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 280 B |
@ -11,30 +11,36 @@ const isBrowserLocale24h = () =>
|
||||
.match(/AM/);
|
||||
|
||||
const DateTimePicker = (): void => {
|
||||
const dateTimeContainers: NodeListOf<HTMLInputElement> = document.querySelectorAll(
|
||||
"input[data-picker='datetime']"
|
||||
const dateTimeContainers: NodeListOf<HTMLDivElement> = document.querySelectorAll(
|
||||
"div[data-picker='datetime']"
|
||||
);
|
||||
|
||||
for (let i = 0; i < dateTimeContainers.length; i++) {
|
||||
const dateTimeContainer = dateTimeContainers[i];
|
||||
|
||||
const flatpickrInstance = flatpickr(dateTimeContainer, {
|
||||
enableTime: true,
|
||||
time_24hr: isBrowserLocale24h(),
|
||||
});
|
||||
|
||||
// convert container UTC date value to user timezone
|
||||
const dateTime = new Date(dateTimeContainer.value);
|
||||
const dateUTC = Date.UTC(
|
||||
dateTime.getFullYear(),
|
||||
dateTime.getMonth(),
|
||||
dateTime.getDate(),
|
||||
dateTime.getHours(),
|
||||
dateTime.getMinutes()
|
||||
const dateTimeInput: HTMLInputElement | null = dateTimeContainer.querySelector(
|
||||
"input[data-input]"
|
||||
);
|
||||
|
||||
// set converted date as field value
|
||||
flatpickrInstance.setDate(new Date(dateUTC));
|
||||
if (dateTimeInput) {
|
||||
const flatpickrInstance = flatpickr(dateTimeContainer, {
|
||||
enableTime: true,
|
||||
time_24hr: isBrowserLocale24h(),
|
||||
wrap: true,
|
||||
});
|
||||
|
||||
// convert container UTC date value to user timezone
|
||||
const dateTime = new Date(dateTimeInput.value);
|
||||
const dateUTC = Date.UTC(
|
||||
dateTime.getFullYear(),
|
||||
dateTime.getMonth(),
|
||||
dateTime.getDate(),
|
||||
dateTime.getHours(),
|
||||
dateTime.getMinutes()
|
||||
);
|
||||
|
||||
// set converted date as field value
|
||||
flatpickrInstance.setDate(new Date(dateUTC));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,8 +3,6 @@ const Time = (): void => {
|
||||
"time"
|
||||
);
|
||||
|
||||
console.log(timeElements);
|
||||
|
||||
for (let i = 0; i < timeElements.length; i++) {
|
||||
const timeElement = timeElements[i];
|
||||
|
||||
|
@ -199,13 +199,20 @@
|
||||
[],
|
||||
lang('Episode.form.publication_date_hint')
|
||||
) ?>
|
||||
<?= form_input([
|
||||
'id' => 'publication_date',
|
||||
'name' => 'publication_date',
|
||||
'class' => 'form-input mb-4',
|
||||
'value' => old('publication_date', date('Y-m-d H:i')),
|
||||
'data-picker' => 'datetime',
|
||||
]) ?>
|
||||
<div class="flex mb-4" data-picker="datetime">
|
||||
<?= form_input([
|
||||
'id' => 'publication_date',
|
||||
'name' => 'publication_date',
|
||||
'class' => 'form-input rounded-r-none flex-1',
|
||||
'value' => old('publication_date', date('Y-m-d H:i')),
|
||||
'data-input' => '',
|
||||
]) ?>
|
||||
<button
|
||||
class="p-3 bg-green-100 border border-l-0 focus:outline-none rounded-r-md hover:bg-green-200 focus:shadow-outline"
|
||||
type="button"
|
||||
title="<?= lang('Episode.form.publication_date_clear') ?>"
|
||||
data-clear=""><?= icon('close') ?></button>
|
||||
</div>
|
||||
|
||||
<?= form_fieldset('', ['class' => 'flex mb-6 gap-1']) ?>
|
||||
<legend>
|
||||
|
@ -202,18 +202,25 @@
|
||||
[],
|
||||
lang('Episode.form.publication_date_hint')
|
||||
) ?>
|
||||
<?= form_input([
|
||||
'id' => 'publication_date',
|
||||
'name' => 'publication_date',
|
||||
'class' => 'form-input mb-4',
|
||||
'value' => old(
|
||||
'publication_date',
|
||||
$episode->published_at
|
||||
? $episode->published_at->format('Y-m-d H:i')
|
||||
: ''
|
||||
),
|
||||
'data-picker' => 'datetime',
|
||||
]) ?>
|
||||
<div class="flex mb-4" data-picker="datetime">
|
||||
<?= form_input([
|
||||
'id' => 'publication_date',
|
||||
'name' => 'publication_date',
|
||||
'class' => 'form-input rounded-r-none flex-1',
|
||||
'value' => old(
|
||||
'publication_date',
|
||||
$episode->published_at
|
||||
? $episode->published_at->format('Y-m-d H:i')
|
||||
: ''
|
||||
),
|
||||
'data-input' => '',
|
||||
]) ?>
|
||||
<button
|
||||
class="p-3 bg-green-100 border border-l-0 focus:outline-none rounded-r-md hover:bg-green-200 focus:shadow-outline"
|
||||
type="button"
|
||||
title="<?= lang('Episode.form.publication_date_clear') ?>"
|
||||
data-clear=""><?= icon('close') ?></button>
|
||||
</div>
|
||||
|
||||
<?= form_fieldset('', ['class' => 'mb-6']) ?>
|
||||
<legend>
|
||||
|
@ -65,9 +65,7 @@
|
||||
'soundbites-edit',
|
||||
$podcast->id,
|
||||
$episode->id
|
||||
) ?>"><?= lang(
|
||||
'Episode.soundbites'
|
||||
) ?></a>
|
||||
) ?>"><?= lang('Episode.soundbites') ?></a>
|
||||
<a class="px-4 py-1 hover:bg-gray-100" href="<?= route_to(
|
||||
'episode',
|
||||
$podcast->name,
|
||||
@ -84,7 +82,7 @@
|
||||
<div class="mb-2 text-xs">
|
||||
<?= publication_pill(
|
||||
$episode->published_at,
|
||||
$episode->is_published
|
||||
$episode->publication_status
|
||||
) ?>
|
||||
<span class="mx-1">•</span>
|
||||
<time datetime="PT<?= $episode->enclosure_duration ?>S">
|
||||
|
@ -8,7 +8,7 @@
|
||||
<?= $episode->title .
|
||||
publication_pill(
|
||||
$episode->published_at,
|
||||
$episode->is_published,
|
||||
$episode->publication_status,
|
||||
'text-sm ml-2 align-middle'
|
||||
) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
@ -33,17 +33,19 @@
|
||||
'font-bold text-gray-600',
|
||||
true
|
||||
) ?>
|
||||
<span class="mx-1">•</span>
|
||||
<time
|
||||
pubdate
|
||||
datetime="<?= $episode->published_at->format(
|
||||
DateTime::ATOM
|
||||
) ?>"
|
||||
title="<?= $episode->published_at ?>">
|
||||
<?= lang('Common.mediumDate', [
|
||||
$episode->published_at,
|
||||
]) ?>
|
||||
</time>
|
||||
<?php if ($episode->published_at): ?>
|
||||
<span class="mx-1">•</span>
|
||||
<time
|
||||
pubdate
|
||||
datetime="<?= $episode->published_at->format(
|
||||
DateTime::ATOM
|
||||
) ?>"
|
||||
title="<?= $episode->published_at ?>">
|
||||
<?= lang('Common.mediumDate', [
|
||||
$episode->published_at,
|
||||
]) ?>
|
||||
</time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative" data-toggle="dropdown">
|
||||
|
12
package-lock.json
generated
12
package-lock.json
generated
@ -3944,9 +3944,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001077",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001077.tgz",
|
||||
"integrity": "sha512-AEzsGvjBJL0lby/87W96PyEvwN0GsYvk5LHsglLg9tW37K4BqvAvoSCdWIE13OZQ8afupqZ73+oL/1LkedN8hA==",
|
||||
"version": "1.0.30001165",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz",
|
||||
"integrity": "sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA==",
|
||||
"dev": true
|
||||
},
|
||||
"cardinal": {
|
||||
@ -16679,12 +16679,6 @@
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001142",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001142.tgz",
|
||||
"integrity": "sha512-pDPpn9ankEpBFZXyCv2I4lh1v/ju+bqb78QfKf+w9XgDAFWBwSYPswXqprRdrgQWK0wQnpIbfwRjNHO1HWqvoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
|
Loading…
x
Reference in New Issue
Block a user