Commit dfb7888a authored by Yassine Doghri's avatar Yassine Doghri
Browse files

feat(plugins): add aside with plugin metadata next to plugin's readme

- enhance plugin card ui
- refactor components to be more consistent
- invert toggler label for better UX
- edit view components regex
parent e6bfdfc3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,6 +31,6 @@ if (! function_exists('replace_breadcrumb_params')) {
    function replace_breadcrumb_params(array $newParams): void
    {
        $breadcrumb = Services::breadcrumb();
        $breadcrumb->replaceParams(esc($newParams));
        $breadcrumb->replaceParams($newParams);
    }
}
+12 −41
Original line number Diff line number Diff line
@@ -16,31 +16,6 @@ use CodeIgniter\View\Table;

// ------------------------------------------------------------------------

if (! function_exists('hint_tooltip')) {
    /**
     * Hint component
     *
     * Used to produce tooltip with a question mark icon for hint texts
     *
     * @param string $hintText The hint text
     */
    function hint_tooltip(string $hintText = '', string $class = ''): string
    {
        $tooltip =
            '<span data-tooltip="bottom" tabindex="0" title="' .
            esc($hintText) .
            '" class="inline-block align-middle opacity-75 focus:ring-accent';

        if ($class !== '') {
            $tooltip .= ' ' . $class;
        }

        return $tooltip . '">' . icon('question-fill') . '</span>';
    }
}

// ------------------------------------------------------------------------

