From d8e1d4031d86de9a3889b74ae2a6d9c90af8a1da Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Wed, 21 Jun 2023 16:17:11 +0000 Subject: [PATCH] feat(import): run podcast imports' processes asynchronously using tasks - use codeigniter4/tasks project to handle cron tasks - use yassinedoghri/podcast-feed project to parse feeds for imports --- app/Config/Autoload.php | 19 +- app/Config/Tasks.php | 55 ++ app/Controllers/WebmanifestController.php | 4 +- app/Entities/Clip/BaseClip.php | 6 +- app/Entities/Episode.php | 24 +- app/Entities/Person.php | 6 +- app/Entities/Podcast.php | 13 +- app/Helpers/components_helper.php | 4 +- app/Helpers/misc_helper.php | 16 - app/Models/EpisodeModel.php | 30 +- app/Models/PersonModel.php | 6 +- app/Models/PlatformModel.php | 12 - app/Models/PodcastModel.php | 11 +- app/Resources/icons/error-warning.svg | 3 + app/Resources/styles/choices.css | 5 +- app/Resources/styles/custom.css | 10 + app/Views/Components/Alert.php | 12 +- app/Views/Components/Forms/Checkbox.php | 4 +- app/Views/Components/Forms/FormComponent.php | 4 + app/Views/Components/Forms/Input.php | 6 - app/Views/Components/Forms/Section.php | 4 +- app/Views/Components/Forms/Select.php | 3 + composer.json | 12 +- composer.lock | 129 +++- crontab | 4 +- docker/production/common/crontab.txt | 4 +- docs/src/getting-started/install.md | 28 +- modules/Admin/Config/Routes.php | 14 +- modules/Admin/Controllers/BaseController.php | 8 + .../Admin/Controllers/DashboardController.php | 4 +- .../Admin/Controllers/EpisodeController.php | 28 +- .../Admin/Controllers/PersonController.php | 7 +- .../Admin/Controllers/PodcastController.php | 7 +- .../Controllers/PodcastImportController.php | 701 ------------------ .../Admin/Controllers/SettingsController.php | 3 +- modules/Admin/Language/en/Breadcrumb.php | 2 +- modules/Admin/Language/en/Navigation.php | 3 +- modules/Admin/Language/en/Podcast.php | 6 +- .../Admin/Language/en/PodcastNavigation.php | 1 + modules/Admin/Language/uk/PodcastImport.php | 37 - .../Rest/V1/Controllers/EpisodeController.php | 4 +- .../Broadcast.php} | 30 +- modules/Media/Entities/Audio.php | 9 +- .../Commands/Generate.php} | 28 +- .../MediaClipper/Config/MediaClipper.php | 16 +- .../MediaClipper/Resources}/castopod-logo.png | Bin .../Resources}/fonts/Inter-Regular.otf | Bin .../Resources}/fonts/Inter-SemiBold.otf | Bin .../Resources}/fonts/NotoSansMono-Regular.ttf | Bin .../Resources}/fonts/Rubik-Bold.ttf | Bin .../MediaClipper/Resources}/quotes.png | Bin .../Resources}/soundwaves-mask-landscape.png | Bin .../Resources}/soundwaves-mask-portrait.png | Bin .../Resources}/soundwaves-mask-squared.png | Bin .../MediaClipper/VideoClipper.php | 2 +- .../PodcastImport/Commands/PodcastImport.php | 541 ++++++++++++++ modules/PodcastImport/Config/Routes.php | 47 ++ .../Controllers/PodcastImportController.php | 181 +++++ .../Entities/PodcastImportTask.php | 242 ++++++ modules/PodcastImport/Entities/TaskStatus.php | 14 + .../Helpers/podcast_import_helper.php | 55 ++ .../Language/ar/PodcastImport.php | 0 .../Language/br/PodcastImport.php | 0 .../Language/ca/PodcastImport.php | 0 .../Language/da/PodcastImport.php | 0 .../Language/de/PodcastImport.php | 0 .../Language/el/PodcastImport.php | 0 .../Language/en/PodcastImport.php | 60 ++ .../Language/es/PodcastImport.php | 0 .../Language/fa}/PodcastImport.php | 0 .../Language/fr/PodcastImport.php | 0 .../Language/fr2}/PodcastImport.php | 0 .../Language/fr_CA}/PodcastImport.php | 0 .../Language/fr_trad}/PodcastImport.php | 0 .../Language/gd}/PodcastImport.php | 0 .../Language/gl/PodcastImport.php | 0 .../Language/id}/PodcastImport.php | 0 .../Language/it}/PodcastImport.php | 0 .../Language/ko}/PodcastImport.php | 0 .../Language/nl}/PodcastImport.php | 0 .../Language/nn-NO/PodcastImport.php | 0 .../Language/oc}/PodcastImport.php | 0 .../Language/pl/PodcastImport.php | 0 .../Language/pt-BR/PodcastImport.php | 0 .../Language/pt}/PodcastImport.php | 0 .../Language/ro}/PodcastImport.php | 0 .../Language/ru}/PodcastImport.php | 0 .../Language/sk}/PodcastImport.php | 0 .../Language/sr_Latn}/PodcastImport.php | 0 .../Language/sv/PodcastImport.php | 0 .../Language/uk}/PodcastImport.php | 0 .../Language/zh-Hans/PodcastImport.php | 0 .../Publish.php} | 25 +- modules/WebSub/Config/Routes.php | 21 - phpstan.neon | 12 +- themes/cp_admin/_layout.php | 17 +- themes/cp_admin/_sidebar.php | 2 +- themes/cp_admin/episode/list.php | 2 +- themes/cp_admin/import/_queue_table.php | 131 ++++ themes/cp_admin/import/add_to_queue.php | 62 ++ themes/cp_admin/import/podcast_queue.php | 20 + themes/cp_admin/import/queue.php | 23 + themes/cp_admin/podcast/_sidebar.php | 2 +- themes/cp_admin/podcast/edit.php | 2 +- themes/cp_admin/podcast/import.php | 99 --- themes/cp_admin/podcast/list.php | 2 +- 106 files changed, 1806 insertions(+), 1098 deletions(-) create mode 100644 app/Config/Tasks.php create mode 100644 app/Resources/icons/error-warning.svg delete mode 100644 modules/Admin/Controllers/PodcastImportController.php delete mode 100644 modules/Admin/Language/uk/PodcastImport.php rename modules/Fediverse/{Controllers/SchedulerController.php => Commands/Broadcast.php} (70%) rename modules/{Admin/Controllers/SchedulerController.php => MediaClipper/Commands/Generate.php} (87%) rename {app/Libraries => modules}/MediaClipper/Config/MediaClipper.php (94%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/castopod-logo.png (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/fonts/Inter-Regular.otf (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/fonts/Inter-SemiBold.otf (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/fonts/NotoSansMono-Regular.ttf (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/fonts/Rubik-Bold.ttf (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/quotes.png (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/soundwaves-mask-landscape.png (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/soundwaves-mask-portrait.png (100%) rename {app/Libraries/MediaClipper => modules/MediaClipper/Resources}/soundwaves-mask-squared.png (100%) rename {app/Libraries => modules}/MediaClipper/VideoClipper.php (99%) create mode 100644 modules/PodcastImport/Commands/PodcastImport.php create mode 100644 modules/PodcastImport/Config/Routes.php create mode 100644 modules/PodcastImport/Controllers/PodcastImportController.php create mode 100644 modules/PodcastImport/Entities/PodcastImportTask.php create mode 100644 modules/PodcastImport/Entities/TaskStatus.php create mode 100644 modules/PodcastImport/Helpers/podcast_import_helper.php rename modules/{Admin => PodcastImport}/Language/ar/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/br/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/ca/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/da/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/de/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/el/PodcastImport.php (100%) create mode 100644 modules/PodcastImport/Language/en/PodcastImport.php rename modules/{Admin => PodcastImport}/Language/es/PodcastImport.php (100%) rename modules/{Admin/Language/en => PodcastImport/Language/fa}/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/fr/PodcastImport.php (100%) rename modules/{Admin/Language/fa => PodcastImport/Language/fr2}/PodcastImport.php (100%) rename modules/{Admin/Language/fr2 => PodcastImport/Language/fr_CA}/PodcastImport.php (100%) rename modules/{Admin/Language/fr_CA => PodcastImport/Language/fr_trad}/PodcastImport.php (100%) rename modules/{Admin/Language/fr_trad => PodcastImport/Language/gd}/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/gl/PodcastImport.php (100%) rename modules/{Admin/Language/gd => PodcastImport/Language/id}/PodcastImport.php (100%) rename modules/{Admin/Language/id => PodcastImport/Language/it}/PodcastImport.php (100%) rename modules/{Admin/Language/it => PodcastImport/Language/ko}/PodcastImport.php (100%) rename modules/{Admin/Language/ko => PodcastImport/Language/nl}/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/nn-NO/PodcastImport.php (100%) rename modules/{Admin/Language/nl => PodcastImport/Language/oc}/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/pl/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/pt-BR/PodcastImport.php (100%) rename modules/{Admin/Language/oc => PodcastImport/Language/pt}/PodcastImport.php (100%) rename modules/{Admin/Language/pt => PodcastImport/Language/ro}/PodcastImport.php (100%) rename modules/{Admin/Language/ro => PodcastImport/Language/ru}/PodcastImport.php (100%) rename modules/{Admin/Language/ru => PodcastImport/Language/sk}/PodcastImport.php (100%) rename modules/{Admin/Language/sk => PodcastImport/Language/sr_Latn}/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/sv/PodcastImport.php (100%) rename modules/{Admin/Language/sr_Latn => PodcastImport/Language/uk}/PodcastImport.php (100%) rename modules/{Admin => PodcastImport}/Language/zh-Hans/PodcastImport.php (100%) rename modules/WebSub/{Controllers/WebSubController.php => Commands/Publish.php} (86%) delete mode 100644 modules/WebSub/Config/Routes.php create mode 100644 themes/cp_admin/import/_queue_table.php create mode 100644 themes/cp_admin/import/add_to_queue.php create mode 100644 themes/cp_admin/import/podcast_queue.php create mode 100644 themes/cp_admin/import/queue.php delete mode 100644 themes/cp_admin/podcast/import.php diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index 4f875095..f8ad08ec 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -43,23 +43,24 @@ class Autoload extends AutoloadConfig */ public $psr4 = [ APP_NAMESPACE => APPPATH, + 'Config' => APPPATH . 'Config/', 'Modules' => ROOTPATH . 'modules/', 'Modules\Admin' => ROOTPATH . 'modules/Admin/', - 'Modules\Auth' => ROOTPATH . 'modules/Auth/', 'Modules\Analytics' => ROOTPATH . 'modules/Analytics/', - 'Modules\Install' => ROOTPATH . 'modules/Install/', - 'Modules\Update' => ROOTPATH . 'modules/Update/', - 'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/', - 'Modules\Media' => ROOTPATH . 'modules/Media/', - 'Modules\WebSub' => ROOTPATH . 'modules/WebSub/', 'Modules\Api\Rest\V1' => ROOTPATH . 'modules/Api/Rest/V1', + 'Modules\Auth' => ROOTPATH . 'modules/Auth/', + 'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/', + 'Modules\Install' => ROOTPATH . 'modules/Install/', + 'Modules\Media' => ROOTPATH . 'modules/Media/', + 'Modules\MediaClipper' => ROOTPATH . 'modules/MediaClipper/', + 'Modules\PodcastImport' => ROOTPATH . 'modules/PodcastImport/', 'Modules\PremiumPodcasts' => ROOTPATH . 'modules/PremiumPodcasts/', - 'Config' => APPPATH . 'Config/', + 'Modules\Update' => ROOTPATH . 'modules/Update/', + 'Modules\WebSub' => ROOTPATH . 'modules/WebSub/', + 'Themes' => ROOTPATH . 'themes', 'ViewComponents' => APPPATH . 'Libraries/ViewComponents/', 'ViewThemes' => APPPATH . 'Libraries/ViewThemes/', - 'MediaClipper' => APPPATH . 'Libraries/MediaClipper/', 'Vite' => APPPATH . 'Libraries/Vite/', - 'Themes' => ROOTPATH . 'themes', ]; /** diff --git a/app/Config/Tasks.php b/app/Config/Tasks.php new file mode 100644 index 00000000..06dd531c --- /dev/null +++ b/app/Config/Tasks.php @@ -0,0 +1,55 @@ +command('fediverse:broadcast') + ->everyMinute() + ->named('fediverse-broadcast'); + + $schedule->command('websub:publish') + ->everyMinute() + ->named('websub-publish'); + + $schedule->command('video-clips:generate') + ->everyMinute() + ->named('video-clips-generate'); + + $schedule->command('podcast:import') + ->everyMinute() + ->named('podcast-import'); + } +} diff --git a/app/Controllers/WebmanifestController.php b/app/Controllers/WebmanifestController.php index d42da053..742709a3 100644 --- a/app/Controllers/WebmanifestController.php +++ b/app/Controllers/WebmanifestController.php @@ -89,11 +89,11 @@ class WebmanifestController extends Controller $webmanifest = [ 'name' => esc($podcast->title), - 'short_name' => '@' . esc($podcast->handle), + 'short_name' => $podcast->at_handle, 'description' => $podcast->description, 'lang' => $podcast->language_code, 'start_url' => $podcast->link, - 'scope' => '/@' . esc($podcast->handle), + 'scope' => '/' . $podcast->at_handle, 'display' => 'standalone', 'orientation' => 'portrait', 'theme_color' => self::THEME_COLORS[service('settings')->get('App.theme')]['theme'], diff --git a/app/Entities/Clip/BaseClip.php b/app/Entities/Clip/BaseClip.php index 4a2186a3..3528bfe8 100644 --- a/app/Entities/Clip/BaseClip.php +++ b/app/Entities/Clip/BaseClip.php @@ -129,15 +129,15 @@ class BaseClip extends Entity $this->getMedia() ->setFile($file); $this->getMedia() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('audio'))->updateMedia($this->getMedia()); } else { $media = new Audio([ 'file_key' => $fileKey, 'language_code' => $this->getPodcast() ->language_code, - 'uploaded_by' => $this->attributes['created_by'], - 'updated_by' => $this->attributes['created_by'], + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $media->setFile($file); diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php index 3108afcc..e16fc81c 100644 --- a/app/Entities/Episode.php +++ b/app/Entities/Episode.php @@ -188,15 +188,15 @@ class Episode extends Entity $this->getCover() ->setFile($file); $this->getCover() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('image'))->updateMedia($this->getCover()); } else { $cover = new Image([ 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '.' . $file->getExtension(), 'sizes' => config('Images') ->podcastCoverSizes, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $cover->setFile($file); @@ -234,7 +234,7 @@ class Episode extends Entity $this->getAudio() ->setFile($file); $this->getAudio() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('audio'))->updateMedia($this->getAudio()); } else { $audio = new Audio([ @@ -244,8 +244,8 @@ class Episode extends Entity ) . '.' . $file->getExtension(), 'language_code' => $this->getPodcast() ->language_code, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $audio->setFile($file); @@ -274,15 +274,15 @@ class Episode extends Entity $this->getTranscript() ->setFile($file); $this->getTranscript() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('transcript'))->updateMedia($this->getTranscript()); } else { $transcript = new Transcript([ 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '-transcript.' . $file->getExtension(), 'language_code' => $this->getPodcast() ->language_code, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $transcript->setFile($file); @@ -311,15 +311,15 @@ class Episode extends Entity $this->getChapters() ->setFile($file); $this->getChapters() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('chapters'))->updateMedia($this->getChapters()); } else { $chapters = new Chapters([ 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '-chapters' . '.' . $file->getExtension(), 'language_code' => $this->getPodcast() ->language_code, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $chapters->setFile($file); diff --git a/app/Entities/Person.php b/app/Entities/Person.php index b09aa6b6..961f5603 100644 --- a/app/Entities/Person.php +++ b/app/Entities/Person.php @@ -66,15 +66,15 @@ class Person extends Entity $this->getAvatar() ->setFile($file); $this->getAvatar() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('image'))->updateMedia($this->getAvatar()); } else { $avatar = new Image([ 'file_key' => 'persons/' . $this->attributes['unique_name'] . '.' . $file->getExtension(), 'sizes' => config('Images') ->personAvatarSizes, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $avatar->setFile($file); diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index 174e50a7..3aff5e15 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -41,6 +41,7 @@ use RuntimeException; * @property int $actor_id * @property Actor|null $actor * @property string $handle + * @property string $at_handle * @property string $link * @property string $feed_url * @property string $title @@ -240,15 +241,15 @@ class Podcast extends Entity $this->getCover() ->setFile($file); $this->getCover() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('image'))->updateMedia($this->getCover()); } else { $cover = new Image([ 'file_key' => 'podcasts/' . $this->attributes['handle'] . '/cover.' . $file->getExtension(), 'sizes' => config('Images') ->podcastCoverSizes, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $cover->setFile($file); @@ -283,15 +284,15 @@ class Podcast extends Entity $this->getBanner() ->setFile($file); $this->getBanner() - ->updated_by = (int) user_id(); + ->updated_by = $this->attributes['updated_by']; (new MediaModel('image'))->updateMedia($this->getBanner()); } else { $banner = new Image([ 'file_key' => 'podcasts/' . $this->attributes['handle'] . '/banner.' . $file->getExtension(), 'sizes' => config('Images') ->podcastBannerSizes, - 'uploaded_by' => user_id(), - 'updated_by' => user_id(), + 'uploaded_by' => $this->attributes['updated_by'], + 'updated_by' => $this->attributes['updated_by'], ]); $banner->setFile($file); diff --git a/app/Helpers/components_helper.php b/app/Helpers/components_helper.php index 773f6360..351d2ec0 100644 --- a/app/Helpers/components_helper.php +++ b/app/Helpers/components_helper.php @@ -218,8 +218,8 @@ if (! function_exists('publication_status_banner')) { } return << -

