Loading app/Database/Migrations/2020-05-30-101500_add_podcasts.php +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ class AddPodcasts extends Migration 'type' => 'INT', 'unsigned' => true, ], 'published_at' => [ 'type' => 'DATETIME', 'null' => true, ], 'created_at' => [ 'type' => 'DATETIME', ], Loading app/Database/Seeds/AuthSeeder.php +1 −1 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ class AuthSeeder extends Seeder [ 'name' => 'manage_publications', 'description' => 'Publish / unpublish episodes & posts of a podcast', 'Publish a podcast and publish / unpublish its episodes & posts', 'has_permission' => ['podcast_admin'], ], [ Loading app/Entities/Episode.php +2 −0 Original line number Diff line number Diff line Loading @@ -541,6 +541,8 @@ class Episode extends Entity if ($this->publication_status === null) { if ($this->published_at === null) { $this->publication_status = 'not_published'; } elseif ($this->getPodcast()->publication_status !== 'published') { $this->publication_status = 'with_podcast'; } elseif ($this->published_at->isBefore(Time::now())) { $this->publication_status = 'published'; } else { Loading app/Entities/Podcast.php +24 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,8 @@ use RuntimeException; * @property string|null $partner_image_url * @property int $created_by * @property int $updated_by * @property string $publication_status; * @property Time|null $published_at; * @property Time $created_at; * @property Time $updated_at; * Loading Loading @@ -147,6 +149,13 @@ class Podcast extends Entity protected string $custom_rss_string; protected ?string $publication_status = null; /** * @var string[] */ protected $dates = ['published_at', 'created_at', 'updated_at']; /** * @var array<string, string> */ Loading Loading @@ -459,6 +468,21 @@ class Podcast extends Entity return $this->description; } public function getPublicationStatus(): string { if ($this->publication_status === null) { if ($this->published_at === null) { $this->publication_status = 'not_published'; } elseif ($this->published_at->isBefore(Time::now())) { $this->publication_status = 'published'; } else { $this->publication_status = 'scheduled'; } } return $this->publication_status; } /** * Returns the podcast's podcasting platform links * Loading app/Helpers/components_helper.php +57 −2 Original line number Diff line number Diff line Loading @@ -116,18 +116,27 @@ if (! function_exists('publication_pill')) { $class = match ($publicationStatus) { 'published' => 'text-pine-500 border-pine-500 bg-pine-50', 'scheduled' => 'text-red-600 border-red-600 bg-red-50', 'with_podcast' => 'text-blue-600 border-blue-600 bg-blue-50', 'not_published' => 'text-gray-600 border-gray-600 bg-gray-50', default => 'text-gray-600 border-gray-600 bg-gray-50', }; $title = match ($publicationStatus) { 'published', 'scheduled' => (string) $publicationDate, 'with_podcast' => lang('Episode.with_podcast_hint'), 'not_published' => '', default => '', }; $label = lang('Episode.publication_status.' . $publicationStatus); return '<span ' . ($publicationDate === null ? '' : 'title="' . $publicationDate . '"') . ' class="px-1 font-semibold border rounded ' . return '<span ' . ($title === '' ? '' : 'title="' . $title . '"') . ' class="flex items-center px-1 font-semibold border rounded w-max ' . $class . ' ' . $customClass . '">' . $label . ($publicationStatus === 'with_podcast' ? '<Icon glyph="warning" class="flex-shrink-0 ml-1 text-lg" />' : '') . '</span>'; } } Loading @@ -136,7 +145,7 @@ if (! function_exists('publication_pill')) { if (! function_exists('publication_button')) { /** * Publication button component * Publication button component for episodes * * Displays the appropriate publication button depending on the publication post. */ Loading @@ -149,6 +158,7 @@ if (! function_exists('publication_button')) { $variant = 'primary'; $iconLeft = 'upload-cloud'; break; case 'with_podcast': case 'scheduled': $label = lang('Episode.publish_edit'); $route = route_to('episode-publish_edit', $podcastId, $episodeId); Loading Loading @@ -177,6 +187,51 @@ if (! function_exists('publication_button')) { // ------------------------------------------------------------------------ if (! function_exists('publication_status_banner')) { /** * Publication status banner component for podcasts * * Displays the appropriate banner depending on the podcast's publication status. */ function publication_status_banner(?Time $publicationDate, int $podcastId, string $publicationStatus): string { switch ($publicationStatus) { case 'not_published': $bannerDisclaimer = lang('Podcast.publication_status_banner.draft_mode'); $bannerText = lang('Podcast.publication_status_banner.not_published'); $linkRoute = route_to('podcast-publish', $podcastId); $linkLabel = lang('Podcast.publish'); break; case 'scheduled': $bannerDisclaimer = lang('Podcast.publication_status_banner.draft_mode'); $bannerText = lang('Podcast.publication_status_banner.scheduled', [ 'publication_date' => local_time($publicationDate), ], null, false); $linkRoute = route_to('podcast-publish_edit', $podcastId); $linkLabel = lang('Podcast.publish_edit'); break; default: $bannerDisclaimer = ''; $bannerText = ''; $linkRoute = ''; $linkLabel = ''; break; } return <<<CODE_SAMPLE <div class="flex items-center px-12 py-1 border-b bg-stripes-gray border-subtle" role="alert"> <p class="text-gray-900"> <span class="text-xs font-semibold tracking-wide uppercase">{$bannerDisclaimer}</span> <span class="ml-3 text-sm">{$bannerText}</span> </p> <a href="{$linkRoute}" class="ml-1 text-sm font-semibold underline shadow-xs text-accent-base hover:text-accent-hover hover:no-underline">{$linkLabel}</a> </div> CODE_SAMPLE; } } // ------------------------------------------------------------------------ if (! function_exists('episode_numbering')) { /** * Returns relevant translated episode numbering. Loading Loading
app/Database/Migrations/2020-05-30-101500_add_podcasts.php +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ class AddPodcasts extends Migration 'type' => 'INT', 'unsigned' => true, ], 'published_at' => [ 'type' => 'DATETIME', 'null' => true, ], 'created_at' => [ 'type' => 'DATETIME', ], Loading
app/Database/Seeds/AuthSeeder.php +1 −1 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ class AuthSeeder extends Seeder [ 'name' => 'manage_publications', 'description' => 'Publish / unpublish episodes & posts of a podcast', 'Publish a podcast and publish / unpublish its episodes & posts', 'has_permission' => ['podcast_admin'], ], [ Loading
app/Entities/Episode.php +2 −0 Original line number Diff line number Diff line Loading @@ -541,6 +541,8 @@ class Episode extends Entity if ($this->publication_status === null) { if ($this->published_at === null) { $this->publication_status = 'not_published'; } elseif ($this->getPodcast()->publication_status !== 'published') { $this->publication_status = 'with_podcast'; } elseif ($this->published_at->isBefore(Time::now())) { $this->publication_status = 'published'; } else { Loading
app/Entities/Podcast.php +24 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,8 @@ use RuntimeException; * @property string|null $partner_image_url * @property int $created_by * @property int $updated_by * @property string $publication_status; * @property Time|null $published_at; * @property Time $created_at; * @property Time $updated_at; * Loading Loading @@ -147,6 +149,13 @@ class Podcast extends Entity protected string $custom_rss_string; protected ?string $publication_status = null; /** * @var string[] */ protected $dates = ['published_at', 'created_at', 'updated_at']; /** * @var array<string, string> */ Loading Loading @@ -459,6 +468,21 @@ class Podcast extends Entity return $this->description; } public function getPublicationStatus(): string { if ($this->publication_status === null) { if ($this->published_at === null) { $this->publication_status = 'not_published'; } elseif ($this->published_at->isBefore(Time::now())) { $this->publication_status = 'published'; } else { $this->publication_status = 'scheduled'; } } return $this->publication_status; } /** * Returns the podcast's podcasting platform links * Loading
app/Helpers/components_helper.php +57 −2 Original line number Diff line number Diff line Loading @@ -116,18 +116,27 @@ if (! function_exists('publication_pill')) { $class = match ($publicationStatus) { 'published' => 'text-pine-500 border-pine-500 bg-pine-50', 'scheduled' => 'text-red-600 border-red-600 bg-red-50', 'with_podcast' => 'text-blue-600 border-blue-600 bg-blue-50', 'not_published' => 'text-gray-600 border-gray-600 bg-gray-50', default => 'text-gray-600 border-gray-600 bg-gray-50', }; $title = match ($publicationStatus) { 'published', 'scheduled' => (string) $publicationDate, 'with_podcast' => lang('Episode.with_podcast_hint'), 'not_published' => '', default => '', }; $label = lang('Episode.publication_status.' . $publicationStatus); return '<span ' . ($publicationDate === null ? '' : 'title="' . $publicationDate . '"') . ' class="px-1 font-semibold border rounded ' . return '<span ' . ($title === '' ? '' : 'title="' . $title . '"') . ' class="flex items-center px-1 font-semibold border rounded w-max ' . $class . ' ' . $customClass . '">' . $label . ($publicationStatus === 'with_podcast' ? '<Icon glyph="warning" class="flex-shrink-0 ml-1 text-lg" />' : '') . '</span>'; } } Loading @@ -136,7 +145,7 @@ if (! function_exists('publication_pill')) { if (! function_exists('publication_button')) { /** * Publication button component * Publication button component for episodes * * Displays the appropriate publication button depending on the publication post. */ Loading @@ -149,6 +158,7 @@ if (! function_exists('publication_button')) { $variant = 'primary'; $iconLeft = 'upload-cloud'; break; case 'with_podcast': case 'scheduled': $label = lang('Episode.publish_edit'); $route = route_to('episode-publish_edit', $podcastId, $episodeId); Loading Loading @@ -177,6 +187,51 @@ if (! function_exists('publication_button')) { // ------------------------------------------------------------------------ if (! function_exists('publication_status_banner')) { /** * Publication status banner component for podcasts * * Displays the appropriate banner depending on the podcast's publication status. */ function publication_status_banner(?Time $publicationDate, int $podcastId, string $publicationStatus): string { switch ($publicationStatus) { case 'not_published': $bannerDisclaimer = lang('Podcast.publication_status_banner.draft_mode'); $bannerText = lang('Podcast.publication_status_banner.not_published'); $linkRoute = route_to('podcast-publish', $podcastId); $linkLabel = lang('Podcast.publish'); break; case 'scheduled': $bannerDisclaimer = lang('Podcast.publication_status_banner.draft_mode'); $bannerText = lang('Podcast.publication_status_banner.scheduled', [ 'publication_date' => local_time($publicationDate), ], null, false); $linkRoute = route_to('podcast-publish_edit', $podcastId); $linkLabel = lang('Podcast.publish_edit'); break; default: $bannerDisclaimer = ''; $bannerText = ''; $linkRoute = ''; $linkLabel = ''; break; } return <<<CODE_SAMPLE <div class="flex items-center px-12 py-1 border-b bg-stripes-gray border-subtle" role="alert"> <p class="text-gray-900"> <span class="text-xs font-semibold tracking-wide uppercase">{$bannerDisclaimer}</span> <span class="ml-3 text-sm">{$bannerText}</span> </p> <a href="{$linkRoute}" class="ml-1 text-sm font-semibold underline shadow-xs text-accent-base hover:text-accent-hover hover:no-underline">{$linkLabel}</a> </div> CODE_SAMPLE; } } // ------------------------------------------------------------------------ if (! function_exists('episode_numbering')) { /** * Returns relevant translated episode numbering. Loading