if (! function_exists('data_table')) {
    /**
     * Data table component
@@ -113,12 +88,12 @@ if (! function_exists('publication_pill')) {
     */
    function publication_pill(?Time $publicationDate, string $publicationStatus, string $customClass = ''): string
    {
        $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',
        $variant = match ($publicationStatus) {
            'published'     => 'success',
            'scheduled'     => 'warning',
            'with_podcast'  => 'info',
            'not_published' => 'default',
            default         => 'default',
        };

        $title = match ($publicationStatus) {
@@ -130,16 +105,12 @@ if (! function_exists('publication_pill')) {

        $label = lang('Episode.publication_status.' . $publicationStatus);

        return '<span ' . ($title === '' ? '' : 'title="' . $title . '"') . ' class="flex items-center px-1 font-semibold border rounded w-max ' .
            $class .
            ' ' .
            $customClass .
            '">' .
            $label .
            ($publicationStatus === 'with_podcast' ? icon('error-warning-fill', [
        // @icon('error-warning-fill')
        return '<x-Pill ' . ($title === '' ? '' : 'title="' . $title . '"') . ' variant="' . $variant . '" class="' . $customClass .
            '">' . $label . ($publicationStatus === 'with_podcast' ? icon('error-warning-fill', [
                'class' => 'flex-shrink-0 ml-1 text-lg',
            ]) : '') .
            '</span>';
            '</x-Pill>';
    }
}

@@ -182,7 +153,7 @@ if (! function_exists('publication_button')) {
        }

        return <<<HTML
            <Button variant="{$variant}" uri="{$route}" iconLeft="{$iconLeft}" >{$label}</Button>
            <x-Button variant="{$variant}" uri="{$route}" iconLeft="{$iconLeft}" >{$label}</x-Button>
        HTML;
    }
}
@@ -356,7 +327,7 @@ if (! function_exists('location_link')) {
                'class' => 'mr-2 flex-shrink-0',
            ]) . '<span class="truncate">' . esc($location->name) . '</span>',
            [
                'class' => 'w-full overflow-hidden inline-flex items-baseline hover:underline focus:ring-accent' .
                'class' => 'w-full overflow-hidden inline-flex items-baseline hover:underline' .
                    ($class === '' ? '' : " {$class}"),
                'target' => '_blank',
                'rel'    => 'noreferrer noopener',
+6 −6
Original line number Diff line number Diff line
@@ -20,30 +20,30 @@ if (! function_exists('render_page_links')) {
    {
        $pages = (new PageModel())->findAll();
        $links = anchor(route_to('home'), lang('Common.home'), [
            'class' => 'px-2 py-1 underline hover:no-underline focus:ring-accent',
            'class' => 'px-2 py-1 underline hover:no-underline',
        ]);
        if ($podcastHandle !== null) {
            $links .= anchor(route_to('podcast-links', $podcastHandle), lang('Podcast.links'), [
                'class' => 'px-2 py-1 underline hover:no-underline focus:ring-accent',
                'class' => 'px-2 py-1 underline hover:no-underline',
            ]);
        }

        $links .= anchor(route_to('credits'), lang('Person.credits'), [
            'class' => 'px-2 py-1 underline hover:no-underline focus:ring-accent',
            'class' => 'px-2 py-1 underline hover:no-underline',
        ]);
        $links .= anchor(route_to('map'), lang('Page.map.title'), [
            'class' => 'px-2 py-1 underline hover:no-underline focus:ring-accent',
            'class' => 'px-2 py-1 underline hover:no-underline',
        ]);
        foreach ($pages as $page) {
            $links .= anchor($page->link, esc($page->title), [
                'class' => 'px-2  py-1 underline hover:no-underline focus:ring-accent',
                'class' => 'px-2  py-1 underline hover:no-underline',
            ]);
        }

        // if set in .env, add legal notice link at the end of page links
        if (config('App')->legalNoticeURL !== null) {
            $links .= anchor(config('App')->legalNoticeURL, lang('Common.legal_notice'), [
                'class'  => 'px-2 py-1 underline hover:no-underline focus:ring-accent',
                'class'  => 'px-2 py-1 underline hover:no-underline',
                'target' => '_blank',
                'rel'    => 'noopener noreferrer',
            ]);
+13 −8
Original line number Diff line number Diff line
@@ -32,12 +32,18 @@ class Breadcrumb
        $uri = '';
        foreach (current_url(true)->getSegments() as $segment) {
            $uri .= '/' . $segment;
            $this->links[] = [
            $link = [
                'text' => is_numeric($segment)
                    ? $segment
                    : lang('Breadcrumb.' . $segment),
                'href' => base_url($uri),
            ];

            if (is_numeric($segment)) {
                $this->links[] = $link;
            } else {
                $this->links[$segment] = $link;
            }
        }
    }

@@ -46,20 +52,19 @@ class Breadcrumb
     *
     * Given a breadcrumb with numeric params, this function replaces them with the values provided in $newParams
     *
     * Example with `Home / podcasts / 1 / episodes / 1`
     * Example with `Home / podcasts / 1 / episodes / 1 / foo`
     *
     * $newParams = [ 0 => 'foo', 1 => 'bar' ] replaceParams($newParams);
     * $newParams = [ 0 => 'bar', 1 => 'baz', 'foo' => 'I Pity The Foo' ] replaceParams($newParams);
     *
     * The breadcrumb is now `Home / podcasts / foo / episodes / bar`
     * The breadcrumb is now `Home / podcasts / foo / episodes / bar / I Pity The Foo`
     *
     * @param string[] $newParams
     */
    public function replaceParams(array $newParams): void
    {
        foreach ($this->links as $key => $link) {
            if (is_numeric($link['text'])) {
                $this->links[$key]['text'] = $newParams[0];
                array_shift($newParams);
        foreach ($newParams as $key => $newValue) {
            if (array_key_exists($key, $this->links)) {
                $this->links[$key]['text'] = $newValue;
            }
        }
    }
+42 −8
Original line number Diff line number Diff line
@@ -4,26 +4,30 @@ declare(strict_types=1);

namespace ViewComponents;

class Component implements ComponentInterface
abstract class Component implements ComponentInterface
{
    protected string $slot = '';
    /**
     * @var list<string>
     */
    protected array $props = [];

    /**
     * @var array<string, string|'boolean'|'array'|'number'>
     */
    protected array $casts = [];

    protected string $class = '';
    protected ?string $slot = null;

    /**
     * @var array<string, string>
     */
    protected array $attributes = [
        'class' => '',
    ];
    protected array $attributes = [];

    /**
     * @param array<string, string> $attributes
     */
    public function __construct(array $attributes)
    {
        helper('viewcomponents');

        // overwrite default attributes if set
        $this->attributes = [...$this->attributes, ...$attributes];

@@ -42,9 +46,39 @@ class Component implements ComponentInterface
            if (is_callable([$this, $method])) {
                $this->{$method}($value);
            } else {
                if (array_key_exists($name, $this->casts)) {
                    $value = match ($this->casts[$name]) {
                        'boolean' => $value === 'true',
                        'number'  => (int) $value,
                        'array'   => json_decode(htmlspecialchars_decode($value), true),
                        default   => $value
                    };
                }

                $this->{$name} = $value;
            }

            // remove from attributes
            if (in_array($name, $this->props, true)) {
                unset($this->attributes[$name]);
            }
        }

        unset($this->attributes['slot']);
    }

    public function mergeClass(string $class): void
    {
        if (! array_key_exists('class', $this->attributes)) {
            $this->attributes['class'] = $class;
        } else {
            $this->attributes['class'] .= ' ' . $class;
        }
    }

    public function getStringifiedAttributes(): string
    {
        return stringify_attributes($this->attributes);
    }

    public function render(): string
Loading