mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
feat(plugins): add settings page for podcast and episode if defined in the plugin's manifest
- rename options to settings
This commit is contained in:
parent
b9aa6a4d3e
commit
3f204819f3
@ -109,7 +109,7 @@ class Autoload extends AutoloadConfig
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public $helpers = ['auth', 'setting', 'icons'];
|
||||
public $helpers = ['auth', 'setting', 'icons', 'plugins'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -20,4 +20,5 @@ return [
|
||||
'video-clips-create' => 'New video clip',
|
||||
'soundbites-list' => 'Soundbites',
|
||||
'soundbites-create' => 'New soundbite',
|
||||
'plugins' => 'Plugins',
|
||||
];
|
||||
|
@ -20,6 +20,7 @@ return [
|
||||
'episodes' => 'Episodes',
|
||||
'episode-list' => 'All episodes',
|
||||
'episode-create' => 'New episode',
|
||||
'plugins' => 'Plugins',
|
||||
'analytics' => 'Analytics',
|
||||
'podcast-analytics' => 'Audience overview',
|
||||
'podcast-analytics-webpages' => 'Web pages visits',
|
||||
|
@ -22,7 +22,7 @@ use RuntimeException;
|
||||
* @property string[] $keywords
|
||||
* @property string[] $hooks
|
||||
* @property string $iconSrc
|
||||
* @property array{settings:array{key:string,name:string,description:string}[],podcast:array{key:string,name:string,description:string}[],episode:array{key:string,name:string,description:string}[]} $options
|
||||
* @property array{general:array{key:string,name:string,description:string}[],podcast:array{key:string,name:string,description:string}[],episode:array{key:string,name:string,description:string}[]} $settings
|
||||
*/
|
||||
abstract class BasePlugin implements PluginInterface
|
||||
{
|
||||
@ -147,24 +147,24 @@ abstract class BasePlugin implements PluginInterface
|
||||
|
||||
$validation = service('validation');
|
||||
|
||||
if (array_key_exists('options', $manifest)) {
|
||||
$optionRules = [
|
||||
if (array_key_exists('settings', $manifest)) {
|
||||
$fieldRules = [
|
||||
'key' => 'required|alpha_numeric',
|
||||
'name' => 'required|max_length[32]',
|
||||
'description' => 'permit_empty|max_length[128]',
|
||||
];
|
||||
$defaultOption = [
|
||||
$defaultField = [
|
||||
'key' => '',
|
||||
'name' => '',
|
||||
'description' => '',
|
||||
];
|
||||
$validation->setRules($optionRules);
|
||||
foreach ($manifest['options'] as $key => $options) {
|
||||
foreach ($options as $key2 => $option) {
|
||||
$manifest['options'][$key][$key2] = array_merge($defaultOption, $option);
|
||||
$validation->setRules($fieldRules);
|
||||
foreach ($manifest['settings'] as $key => $settings) {
|
||||
foreach ($settings as $key2 => $fields) {
|
||||
$manifest['settings'][$key][$key2] = array_merge($defaultField, $fields);
|
||||
|
||||
if (! $validation->run($manifest['options'][$key][$key2])) {
|
||||
dd($this->key, $manifest['options'][$key][$key2], $validation->getErrors());
|
||||
if (! $validation->run($manifest['settings'][$key][$key2])) {
|
||||
dd($this->key, $manifest['settings'][$key][$key2], $validation->getErrors());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,7 +183,7 @@ abstract class BasePlugin implements PluginInterface
|
||||
'website' => 'valid_url_strict',
|
||||
'keywords.*' => 'permit_empty|in_list[seo,podcasting20,analytics]',
|
||||
'hooks.*' => 'permit_empty|in_list[' . implode(',', Plugins::HOOKS) . ']',
|
||||
'options' => 'permit_empty',
|
||||
'settings' => 'permit_empty',
|
||||
];
|
||||
|
||||
$validation->setRules($rules);
|
||||
@ -200,10 +200,10 @@ abstract class BasePlugin implements PluginInterface
|
||||
'website' => '',
|
||||
'hooks' => [],
|
||||
'keywords' => [],
|
||||
'options' => [
|
||||
'settings' => [],
|
||||
'podcast' => [],
|
||||
'episode' => [],
|
||||
'settings' => [
|
||||
'general' => [],
|
||||
'podcast' => [],
|
||||
'episode' => [],
|
||||
],
|
||||
];
|
||||
|
||||
|
@ -13,26 +13,46 @@ $routes->group(
|
||||
],
|
||||
static function ($routes): void {
|
||||
$routes->group('plugins', static function ($routes): void {
|
||||
$routes->get('/', 'PluginsController::installed', [
|
||||
$routes->get('/', 'PluginController::installed', [
|
||||
'as' => 'plugins-installed',
|
||||
'filter' => 'permission:plugins.manage',
|
||||
]);
|
||||
$routes->get('(:segment)', 'PluginsController::settings/$1', [
|
||||
'as' => 'plugins-settings',
|
||||
$routes->get('(:segment)', 'PluginController::generalSettings/$1', [
|
||||
'as' => 'plugins-general-settings',
|
||||
'filter' => 'permission:plugins.manage',
|
||||
]);
|
||||
$routes->post('(:segment)', 'PluginsController::settingsAction/$1', [
|
||||
'as' => 'plugins-settings-action',
|
||||
$routes->post('(:segment)', 'PluginController::generalSettingsAction/$1', [
|
||||
'as' => 'plugins-general-settings-action',
|
||||
'filter' => 'permission:plugins.manage',
|
||||
]);
|
||||
$routes->post('activate/(:segment)', 'PluginsController::activate/$1', [
|
||||
$routes->post('activate/(:segment)', 'PluginController::activate/$1', [
|
||||
'as' => 'plugins-activate',
|
||||
'filter' => 'permission:plugins.manage',
|
||||
]);
|
||||
$routes->post('deactivate/(:segment)', 'PluginsController::deactivate/$1', [
|
||||
$routes->post('deactivate/(:segment)', 'PluginController::deactivate/$1', [
|
||||
'as' => 'plugins-deactivate',
|
||||
'filter' => 'permission:plugins.manage',
|
||||
]);
|
||||
});
|
||||
$routes->group('podcasts/(:num)/plugins', static function ($routes): void {
|
||||
$routes->get('(:segment)', 'PluginController::podcastSettings/$1/$2', [
|
||||
'as' => 'plugins-podcast-settings',
|
||||
'filter' => 'permission:podcast#.edit',
|
||||
]);
|
||||
$routes->post('(:segment)', 'PluginController::podcastSettingsAction/$1/$2', [
|
||||
'as' => 'plugins-podcast-settings-action',
|
||||
'filter' => 'permission:podcast#.edit',
|
||||
]);
|
||||
});
|
||||
$routes->group('podcasts/(:num)/episodes/(:num)/plugins', static function ($routes): void {
|
||||
$routes->get('(:segment)', 'PluginController::episodeSettings/$1/$2/$3', [
|
||||
'as' => 'plugins-episode-settings',
|
||||
'filter' => 'permission:podcast#.edit',
|
||||
]);
|
||||
$routes->post('(:segment)', 'PluginController::episodeSettingsAction/$1/$2/$3', [
|
||||
'as' => 'plugins-episode-settings-action',
|
||||
'filter' => 'permission:podcast#.edit',
|
||||
]);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
193
modules/Plugins/Controllers/PluginController.php
Normal file
193
modules/Plugins/Controllers/PluginController.php
Normal file
@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Plugins\Controllers;
|
||||
|
||||
use App\Entities\Episode;
|
||||
use App\Entities\Podcast;
|
||||
use App\Models\EpisodeModel;
|
||||
use App\Models\PodcastModel;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use Modules\Admin\Controllers\BaseController;
|
||||
use Modules\Plugins\Plugins;
|
||||
|
||||
class PluginController extends BaseController
|
||||
{
|
||||
public function installed(): string
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$pager = service('pager');
|
||||
|
||||
$page = (int) ($this->request->getGet('page') ?? 1);
|
||||
$perPage = 10;
|
||||
$total = $plugins->getInstalledCount();
|
||||
|
||||
$pager_links = $pager->makeLinks($page, $perPage, $total);
|
||||
|
||||
return view('plugins/installed', [
|
||||
'total' => $total,
|
||||
'plugins' => $plugins->getPlugins($page, $perPage),
|
||||
'pager_links' => $pager_links,
|
||||
]);
|
||||
}
|
||||
|
||||
public function generalSettings(string $pluginKey): string
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
helper('form');
|
||||
return view('plugins/settings_general', [
|
||||
'plugin' => $plugin,
|
||||
]);
|
||||
}
|
||||
|
||||
public function generalSettingsAction(string $pluginKey): RedirectResponse
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
foreach ($plugin->settings['general'] as $option) {
|
||||
$optionKey = $option['key'];
|
||||
$optionValue = $this->request->getPost($optionKey);
|
||||
$plugins->setOption($pluginKey, $optionKey, $optionValue);
|
||||
}
|
||||
|
||||
return redirect()->back()
|
||||
->with('message', lang('Plugins.messages.saveSettingsSuccess', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]));
|
||||
}
|
||||
|
||||
public function podcastSettings(string $podcastId, string $pluginKey): string
|
||||
{
|
||||
$podcast = (new PodcastModel())->getPodcastById((int) $podcastId);
|
||||
|
||||
if (! $podcast instanceof Podcast) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
helper('form');
|
||||
replace_breadcrumb_params([
|
||||
0 => $podcast->handle,
|
||||
]);
|
||||
return view('plugins/settings_podcast', [
|
||||
'podcast' => $podcast,
|
||||
'plugin' => $plugin,
|
||||
]);
|
||||
}
|
||||
|
||||
public function podcastSettingsAction(string $podcastId, string $pluginKey): RedirectResponse
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
foreach ($plugin->settings['podcast'] as $setting) {
|
||||
$settingKey = $setting['key'];
|
||||
$settingValue = $this->request->getPost($settingKey);
|
||||
$plugins->setOption($pluginKey, $settingKey, $settingValue, ['podcast', (int) $podcastId]);
|
||||
}
|
||||
|
||||
return redirect()->back()
|
||||
->with('message', lang('Plugins.messages.saveSettingsSuccess', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]));
|
||||
}
|
||||
|
||||
public function episodeSettings(string $podcastId, string $episodeId, string $pluginKey): string
|
||||
{
|
||||
$episode = (new EpisodeModel())->getEpisodeById((int) $episodeId);
|
||||
|
||||
if (! $episode instanceof Episode) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
helper('form');
|
||||
replace_breadcrumb_params([
|
||||
0 => $episode->podcast->handle,
|
||||
1 => $episode->title,
|
||||
]);
|
||||
return view('plugins/settings_episode', [
|
||||
'podcast' => $episode->podcast,
|
||||
'episode' => $episode,
|
||||
'plugin' => $plugin,
|
||||
]);
|
||||
}
|
||||
|
||||
public function episodeSettingsAction(string $podcastId, string $episodeId, string $pluginKey): RedirectResponse
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
foreach ($plugin->settings['episode'] as $setting) {
|
||||
$settingKey = $setting['key'];
|
||||
$settingValue = $this->request->getPost($settingKey);
|
||||
$plugins->setOption($pluginKey, $settingKey, $settingValue, ['episode', (int) $episodeId]);
|
||||
}
|
||||
|
||||
return redirect()->back()
|
||||
->with('message', lang('Plugins.messages.saveSettingsSuccess', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]));
|
||||
}
|
||||
|
||||
public function activate(string $pluginKey): RedirectResponse
|
||||
{
|
||||
service('plugins')->activate($pluginKey);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function deactivate(string $pluginKey): RedirectResponse
|
||||
{
|
||||
service('plugins')->deactivate($pluginKey);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Plugins\Controllers;
|
||||
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use Modules\Admin\Controllers\BaseController;
|
||||
use Modules\Plugins\Plugins;
|
||||
|
||||
class PluginsController extends BaseController
|
||||
{
|
||||
public function installed(): string
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$pager = service('pager');
|
||||
|
||||
$page = (int) ($this->request->getGet('page') ?? 1);
|
||||
$perPage = 10;
|
||||
$total = $plugins->getInstalledCount();
|
||||
|
||||
$pager_links = $pager->makeLinks($page, $perPage, $total);
|
||||
|
||||
return view('plugins/installed', [
|
||||
'total' => $total,
|
||||
'plugins' => $plugins->getPlugins($page, $perPage),
|
||||
'pager_links' => $pager_links,
|
||||
]);
|
||||
}
|
||||
|
||||
public function settings(string $pluginKey): string
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
helper('form');
|
||||
return view('plugins/settings', [
|
||||
'plugin' => $plugin,
|
||||
]);
|
||||
}
|
||||
|
||||
public function settingsAction(string $pluginKey): RedirectResponse
|
||||
{
|
||||
/** @var Plugins $plugins */
|
||||
$plugins = service('plugins');
|
||||
|
||||
$plugin = $plugins->getPlugin($pluginKey);
|
||||
|
||||
if ($plugin === null) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
foreach ($plugin->options['settings'] as $option) {
|
||||
$optionKey = $option['key'];
|
||||
$optionValue = $this->request->getPost($optionKey);
|
||||
$plugins->setOption($pluginKey, $optionKey, $optionValue);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function activate(string $pluginKey): RedirectResponse
|
||||
{
|
||||
service('plugins')->activate($pluginKey);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function deactivate(string $pluginKey): RedirectResponse
|
||||
{
|
||||
service('plugins')->deactivate($pluginKey);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
@ -2,22 +2,49 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Modules\Plugins\Plugins;
|
||||
|
||||
if (! function_exists('plugins')) {
|
||||
function plugins(): Plugins
|
||||
{
|
||||
return service('plugins');
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('get_plugin_option')) {
|
||||
function get_plugin_option(string $pluginKey, string $option): mixed
|
||||
/**
|
||||
* @param ?array{'podcast'|'episode',int} $additionalContext
|
||||
*/
|
||||
function get_plugin_option(string $pluginKey, string $option, array $additionalContext = null): mixed
|
||||
{
|
||||
$key = sprintf('Plugins.%s', $option);
|
||||
$context = sprintf('plugin:%s', $pluginKey);
|
||||
|
||||
if ($additionalContext !== null) {
|
||||
$context .= sprintf('+%s:%d', ...$additionalContext);
|
||||
}
|
||||
|
||||
return setting()->get($key, $context);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('set_plugin_option')) {
|
||||
function set_plugin_option(string $pluginKey, string $option, mixed $value = null): void
|
||||
{
|
||||
/**
|
||||
* @param ?array{'podcast'|'episode',int} $additionalContext
|
||||
*/
|
||||
function set_plugin_option(
|
||||
string $pluginKey,
|
||||
string $option,
|
||||
mixed $value = null,
|
||||
array $additionalContext = null
|
||||
): void {
|
||||
$key = sprintf('Plugins.%s', $option);
|
||||
$context = sprintf('plugin:%s', $pluginKey);
|
||||
|
||||
if ($additionalContext !== null) {
|
||||
$context .= sprintf('+%s:%d', ...$additionalContext);
|
||||
}
|
||||
|
||||
setting()
|
||||
->set($key, $value, $context);
|
||||
}
|
||||
|
@ -9,14 +9,18 @@ declare(strict_types=1);
|
||||
*/
|
||||
|
||||
return [
|
||||
"installed" => "Installed plugins ({count})",
|
||||
"website" => "Website",
|
||||
"activate" => "Activate",
|
||||
"deactivate" => "Deactivate",
|
||||
"keywords" => [
|
||||
'installed' => 'Installed plugins ({count})',
|
||||
'website' => 'Website',
|
||||
'settings' => '{pluginName} settings',
|
||||
'activate' => 'Activate',
|
||||
'deactivate' => 'Deactivate',
|
||||
'keywords' => [
|
||||
'podcasting20' => 'Podcasting 2.0',
|
||||
'seo' => 'SEO',
|
||||
'analytics' => 'Analytics',
|
||||
'accessibility' => 'Accessibility',
|
||||
],
|
||||
'messages' => [
|
||||
'saveSettingsSuccess' => '{pluginName} settings were successfully saved!',
|
||||
],
|
||||
];
|
||||
|
@ -57,6 +57,48 @@ class Plugins
|
||||
return array_slice(static::$plugins, (($page - 1) * $perPage), $perPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<BasePlugin>
|
||||
*/
|
||||
public function getPluginsWithPodcastSettings(): array
|
||||
{
|
||||
$pluginsWithPodcastSettings = [];
|
||||
foreach (static::$plugins as $plugin) {
|
||||
if (! $plugin->isActive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($plugin->settings['podcast'] === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$pluginsWithPodcastSettings[] = $plugin;
|
||||
}
|
||||
|
||||
return $pluginsWithPodcastSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<BasePlugin>
|
||||
*/
|
||||
public function getPluginsWithEpisodeSettings(): array
|
||||
{
|
||||
$pluginsWithEpisodeSettings = [];
|
||||
foreach (static::$plugins as $plugin) {
|
||||
if (! $plugin->isActive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($plugin->settings['episode'] === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$pluginsWithEpisodeSettings[] = $plugin;
|
||||
}
|
||||
|
||||
return $pluginsWithEpisodeSettings;
|
||||
}
|
||||
|
||||
public function getPlugin(string $key): ?BasePlugin
|
||||
{
|
||||
foreach (static::$plugins as $plugin) {
|
||||
@ -98,9 +140,12 @@ class Plugins
|
||||
set_plugin_option($pluginKey, 'active', false);
|
||||
}
|
||||
|
||||
public function setOption(string $pluginKey, string $name, string $value): void
|
||||
/**
|
||||
* @param ?array{'podcast'|'episode',int} $additionalContext
|
||||
*/
|
||||
public function setOption(string $pluginKey, string $name, mixed $value, array $additionalContext = null): void
|
||||
{
|
||||
set_plugin_option($pluginKey, $name, $value);
|
||||
set_plugin_option($pluginKey, $name, $value, $additionalContext);
|
||||
}
|
||||
|
||||
public function getInstalledCount(): int
|
||||
|
@ -1,9 +1,14 @@
|
||||
<nav class="flex flex-col flex-1 py-4 overflow-y-auto">
|
||||
<?php foreach ($navigation as $section => $data):
|
||||
if ($data['items'] === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isSectionActive = false;
|
||||
$activeItem = '';
|
||||
foreach ($data['items'] as $item) {
|
||||
if (url_is(route_to($item, $podcastId ?? null, $episodeId ?? null))) {
|
||||
$href = str_starts_with($item, '/') ? $item : route_to($item, $podcastId ?? null, $episodeId ?? null);
|
||||
if (url_is($href)) {
|
||||
$activeItem = $item;
|
||||
$isSectionActive = true;
|
||||
}
|
||||
@ -27,8 +32,10 @@
|
||||
<?php endif; ?>
|
||||
</summary>
|
||||
<ul class="flex flex-col pb-4">
|
||||
<?php foreach ($data['items'] as $item):
|
||||
<?php foreach ($data['items'] as $key => $item):
|
||||
$isActive = $item === $activeItem;
|
||||
$label = array_key_exists('items-labels', $data) ? $data['items-labels'][$key] : lang($langKey . '.' . $item);
|
||||
$href = str_starts_with($item, '/') ? $item : route_to($item, $podcastId ?? null, $episodeId ?? null);
|
||||
|
||||
$isAllowed = true;
|
||||
if (array_key_exists('items-permissions', $data) && array_key_exists($item, $data['items-permissions'])) {
|
||||
@ -43,13 +50,9 @@
|
||||
<?php if ($isAllowed): ?>
|
||||
<a class="relative w-full py-3 pl-14 pr-2 text-sm hover:opacity-100 before:content-chevronRightIcon before:absolute before:-ml-5 before:opacity-0 before:w-5 before:h-5 hover:bg-navigation-active focus:ring-inset focus:ring-accent<?= $isActive
|
||||
? ' before:opacity-100 font-semibold inline-flex items-center'
|
||||
: ' hover:before:opacity-60 focus:before:opacity-60' ?>" href="<?= route_to($item, $podcastId ?? null, $episodeId ?? null) ?>"><?= lang(
|
||||
$langKey . '.' . $item,
|
||||
) ?></a>
|
||||
: ' hover:before:opacity-60 focus:before:opacity-60' ?>" href="<?= $href ?>"><?= $label ?></a>
|
||||
<?php else: ?>
|
||||
<span data-tooltip="right" title="<?= lang('Navigation.not-authorized') ?>" class="relative w-full py-3 pr-2 text-sm cursor-not-allowed before:inset-y-0 before:my-auto pl-14 hover:opacity-100 before:absolute before:content-prohibitedIcon before:-ml-5 before:opacity-60 before:w-4 before:h-4 hover:bg-navigation-active focus:ring-inset focus:ring-accent"><?= lang(
|
||||
$langKey . '.' . $item,
|
||||
) ?></span>
|
||||
<span data-tooltip="right" title="<?= lang('Navigation.not-authorized') ?>" class="relative w-full py-3 pr-2 text-sm cursor-not-allowed before:inset-y-0 before:my-auto pl-14 hover:opacity-100 before:absolute before:content-prohibitedIcon before:-ml-5 before:opacity-60 before:w-4 before:h-4 hover:bg-navigation-active focus:ring-inset focus:ring-accent"><?= $label ?></span>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
|
@ -24,7 +24,22 @@ $episodeNavigation = [
|
||||
'count-route' => 'video-clips-list',
|
||||
'add-cta' => 'video-clips-create',
|
||||
],
|
||||
]; ?>
|
||||
'plugins' => [
|
||||
'icon' => 'puzzle-fill', // @icon('puzzle-fill')
|
||||
'items' => [],
|
||||
'items-labels' => [],
|
||||
'items-permissions' => [],
|
||||
],
|
||||
];
|
||||
|
||||
foreach (plugins()->getPluginsWithEpisodeSettings() as $plugin) {
|
||||
$route = route_to('plugins-episode-settings', $podcast->id, $episode->id, $plugin->getKey());
|
||||
$episodeNavigation['plugins']['items'][] = $route;
|
||||
$episodeNavigation['plugins']['items-labels'][] = $plugin->getName();
|
||||
$episodeNavigation['plugins']['items-permissions'][$route] = 'episodes.edit';
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<a href="<?= route_to('podcast-view', $podcast->id) ?>" class="flex items-center px-4 py-2 focus:ring-inset focus:ring-accent">
|
||||
<?= icon('arrow-left-line', [
|
||||
|
@ -1,4 +1,10 @@
|
||||
<article class="flex flex-col p-4 rounded-xl bg-elevated border-3 <?= $plugin->isActive() ? 'border-accent-base' : 'border-subtle' ?>">
|
||||
<article class="flex flex-col p-4 rounded-xl relative bg-elevated border-3 <?= $plugin->isActive() ? 'border-accent-base' : 'border-subtle' ?>">
|
||||
<?php if ($plugin->settings['general'] !== []): ?>
|
||||
<?php // @icon('equalizer-fill')?>
|
||||
<IconButton class="absolute top-0 right-0 mt-4 mr-4" uri="<?= route_to('plugins-general-settings', $plugin->getKey()) ?>" glyph="equalizer-fill"><?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?></IconButton>
|
||||
<?php endif; ?>
|
||||
<img class="rounded-full min-w-16 max-w-16 aspect-square" src="<?= $plugin->iconSrc ?>">
|
||||
<div class="flex flex-col mt-2">
|
||||
<h2 class="flex items-center text-xl font-bold font-display gap-x-2"><?= $plugin->getName() ?><span class="px-1 font-mono text-xs rounded-full bg-subtle"><?= $plugin->version ?></span></h2>
|
||||
@ -8,10 +14,7 @@
|
||||
<a href="<?= $plugin->website ?>" class="inline-flex items-center text-sm font-semibold underline hover:no-underline gap-x-1" target="_blank" rel="noopener noreferrer"><?= icon('link', [
|
||||
'class' => 'text-gray-500',
|
||||
]) . lang('Plugins.website') ?></a>
|
||||
<?php if ($plugin->options['settings'] !== []): ?>
|
||||
<?php // @icon('equalizer-fill')?>
|
||||
<IconButton uri="<?= route_to('plugins-settings', $plugin->getKey()) ?>" glyph="equalizer-fill">Settings</IconButton>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if($plugin->isActive()): ?>
|
||||
<form class="flex justify-end" method="POST" action="<?= route_to('plugins-deactivate', $plugin->getKey()) ?>">
|
||||
<?= csrf_field() ?>
|
||||
|
12
themes/cp_admin/plugins/_settings.php
Normal file
12
themes/cp_admin/plugins/_settings.php
Normal file
@ -0,0 +1,12 @@
|
||||
<form method="POST" action="<?= $action ?>" class="flex flex-col max-w-sm gap-4" >
|
||||
<?= csrf_field() ?>
|
||||
<?php foreach ($plugin->settings[$type] as $field): ?>
|
||||
<Forms.Field
|
||||
name="<?= $field['key'] ?>"
|
||||
label="<?= $field['name'] ?>"
|
||||
hint="<?= $field['description'] ?>"
|
||||
value="<?= get_plugin_option($plugin->getKey(), $field['key'], $context) ?>"
|
||||
/>
|
||||
<?php endforeach; ?>
|
||||
<Button class="self-end mt-4" variant="primary" type="submit"><?= lang('Common.forms.save') ?></Button>
|
||||
</form>
|
@ -1,15 +0,0 @@
|
||||
<?= $this->extend('_layout') ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<form method="POST" action="<?= route_to('plugins-settings-action', $plugin->getKey()) ?>" class="flex flex-col max-w-sm gap-4" >
|
||||
<?= csrf_field() ?>
|
||||
<?php foreach ($plugin->options['settings'] as $option): ?>
|
||||
<Forms.Field
|
||||
name="<?= $option['key'] ?>"
|
||||
label="<?= $option['name'] ?>"
|
||||
hint="<?= $option['description'] ?>"
|
||||
/>
|
||||
<?php endforeach; ?>
|
||||
<Button class="self-end mt-4" variant="primary" type="submit"><?= lang('Plugins.form.save') ?></Button>
|
||||
</form>
|
||||
<?= $this->endSection() ?>
|
22
themes/cp_admin/plugins/settings_episode.php
Normal file
22
themes/cp_admin/plugins/settings_episode.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?= $this->extend('_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('pageTitle') ?>
|
||||
<?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<?= view('plugins/_settings', [
|
||||
'plugin' => $plugin,
|
||||
'action' => route_to('plugins-episode-settings-action', $podcast->id, $episode->id, $plugin->getKey()),
|
||||
'type' => 'episode',
|
||||
'context' => ['episode', $episode->id],
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
22
themes/cp_admin/plugins/settings_general.php
Normal file
22
themes/cp_admin/plugins/settings_general.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?= $this->extend('_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('pageTitle') ?>
|
||||
<?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<?= view('plugins/_settings', [
|
||||
'plugin' => $plugin,
|
||||
'action' => route_to('plugins-general-settings-action', $plugin->getKey()),
|
||||
'type' => 'general',
|
||||
'context' => null,
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
22
themes/cp_admin/plugins/settings_podcast.php
Normal file
22
themes/cp_admin/plugins/settings_podcast.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?= $this->extend('_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('pageTitle') ?>
|
||||
<?= lang('Plugins.settings', [
|
||||
'pluginName' => $plugin->getName(),
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<?= view('plugins/_settings', [
|
||||
'plugin' => $plugin,
|
||||
'action' => route_to('plugins-podcast-settings-action', $podcast->id, $plugin->getKey()),
|
||||
'type' => 'podcast',
|
||||
'context' => ['podcast', $podcast->id],
|
||||
]) ?>
|
||||
<?= $this->endSection() ?>
|
@ -23,6 +23,12 @@ $podcastNavigation = [
|
||||
'count' => $podcast->getEpisodesCount(),
|
||||
'count-route' => 'episode-list',
|
||||
],
|
||||
'plugins' => [
|
||||
'icon' => 'puzzle-fill', // @icon('puzzle-fill')
|
||||
'items' => [],
|
||||
'items-labels' => [],
|
||||
'items-permissions' => [],
|
||||
],
|
||||
'analytics' => [
|
||||
'icon' => 'line-chart-fill', // @icon('line-chart-fill')
|
||||
'items' => [
|
||||
@ -83,6 +89,13 @@ $podcastNavigation = [
|
||||
],
|
||||
];
|
||||
|
||||
foreach (plugins()->getPluginsWithPodcastSettings() as $plugin) {
|
||||
$route = route_to('plugins-podcast-settings', $podcast->id, $plugin->getKey());
|
||||
$podcastNavigation['plugins']['items'][] = $route;
|
||||
$podcastNavigation['plugins']['items-labels'][] = $plugin->getName();
|
||||
$podcastNavigation['plugins']['items-permissions'][$route] = 'edit';
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="flex gap-2 px-2 py-2 border-b border-navigation">
|
||||
|
Loading…
x
Reference in New Issue
Block a user