+

- publication_status !== 'published'): ?> + + get('Import.current') === $podcast->handle): ?> + + + publication_status !== 'published'): ?> published_at, $podcast->id, $podcast->publication_status) ?> - + +
renderSection('content') ?> diff --git a/themes/cp_admin/_sidebar.php b/themes/cp_admin/_sidebar.php index 2d1a9deb..e5a8d271 100644 --- a/themes/cp_admin/_sidebar.php +++ b/themes/cp_admin/_sidebar.php @@ -7,7 +7,7 @@ $navigation = [ ], 'podcasts' => [ 'icon' => 'mic', - 'items' => ['podcast-list', 'podcast-create', 'podcast-import'], + 'items' => ['podcast-list', 'podcast-create', 'all-podcast-imports', 'podcast-imports-add'], ], 'persons' => [ 'icon' => 'folder-user', diff --git a/themes/cp_admin/episode/list.php b/themes/cp_admin/episode/list.php index a0e5d275..2e603a59 100644 --- a/themes/cp_admin/episode/list.php +++ b/themes/cp_admin/episode/list.php @@ -27,7 +27,7 @@

- + diff --git a/themes/cp_admin/import/_queue_table.php b/themes/cp_admin/import/_queue_table.php new file mode 100644 index 00000000..fe51a3b1 --- /dev/null +++ b/themes/cp_admin/import/_queue_table.php @@ -0,0 +1,131 @@ + + + lang('PodcastImport.queue.status.label'), + 'cell' => function (PodcastImportTask $importTask) { + $pillVariantMap = [ + 'queued' => 'default', + 'pending' => 'warning', + 'running' => 'primary', + 'canceled' => 'default', + 'failed' => 'danger', + 'passed' => 'success', + ]; + + $pillIconMap = [ + 'queued' => 'timer', + 'pending' => 'pause', + 'running' => 'loader', + 'canceled' => 'forbid', + 'failed' => 'close', + 'passed' => 'check', + ]; + + $pillIconClassMap = [ + 'queued' => '', + 'pending' => '', + 'running' => 'animate-spin', + 'canceled' => '', + 'failed' => '', + 'passed' => '', + ]; + + $errorHint = $importTask->status === TaskStatus::Failed ? hint_tooltip($importTask->error, 'ml-1') : ''; + + return '
' . lang('PodcastImport.queue.status.' . $importTask->status->value) . '' . $errorHint . '
'; + }, + ], + [ + 'header' => lang('PodcastImport.queue.feed'), + 'cell' => function (PodcastImportTask $importTask) { + return << + {$importTask->feed_url} + @{$importTask->handle} +
+ HTML; + }, + ], + [ + 'header' => lang('PodcastImport.queue.duration'), + 'cell' => function (PodcastImportTask $importTask) { + $duration = '-'; + if ($importTask->started_at !== null) { + if ($importTask->ended_at !== null) { + $duration = '
' . + '
' . format_duration((int) $importTask->getDuration(), true) . '
' . + '
' . relative_time($importTask->ended_at) . '
' . + '
'; + } else { + $duration = '
' . format_duration(($importTask->started_at->difference(Time::now()))->getSeconds(), true) . '
'; + } + } + + return $duration; + }, + ], + [ + 'header' => lang('PodcastImport.queue.imported_episodes'), + 'cell' => function (PodcastImportTask $importTask) { + if ($importTask->episodes_count) { + $progressPercentage = (int) ($importTask->getProgress() * 100) . '%'; + $moreInfoHelper = hint_tooltip(lang('PodcastImport.queue.imported_episodes_hint', [ + 'newlyImportedCount' => $importTask->episodes_newly_imported, + 'alreadyImportedCount' => $importTask->episodes_already_imported, + ]), 'ml-1'); + return << + {$progressPercentage} +

+ {$importTask->episodes_imported} out of {$importTask->episodes_count} + {$moreInfoHelper} +

+
+ HTML; + } + + return '-'; + }, + ], + [ + 'header' => lang('Common.list.actions'), + 'cell' => function (PodcastImportTask $importTask) { + return '
' . + '' . + '' . + '
'; + }, + ], + ], + $podcastImportsQueue +) ?> diff --git a/themes/cp_admin/import/add_to_queue.php b/themes/cp_admin/import/add_to_queue.php new file mode 100644 index 00000000..377b2062 --- /dev/null +++ b/themes/cp_admin/import/add_to_queue.php @@ -0,0 +1,62 @@ +extend('_layout') ?> + +section('title') ?> + +endSection() ?> + +section('pageTitle') ?> + +endSection() ?> + +section('content') ?> + + + + + + + + + + + + +
+ +
+ + +
+
+ + + + + +
+ + + + + + +endSection() ?> diff --git a/themes/cp_admin/import/podcast_queue.php b/themes/cp_admin/import/podcast_queue.php new file mode 100644 index 00000000..9c38a5f0 --- /dev/null +++ b/themes/cp_admin/import/podcast_queue.php @@ -0,0 +1,20 @@ +extend('_layout') ?> + +section('title') ?> + +endSection() ?> + +section('pageTitle') ?> + +endSection() ?> + +section('headerRight') ?> + +endSection() ?> + + +section('content') ?> + +include('import/_queue_table'); ?> + +endSection() ?> diff --git a/themes/cp_admin/import/queue.php b/themes/cp_admin/import/queue.php new file mode 100644 index 00000000..6182c6f6 --- /dev/null +++ b/themes/cp_admin/import/queue.php @@ -0,0 +1,23 @@ + +extend('_layout') ?> + +section('title') ?> + +endSection() ?> + +section('pageTitle') ?> + +endSection() ?> + +section('headerRight') ?> + +endSection() ?> + + +section('content') ?> + +include('import/_queue_table'); ?> + +endSection() ?> diff --git a/themes/cp_admin/podcast/_sidebar.php b/themes/cp_admin/podcast/_sidebar.php index 35db7c54..3558cd51 100644 --- a/themes/cp_admin/podcast/_sidebar.php +++ b/themes/cp_admin/podcast/_sidebar.php @@ -3,7 +3,7 @@ $podcastNavigation = [ 'dashboard' => [ 'icon' => 'dashboard', - 'items' => ['podcast-view', 'podcast-edit', 'podcast-persons-manage'], + 'items' => ['podcast-view', 'podcast-edit', 'podcast-persons-manage', 'podcast-imports'], ], 'episodes' => [ 'icon' => 'play-circle', diff --git a/themes/cp_admin/podcast/edit.php b/themes/cp_admin/podcast/edit.php index 3b05c882..d4b9b283 100644 --- a/themes/cp_admin/podcast/edit.php +++ b/themes/cp_admin/podcast/edit.php @@ -248,7 +248,7 @@ - + diff --git a/themes/cp_admin/podcast/import.php b/themes/cp_admin/podcast/import.php deleted file mode 100644 index bd2ee775..00000000 --- a/themes/cp_admin/podcast/import.php +++ /dev/null @@ -1,99 +0,0 @@ -extend('_layout') ?> - -section('title') ?> - -endSection() ?> - -section('pageTitle') ?> - -endSection() ?> - -section('content') ?> - - - -
- - - - - - - - - -
- -
- - -
-
- - - - - -
- - - -
- - <title> - <link> -
- -
- - <description> - <itunes:summary> - <itunes:subtitle> + <itunes:summary> - <content:encoded> -
- - - - - - - -
- - - -
- - -endSection() ?> diff --git a/themes/cp_admin/podcast/list.php b/themes/cp_admin/podcast/list.php index 28cbd916..ae6567c4 100644 --- a/themes/cp_admin/podcast/list.php +++ b/themes/cp_admin/podcast/list.php @@ -9,7 +9,7 @@ endSection() ?> section('headerRight') ?> - + endSection() ?>