init with kirby, vue and pagedjs interactive
This commit is contained in:
commit
dc0ae26464
968 changed files with 211706 additions and 0 deletions
64
public/kirby/src/Panel/Ui/Button.php
Normal file
64
public/kirby/src/Panel/Ui/Button.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui;
|
||||
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class Button extends Component
|
||||
{
|
||||
public function __construct(
|
||||
public string $component = 'k-button',
|
||||
public array|null $badge = null,
|
||||
public string|null $class = null,
|
||||
public string|bool|null $current = null,
|
||||
public string|null $dialog = null,
|
||||
public bool $disabled = false,
|
||||
public string|null $drawer = null,
|
||||
public bool|null $dropdown = null,
|
||||
public string|null $icon = null,
|
||||
public string|null $link = null,
|
||||
public bool|string $responsive = true,
|
||||
public string|null $size = null,
|
||||
public string|null $style = null,
|
||||
public string|null $target = null,
|
||||
public string|array|null $text = null,
|
||||
public string|null $theme = null,
|
||||
public string|array|null $title = null,
|
||||
public string $type = 'button',
|
||||
public string|null $variant = null,
|
||||
...$attrs
|
||||
) {
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
...parent::props(),
|
||||
'badge' => $this->badge,
|
||||
'current' => $this->current,
|
||||
'dialog' => $this->dialog,
|
||||
'disabled' => $this->disabled,
|
||||
'drawer' => $this->drawer,
|
||||
'dropdown' => $this->dropdown,
|
||||
'icon' => $this->icon,
|
||||
'link' => $this->link,
|
||||
'responsive' => $this->responsive,
|
||||
'size' => $this->size,
|
||||
'target' => $this->target,
|
||||
'text' => I18n::translate($this->text, $this->text),
|
||||
'theme' => $this->theme,
|
||||
'title' => I18n::translate($this->title, $this->title),
|
||||
'type' => $this->type,
|
||||
'variant' => $this->variant,
|
||||
];
|
||||
}
|
||||
}
|
||||
33
public/kirby/src/Panel/Ui/Buttons/LanguageCreateButton.php
Normal file
33
public/kirby/src/Panel/Ui/Buttons/LanguageCreateButton.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* View button to create a new language
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class LanguageCreateButton extends ViewButton
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$user = App::instance()->user();
|
||||
$permission = $user?->role()->permissions()->for('languages', 'create');
|
||||
|
||||
parent::__construct(
|
||||
dialog: 'languages/create',
|
||||
disabled: $permission !== true,
|
||||
icon: 'add',
|
||||
text: I18n::translate('language.create'),
|
||||
);
|
||||
}
|
||||
}
|
||||
34
public/kirby/src/Panel/Ui/Buttons/LanguageDeleteButton.php
Normal file
34
public/kirby/src/Panel/Ui/Buttons/LanguageDeleteButton.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Language;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* View button to delete a language
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class LanguageDeleteButton extends ViewButton
|
||||
{
|
||||
public function __construct(Language $language)
|
||||
{
|
||||
$user = App::instance()->user();
|
||||
$permission = $user?->role()->permissions()->for('languages', 'delete');
|
||||
|
||||
parent::__construct(
|
||||
dialog: 'languages/' . $language->id() . '/delete',
|
||||
disabled: $permission !== true,
|
||||
icon: 'trash',
|
||||
title: I18n::translate('delete'),
|
||||
);
|
||||
}
|
||||
}
|
||||
34
public/kirby/src/Panel/Ui/Buttons/LanguageSettingsButton.php
Normal file
34
public/kirby/src/Panel/Ui/Buttons/LanguageSettingsButton.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Language;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* View button to update settings of a language
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class LanguageSettingsButton extends ViewButton
|
||||
{
|
||||
public function __construct(Language $language)
|
||||
{
|
||||
$user = App::instance()->user();
|
||||
$permission = $user?->role()->permissions()->for('languages', 'update');
|
||||
|
||||
parent::__construct(
|
||||
dialog: 'languages/' . $language->id() . '/update',
|
||||
disabled: $permission !== true,
|
||||
icon: 'cog',
|
||||
title: I18n::translate('settings'),
|
||||
);
|
||||
}
|
||||
}
|
||||
120
public/kirby/src/Panel/Ui/Buttons/LanguagesDropdown.php
Normal file
120
public/kirby/src/Panel/Ui/Buttons/LanguagesDropdown.php
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Language;
|
||||
use Kirby\Cms\Languages;
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
* View button to switch content translation languages
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class LanguagesDropdown extends ViewButton
|
||||
{
|
||||
protected App $kirby;
|
||||
|
||||
public function __construct(
|
||||
ModelWithContent $model
|
||||
) {
|
||||
$this->kirby = $model->kirby();
|
||||
|
||||
parent::__construct(
|
||||
component: 'k-languages-dropdown',
|
||||
model: $model,
|
||||
class: 'k-languages-dropdown',
|
||||
icon: 'translate',
|
||||
// Fiber dropdown endpoint to load options
|
||||
// only when dropdown is opened
|
||||
options: $model->panel()->url(true) . '/languages',
|
||||
responsive: 'text',
|
||||
text: Str::upper($this->kirby->language()?->code())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if any translation other than the current one has unsaved changes
|
||||
* (the current language has to be handled in `k-languages-dropdown` as its
|
||||
* state can change dynamically without another backend request)
|
||||
*/
|
||||
public function hasDiff(): bool
|
||||
{
|
||||
foreach (Languages::ensure() as $language) {
|
||||
if ($this->kirby->language()?->code() !== $language->code()) {
|
||||
if ($this->model->version('changes')->exists($language) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function option(Language $language): array
|
||||
{
|
||||
$changes = $this->model->version('changes');
|
||||
|
||||
return [
|
||||
'text' => $language->name(),
|
||||
'code' => $language->code(),
|
||||
'current' => $language->code() === $this->kirby->language()?->code(),
|
||||
'default' => $language->isDefault(),
|
||||
'changes' => $changes->exists($language),
|
||||
'lock' => $changes->isLocked('*')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Options are used in the Fiber dropdown routes
|
||||
*/
|
||||
public function options(): array
|
||||
{
|
||||
$languages = $this->kirby->languages();
|
||||
$options = [];
|
||||
|
||||
if ($this->kirby->multilang() === false) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
// add the primary/default language first
|
||||
if ($default = $languages->default()) {
|
||||
$options[] = $this->option($default);
|
||||
$options[] = '-';
|
||||
$languages = $languages->not($default);
|
||||
}
|
||||
|
||||
// add all secondary languages after the separator
|
||||
foreach ($languages as $language) {
|
||||
$options[] = $this->option($language);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
...parent::props(),
|
||||
'hasDiff' => $this->hasDiff()
|
||||
];
|
||||
}
|
||||
|
||||
public function render(): array|null
|
||||
{
|
||||
// hides the language selector when there are less than 2 languages
|
||||
if ($this->kirby->languages()->count() < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
}
|
||||
32
public/kirby/src/Panel/Ui/Buttons/OpenButton.php
Normal file
32
public/kirby/src/Panel/Ui/Buttons/OpenButton.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Open view button
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class OpenButton extends ViewButton
|
||||
{
|
||||
public function __construct(
|
||||
public string|null $link,
|
||||
public string|null $target = '_blank'
|
||||
) {
|
||||
parent::__construct(
|
||||
class: 'k-open-view-button',
|
||||
icon: 'open',
|
||||
link: $link,
|
||||
target: $target,
|
||||
title: I18n::translate('open')
|
||||
);
|
||||
}
|
||||
}
|
||||
50
public/kirby/src/Panel/Ui/Buttons/PageStatusButton.php
Normal file
50
public/kirby/src/Panel/Ui/Buttons/PageStatusButton.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Status view button for pages
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class PageStatusButton extends ViewButton
|
||||
{
|
||||
public function __construct(
|
||||
Page $page
|
||||
) {
|
||||
$status = $page->status();
|
||||
$blueprint = $page->blueprint()->status()[$status] ?? null;
|
||||
$disabled = $page->permissions()->cannot('changeStatus');
|
||||
$text = $blueprint['label'] ?? I18n::translate('page.status.' . $status);
|
||||
$title = I18n::translate('page.status') . ': ' . $text;
|
||||
|
||||
if ($disabled === true) {
|
||||
$title .= ' (' . I18n::translate('disabled') . ')';
|
||||
}
|
||||
|
||||
parent::__construct(
|
||||
class: 'k-status-view-button k-page-status-button',
|
||||
component: 'k-status-view-button',
|
||||
dialog: $page->panel()->url(true) . '/changeStatus',
|
||||
disabled: $disabled,
|
||||
icon: 'status-' . $status,
|
||||
style: '--icon-size: 15px',
|
||||
text: $text,
|
||||
title: $title,
|
||||
theme: match($status) {
|
||||
'draft' => 'negative-icon',
|
||||
'unlisted' => 'info-icon',
|
||||
'listed' => 'positive-icon'
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
30
public/kirby/src/Panel/Ui/Buttons/PreviewButton.php
Normal file
30
public/kirby/src/Panel/Ui/Buttons/PreviewButton.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Preview view button
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class PreviewButton extends ViewButton
|
||||
{
|
||||
public function __construct(
|
||||
public string|null $link
|
||||
) {
|
||||
parent::__construct(
|
||||
class: 'k-preview-view-button',
|
||||
icon: 'window',
|
||||
link: $link,
|
||||
title: I18n::translate('preview')
|
||||
);
|
||||
}
|
||||
}
|
||||
32
public/kirby/src/Panel/Ui/Buttons/SettingsButton.php
Normal file
32
public/kirby/src/Panel/Ui/Buttons/SettingsButton.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Settings view button for models
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class SettingsButton extends ViewButton
|
||||
{
|
||||
public function __construct(
|
||||
ModelWithContent $model
|
||||
) {
|
||||
parent::__construct(
|
||||
component: 'k-settings-view-button',
|
||||
class: 'k-settings-view-button',
|
||||
icon: 'cog',
|
||||
options: $model->panel()->url(true),
|
||||
title: I18n::translate('settings'),
|
||||
);
|
||||
}
|
||||
}
|
||||
57
public/kirby/src/Panel/Ui/Buttons/VersionsButton.php
Normal file
57
public/kirby/src/Panel/Ui/Buttons/VersionsButton.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Content\VersionId;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Versions view button for models
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class VersionsButton extends ViewButton
|
||||
{
|
||||
public function __construct(
|
||||
ModelWithContent $model,
|
||||
VersionId|string $versionId = 'latest'
|
||||
) {
|
||||
$versionId = $versionId === 'compare' ? 'compare' : VersionId::from($versionId)->value();
|
||||
$viewUrl = $model->panel()->url(true) . '/preview';
|
||||
|
||||
parent::__construct(
|
||||
class: 'k-versions-view-button',
|
||||
icon: $versionId === 'compare' ? 'layout-columns' : 'git-branch',
|
||||
options: [
|
||||
[
|
||||
'label' => I18n::translate('version.latest'),
|
||||
'icon' => 'git-branch',
|
||||
'link' => $viewUrl . '/latest',
|
||||
'current' => $versionId === 'latest'
|
||||
],
|
||||
[
|
||||
'label' => I18n::translate('version.changes'),
|
||||
'icon' => 'git-branch',
|
||||
'link' => $viewUrl . '/changes',
|
||||
'current' => $versionId === 'changes'
|
||||
],
|
||||
'-',
|
||||
[
|
||||
'label' => I18n::translate('version.compare'),
|
||||
'icon' => 'layout-columns',
|
||||
'link' => $viewUrl . '/compare',
|
||||
'current' => $versionId === 'compare'
|
||||
],
|
||||
|
||||
],
|
||||
text: I18n::translate('version.' . $versionId),
|
||||
);
|
||||
}
|
||||
}
|
||||
215
public/kirby/src/Panel/Ui/Buttons/ViewButton.php
Normal file
215
public/kirby/src/Panel/Ui/Buttons/ViewButton.php
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Closure;
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Language;
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Panel\Panel;
|
||||
use Kirby\Panel\Ui\Button;
|
||||
use Kirby\Toolkit\Controller;
|
||||
|
||||
/**
|
||||
* A view button is a UI button, by default small in size and filles,
|
||||
* that optionally defines options for a dropdown
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class ViewButton extends Button
|
||||
{
|
||||
public function __construct(
|
||||
public string $component = 'k-view-button',
|
||||
public readonly ModelWithContent|Language|null $model = null,
|
||||
public array|null $badge = null,
|
||||
public string|null $class = null,
|
||||
public string|bool|null $current = null,
|
||||
public string|null $dialog = null,
|
||||
public bool $disabled = false,
|
||||
public string|null $drawer = null,
|
||||
public bool|null $dropdown = null,
|
||||
public string|null $icon = null,
|
||||
public string|null $link = null,
|
||||
public array|string|null $options = null,
|
||||
public bool|string $responsive = true,
|
||||
public string|null $size = 'sm',
|
||||
public string|null $style = null,
|
||||
public string|null $target = null,
|
||||
public string|array|null $text = null,
|
||||
public string|null $theme = null,
|
||||
public string|array|null $title = null,
|
||||
public string $type = 'button',
|
||||
public string|null $variant = 'filled',
|
||||
...$attrs
|
||||
) {
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new view button by looking up
|
||||
* the button in all areas, if referenced by name
|
||||
* and resolving to proper instance
|
||||
*/
|
||||
public static function factory(
|
||||
string|array|Closure|bool $button = true,
|
||||
string|int|null $name = null,
|
||||
string|null $view = null,
|
||||
ModelWithContent|Language|null $model = null,
|
||||
array $data = []
|
||||
): static|null {
|
||||
// if referenced by name (`name: false`),
|
||||
// don't render anything
|
||||
if ($button === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// transform `- name` notation to `name: true`
|
||||
if (
|
||||
is_string($name) === false &&
|
||||
is_string($button) === true
|
||||
) {
|
||||
$name = $button;
|
||||
$button = true;
|
||||
}
|
||||
|
||||
// if referenced by name (`name: true`),
|
||||
// try to get button definition from areas or config
|
||||
if ($button === true) {
|
||||
$button = static::find($name, $view);
|
||||
}
|
||||
|
||||
// resolve Closure to button object or array
|
||||
if ($button instanceof Closure) {
|
||||
$button = static::resolve($button, $model, $data);
|
||||
}
|
||||
|
||||
if (
|
||||
$button === null ||
|
||||
$button instanceof ViewButton
|
||||
) {
|
||||
return $button;
|
||||
}
|
||||
|
||||
// flatten array into list of arguments for this class
|
||||
$button = static::normalize($button);
|
||||
|
||||
// if button definition has a name, use it for the component name
|
||||
if (is_string($name) === true) {
|
||||
// if this specific component does not exist,
|
||||
// `k-view-buttons` will fall back to `k-view-button` again
|
||||
$button['component'] ??= 'k-' . $name . '-view-button';
|
||||
}
|
||||
|
||||
return new static(...$button, model: $model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a view button by name
|
||||
* among the defined buttons from all areas
|
||||
* @unstable
|
||||
*/
|
||||
public static function find(
|
||||
string $name,
|
||||
string|null $view = null
|
||||
): array|Closure {
|
||||
// collect all buttons from areas and config
|
||||
$buttons = [
|
||||
...Panel::buttons(),
|
||||
...App::instance()->option('panel.viewButtons.' . $view, [])
|
||||
];
|
||||
|
||||
// try to find by full name (view-prefixed)
|
||||
if ($view && $button = $buttons[$view . '.' . $name] ?? null) {
|
||||
return $button;
|
||||
}
|
||||
|
||||
// try to find by just name
|
||||
if ($button = $buttons[$name] ?? null) {
|
||||
return $button;
|
||||
}
|
||||
|
||||
// assume it must be a custom view button component
|
||||
return ['component' => 'k-' . $name . '-view-button'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an array to be used as
|
||||
* named arguments in the constructor
|
||||
* @unstable
|
||||
*/
|
||||
public static function normalize(array $button): array
|
||||
{
|
||||
// if component and props are both not set, assume shortcut
|
||||
// where props were directly passed on top-level
|
||||
if (
|
||||
isset($button['component']) === false &&
|
||||
isset($button['props']) === false
|
||||
) {
|
||||
return $button;
|
||||
}
|
||||
|
||||
// flatten array
|
||||
if ($props = $button['props'] ?? null) {
|
||||
$button = [...$props, ...$button];
|
||||
unset($button['props']);
|
||||
}
|
||||
|
||||
return $button;
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
// helper for props that support Kirby queries
|
||||
$resolve = fn ($value) =>
|
||||
$value ?
|
||||
$this->model?->toSafeString($value) ?? $value :
|
||||
null;
|
||||
|
||||
return [
|
||||
...$props = parent::props(),
|
||||
'dialog' => $resolve($props['dialog']),
|
||||
'drawer' => $resolve($props['drawer']),
|
||||
'icon' => $resolve($props['icon']),
|
||||
'link' => $resolve($props['link']),
|
||||
'text' => $resolve($props['text']),
|
||||
'theme' => $resolve($props['theme']),
|
||||
'options' => $this->options
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a closure to the actual view button
|
||||
* by calling it with the provided arguments
|
||||
*/
|
||||
public static function resolve(
|
||||
Closure $button,
|
||||
ModelWithContent|Language|null $model = null,
|
||||
array $data = []
|
||||
): static|array|null {
|
||||
$kirby = App::instance();
|
||||
$controller = new Controller($button);
|
||||
|
||||
if (
|
||||
$model instanceof ModelWithContent ||
|
||||
$model instanceof Language
|
||||
) {
|
||||
$data = [
|
||||
'model' => $model,
|
||||
$model::CLASS_ALIAS => $model,
|
||||
...$data
|
||||
];
|
||||
}
|
||||
|
||||
return $controller->call(data: [
|
||||
'kirby' => $kirby,
|
||||
'site' => $kirby->site(),
|
||||
'user' => $kirby->user(),
|
||||
...$data
|
||||
]);
|
||||
}
|
||||
}
|
||||
104
public/kirby/src/Panel/Ui/Buttons/ViewButtons.php
Normal file
104
public/kirby/src/Panel/Ui/Buttons/ViewButtons.php
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Buttons;
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Language;
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Panel\Model;
|
||||
|
||||
/**
|
||||
* Collects view buttons for a specific view
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class ViewButtons
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $view,
|
||||
public readonly ModelWithContent|Language|null $model = null,
|
||||
public array|false|null $buttons = null,
|
||||
public array $data = []
|
||||
) {
|
||||
// if no specific buttons are passed,
|
||||
// use default buttons for this view from config
|
||||
$this->buttons ??= App::instance()->option(
|
||||
'panel.viewButtons.' . $view
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds data passed to view button closures
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function bind(array $data): static
|
||||
{
|
||||
$this->data = [...$this->data, ...$data];
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the default buttons
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function defaults(string ...$defaults): static
|
||||
{
|
||||
$this->buttons ??= $defaults;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of button component-props definitions
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
// hides all buttons when `buttons: false` set
|
||||
if ($this->buttons === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$buttons = [];
|
||||
|
||||
foreach ($this->buttons ?? [] as $name => $button) {
|
||||
$buttons[] = ViewButton::factory(
|
||||
button: $button,
|
||||
name: $name,
|
||||
view: $this->view,
|
||||
model: $this->model,
|
||||
data: $this->data
|
||||
)?->render();
|
||||
}
|
||||
|
||||
return array_values(array_filter($buttons));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new instance for a view
|
||||
* with special support for model views
|
||||
*/
|
||||
public static function view(
|
||||
string|Model $view,
|
||||
ModelWithContent|Language|null $model = null
|
||||
): static {
|
||||
if ($view instanceof Model) {
|
||||
$model = $view->model();
|
||||
$blueprint = $model->blueprint()->buttons();
|
||||
$view = $model::CLASS_ALIAS;
|
||||
}
|
||||
|
||||
return new static(
|
||||
view: $view,
|
||||
model: $model ?? null,
|
||||
buttons: $blueprint ?? null
|
||||
);
|
||||
}
|
||||
}
|
||||
93
public/kirby/src/Panel/Ui/Component.php
Normal file
93
public/kirby/src/Panel/Ui/Component.php
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui;
|
||||
|
||||
use Kirby\Exception\LogicException;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
* Component that can be passed as component-props array
|
||||
* to the Vue Panel frontend
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
*/
|
||||
abstract class Component
|
||||
{
|
||||
protected string $key;
|
||||
public array $attrs = [];
|
||||
|
||||
public function __construct(
|
||||
public string $component,
|
||||
public string|null $class = null,
|
||||
public string|null $style = null,
|
||||
...$attrs
|
||||
) {
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic setter and getter for component properties
|
||||
*
|
||||
* ```php
|
||||
* $component->class('my-class')
|
||||
* ```
|
||||
*/
|
||||
public function __call(string $name, array $args = [])
|
||||
{
|
||||
if (property_exists($this, $name) === false) {
|
||||
throw new LogicException(
|
||||
message: 'The property "' . $name . '" does not exist on the UI component "' . $this->component . '"'
|
||||
);
|
||||
}
|
||||
|
||||
// getter
|
||||
if ($args === []) {
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
// setter
|
||||
$this->$name = $args[0];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a (unique) key that can be used
|
||||
* for Vue's `:key` attribute
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return $this->key ??= Str::random(10, 'alphaNum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the props that will be passed to the Vue component
|
||||
*/
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
'class' => $this->class,
|
||||
'style' => $this->style,
|
||||
...$this->attrs
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array with the Vue component name and props array
|
||||
*/
|
||||
public function render(): array|null
|
||||
{
|
||||
return [
|
||||
'component' => $this->component,
|
||||
'key' => $this->key(),
|
||||
'props' => array_filter(
|
||||
$this->props(),
|
||||
fn ($prop) => $prop !== null
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
105
public/kirby/src/Panel/Ui/FilePreview.php
Normal file
105
public/kirby/src/Panel/Ui/FilePreview.php
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui;
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Panel\Ui\FilePreviews\DefaultFilePreview;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* Defines a component that implements a file preview
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
*/
|
||||
abstract class FilePreview extends Component
|
||||
{
|
||||
public function __construct(
|
||||
public File $file,
|
||||
public string $component
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class should
|
||||
* handle the preview of this file
|
||||
*/
|
||||
abstract public static function accepts(File $file): bool;
|
||||
|
||||
/**
|
||||
* Returns detail information about the file
|
||||
*/
|
||||
public function details(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'title' => I18n::translate('template'),
|
||||
'text' => $this->file->template() ?? '—'
|
||||
],
|
||||
[
|
||||
'title' => I18n::translate('mime'),
|
||||
'text' => $this->file->mime()
|
||||
],
|
||||
[
|
||||
'title' => I18n::translate('url'),
|
||||
'link' => $link = $this->file->previewUrl(),
|
||||
'text' => $link,
|
||||
],
|
||||
[
|
||||
'title' => I18n::translate('size'),
|
||||
'text' => $this->file->niceSize()
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file preview instance by going through all
|
||||
* available handler classes and finding the first that
|
||||
* accepts the file
|
||||
*/
|
||||
final public static function factory(File $file): static
|
||||
{
|
||||
// get file preview classes providers from plugins
|
||||
$handlers = App::instance()->extensions('filePreviews');
|
||||
|
||||
foreach ($handlers as $handler) {
|
||||
if (is_subclass_of($handler, self::class) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
message: 'File preview handler "' . $handler . '" must extend ' . self::class
|
||||
);
|
||||
}
|
||||
|
||||
if ($handler::accepts($file) === true) {
|
||||
return new $handler($file);
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultFilePreview($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon or image to display as thumbnail
|
||||
*/
|
||||
public function image(): array|null
|
||||
{
|
||||
return $this->file->panel()->image([
|
||||
'back' => 'transparent',
|
||||
'ratio' => '1/1'
|
||||
], 'cards');
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
'details' => $this->details(),
|
||||
'image' => $this->image(),
|
||||
'url' => $this->file->previewUrl()
|
||||
];
|
||||
}
|
||||
}
|
||||
29
public/kirby/src/Panel/Ui/FilePreviews/AudioFilePreview.php
Normal file
29
public/kirby/src/Panel/Ui/FilePreviews/AudioFilePreview.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\FilePreviews;
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Panel\Ui\FilePreview;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class AudioFilePreview extends FilePreview
|
||||
{
|
||||
public function __construct(
|
||||
public File $file,
|
||||
public string $component = 'k-audio-file-preview'
|
||||
) {
|
||||
}
|
||||
|
||||
public static function accepts(File $file): bool
|
||||
{
|
||||
return $file->type() === 'audio';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\FilePreviews;
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Panel\Ui\FilePreview;
|
||||
|
||||
/**
|
||||
* Fallback file preview component
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class DefaultFilePreview extends FilePreview
|
||||
{
|
||||
public function __construct(
|
||||
public File $file,
|
||||
public string $component = 'k-default-file-preview'
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts any file as last resort
|
||||
*/
|
||||
public static function accepts(File $file): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
...parent::props(),
|
||||
'image' => $this->image()
|
||||
];
|
||||
}
|
||||
}
|
||||
53
public/kirby/src/Panel/Ui/FilePreviews/ImageFilePreview.php
Normal file
53
public/kirby/src/Panel/Ui/FilePreviews/ImageFilePreview.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\FilePreviews;
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Panel\Ui\FilePreview;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class ImageFilePreview extends FilePreview
|
||||
{
|
||||
public function __construct(
|
||||
public File $file,
|
||||
public string $component = 'k-image-file-preview'
|
||||
) {
|
||||
}
|
||||
|
||||
public static function accepts(File $file): bool
|
||||
{
|
||||
return $file->type() === 'image';
|
||||
}
|
||||
|
||||
public function details(): array
|
||||
{
|
||||
return [
|
||||
...parent::details(),
|
||||
[
|
||||
'title' => I18n::translate('dimensions'),
|
||||
'text' => $this->file->dimensions() . ' ' . I18n::translate('pixel')
|
||||
],
|
||||
[
|
||||
'title' => I18n::translate('orientation'),
|
||||
'text' => I18n::translate('orientation.' . $this->file->dimensions()->orientation())
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
...parent::props(),
|
||||
'focusable' => $this->file->panel()->isFocusable()
|
||||
];
|
||||
}
|
||||
}
|
||||
29
public/kirby/src/Panel/Ui/FilePreviews/PdfFilePreview.php
Normal file
29
public/kirby/src/Panel/Ui/FilePreviews/PdfFilePreview.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\FilePreviews;
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Panel\Ui\FilePreview;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class PdfFilePreview extends FilePreview
|
||||
{
|
||||
public function __construct(
|
||||
public File $file,
|
||||
public string $component = 'k-pdf-file-preview'
|
||||
) {
|
||||
}
|
||||
|
||||
public static function accepts(File $file): bool
|
||||
{
|
||||
return $file->extension() === 'pdf';
|
||||
}
|
||||
}
|
||||
29
public/kirby/src/Panel/Ui/FilePreviews/VideoFilePreview.php
Normal file
29
public/kirby/src/Panel/Ui/FilePreviews/VideoFilePreview.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\FilePreviews;
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Panel\Ui\FilePreview;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.0.0
|
||||
* @unstable
|
||||
*/
|
||||
class VideoFilePreview extends FilePreview
|
||||
{
|
||||
public function __construct(
|
||||
public File $file,
|
||||
public string $component = 'k-video-file-preview'
|
||||
) {
|
||||
}
|
||||
|
||||
public static function accepts(File $file): bool
|
||||
{
|
||||
return $file->type() === 'video';
|
||||
}
|
||||
}
|
||||
74
public/kirby/src/Panel/Ui/Item/FileItem.php
Normal file
74
public/kirby/src/Panel/Ui/Item/FileItem.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Item;
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Panel\Model;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class FileItem extends ModelItem
|
||||
{
|
||||
/**
|
||||
* @var \Kirby\Cms\File
|
||||
*/
|
||||
protected ModelWithContent $model;
|
||||
|
||||
/**
|
||||
* @var \Kirby\Panel\File
|
||||
*/
|
||||
protected Model $panel;
|
||||
|
||||
public function __construct(
|
||||
File $file,
|
||||
protected bool $dragTextIsAbsolute = false,
|
||||
string|array|false|null $image = [],
|
||||
string|null $info = null,
|
||||
string|null $layout = null,
|
||||
string|null $text = null,
|
||||
) {
|
||||
parent::__construct(
|
||||
model: $file,
|
||||
image: $image,
|
||||
info: $info,
|
||||
layout: $layout,
|
||||
text: $text ?? '{{ file.filename }}',
|
||||
);
|
||||
}
|
||||
|
||||
protected function dragText(): string
|
||||
{
|
||||
return $this->panel->dragText(absolute: $this->dragTextIsAbsolute);
|
||||
}
|
||||
|
||||
protected function permissions(): array
|
||||
{
|
||||
$permissions = $this->model->permissions();
|
||||
|
||||
return [
|
||||
'delete' => $permissions->can('delete'),
|
||||
'sort' => $permissions->can('sort'),
|
||||
];
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
...parent::props(),
|
||||
'dragText' => $this->dragText(),
|
||||
'extension' => $this->model->extension(),
|
||||
'filename' => $this->model->filename(),
|
||||
'mime' => $this->model->mime(),
|
||||
'parent' => $this->model->parent()->panel()->path(),
|
||||
'template' => $this->model->template(),
|
||||
'url' => $this->model->url(),
|
||||
];
|
||||
}
|
||||
}
|
||||
74
public/kirby/src/Panel/Ui/Item/ModelItem.php
Normal file
74
public/kirby/src/Panel/Ui/Item/ModelItem.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Item;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Panel\Model as Panel;
|
||||
use Kirby\Panel\Ui\Component;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class ModelItem extends Component
|
||||
{
|
||||
protected string $layout;
|
||||
protected Panel $panel;
|
||||
protected string $text;
|
||||
|
||||
public function __construct(
|
||||
protected ModelWithContent $model,
|
||||
protected string|array|false|null $image = [],
|
||||
protected string|null $info = null,
|
||||
string|null $layout = null,
|
||||
string|null $text = null,
|
||||
) {
|
||||
parent::__construct(component: 'k-item');
|
||||
|
||||
$this->layout = $layout ?? 'list';
|
||||
$this->panel = $this->model->panel();
|
||||
$this->text = $text ?? '{{ model.title }}';
|
||||
}
|
||||
|
||||
protected function info(): string|null
|
||||
{
|
||||
return $this->model->toSafeString($this->info ?? false);
|
||||
}
|
||||
|
||||
protected function image(): array|null
|
||||
{
|
||||
return $this->panel->image($this->image, $this->layout);
|
||||
}
|
||||
|
||||
protected function link(): string
|
||||
{
|
||||
return $this->panel->url(true);
|
||||
}
|
||||
|
||||
protected function permissions(): array
|
||||
{
|
||||
return $this->model->permissions()->toArray();
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->model->id(),
|
||||
'image' => $this->image(),
|
||||
'info' => $this->info(),
|
||||
'link' => $this->link(),
|
||||
'permissions' => $this->permissions(),
|
||||
'text' => $this->text(),
|
||||
'uuid' => $this->model->uuid()?->toString(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function text(): string
|
||||
{
|
||||
return $this->model->toSafeString($this->text);
|
||||
}
|
||||
}
|
||||
74
public/kirby/src/Panel/Ui/Item/PageItem.php
Normal file
74
public/kirby/src/Panel/Ui/Item/PageItem.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Item;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Panel\Model;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class PageItem extends ModelItem
|
||||
{
|
||||
/**
|
||||
* @var \Kirby\Cms\Page
|
||||
*/
|
||||
protected ModelWithContent $model;
|
||||
|
||||
/**
|
||||
* @var \Kirby\Panel\Page
|
||||
*/
|
||||
protected Model $panel;
|
||||
|
||||
public function __construct(
|
||||
Page $page,
|
||||
string|array|false|null $image = [],
|
||||
string|null $info = null,
|
||||
string|null $layout = null,
|
||||
string|null $text = null,
|
||||
) {
|
||||
parent::__construct(
|
||||
model: $page,
|
||||
image: $image,
|
||||
info: $info,
|
||||
layout: $layout,
|
||||
text: $text ?? '{{ page.title }}',
|
||||
);
|
||||
}
|
||||
|
||||
protected function dragText(): string
|
||||
{
|
||||
return $this->panel->dragText();
|
||||
}
|
||||
|
||||
protected function permissions(): array
|
||||
{
|
||||
$permissions = $this->model->permissions();
|
||||
|
||||
return [
|
||||
'changeSlug' => $permissions->can('changeSlug'),
|
||||
'changeStatus' => $permissions->can('changeStatus'),
|
||||
'changeTitle' => $permissions->can('changeTitle'),
|
||||
'delete' => $permissions->can('delete'),
|
||||
'sort' => $permissions->can('sort'),
|
||||
];
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
...parent::props(),
|
||||
'dragText' => $this->dragText(),
|
||||
'parent' => $this->model->parentId(),
|
||||
'status' => $this->model->status(),
|
||||
'template' => $this->model->intendedTemplate()->name(),
|
||||
'url' => $this->model->url(),
|
||||
];
|
||||
}
|
||||
}
|
||||
38
public/kirby/src/Panel/Ui/Item/UserItem.php
Normal file
38
public/kirby/src/Panel/Ui/Item/UserItem.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui\Item;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Cms\User;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class UserItem extends ModelItem
|
||||
{
|
||||
/**
|
||||
* @var \Kirby\Cms\User
|
||||
*/
|
||||
protected ModelWithContent $model;
|
||||
|
||||
public function __construct(
|
||||
User $user,
|
||||
string|array|false|null $image = [],
|
||||
string|null $info = '{{ user.role.title }}',
|
||||
string|null $layout = null,
|
||||
string|null $text = null,
|
||||
) {
|
||||
parent::__construct(
|
||||
model: $user,
|
||||
image: $image,
|
||||
info: $info,
|
||||
layout: $layout,
|
||||
text: $text ?? '{{ user.username }}',
|
||||
);
|
||||
}
|
||||
}
|
||||
140
public/kirby/src/Panel/Ui/Stat.php
Normal file
140
public/kirby/src/Panel/Ui/Stat.php
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class Stat extends Component
|
||||
{
|
||||
public function __construct(
|
||||
public array|string $label,
|
||||
public array|string $value,
|
||||
public string $component = 'k-stat',
|
||||
public array|string|null $dialog = null,
|
||||
public array|string|null $drawer = null,
|
||||
public string|null $icon = null,
|
||||
public array|string|null $info = null,
|
||||
public array|string|null $link = null,
|
||||
public ModelWithContent|null $model = null,
|
||||
public string|null $theme = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function dialog(): string|null
|
||||
{
|
||||
return $this->stringTemplate(
|
||||
$this->i18n($this->dialog)
|
||||
);
|
||||
}
|
||||
|
||||
public function drawer(): string|null
|
||||
{
|
||||
return $this->stringTemplate(
|
||||
$this->i18n($this->drawer)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress TooFewArguments
|
||||
*/
|
||||
public static function from(
|
||||
array|string $input,
|
||||
ModelWithContent|null $model = null,
|
||||
): static {
|
||||
if ($model !== null) {
|
||||
if (is_string($input) === true) {
|
||||
$input = $model->query($input);
|
||||
|
||||
if (is_array($input) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
message: 'Invalid data from stat query. The query must return an array.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$input['model'] = $model;
|
||||
}
|
||||
|
||||
return new static(...$input);
|
||||
}
|
||||
|
||||
public function icon(): string|null
|
||||
{
|
||||
return $this->stringTemplate($this->icon);
|
||||
}
|
||||
|
||||
public function info(): string|null
|
||||
{
|
||||
return $this->stringTemplate(
|
||||
$this->i18n($this->info)
|
||||
);
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return $this->stringTemplate(
|
||||
$this->i18n($this->label)
|
||||
);
|
||||
}
|
||||
|
||||
public function link(): string|null
|
||||
{
|
||||
return $this->stringTemplate(
|
||||
$this->i18n($this->link)
|
||||
);
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
'dialog' => $this->dialog(),
|
||||
'drawer' => $this->drawer(),
|
||||
'icon' => $this->icon(),
|
||||
'info' => $this->info(),
|
||||
'label' => $this->label(),
|
||||
'link' => $this->link(),
|
||||
'theme' => $this->theme(),
|
||||
'value' => $this->value(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function stringTemplate(string|null $string = null): string|null
|
||||
{
|
||||
if ($this->model === null) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
if ($string !== null) {
|
||||
return $this->model->toString($string);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function theme(): string|null
|
||||
{
|
||||
return $this->stringTemplate($this->theme);
|
||||
}
|
||||
|
||||
protected function i18n(string|array|null $param = null): string|null
|
||||
{
|
||||
return empty($param) === false ? I18n::translate($param, $param) : null;
|
||||
}
|
||||
|
||||
public function value(): string
|
||||
{
|
||||
return $this->stringTemplate(
|
||||
$this->i18n($this->value)
|
||||
);
|
||||
}
|
||||
}
|
||||
83
public/kirby/src/Panel/Ui/Stats.php
Normal file
83
public/kirby/src/Panel/Ui/Stats.php
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui;
|
||||
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class Stats extends Component
|
||||
{
|
||||
public function __construct(
|
||||
public string $component = 'k-stats',
|
||||
public ModelWithContent|null $model = null,
|
||||
public array $reports = [],
|
||||
public string $size = 'large',
|
||||
) {
|
||||
}
|
||||
|
||||
public static function from(
|
||||
ModelWithContent $model,
|
||||
array|string $reports,
|
||||
string $size = 'large'
|
||||
): static {
|
||||
if (is_string($reports) === true) {
|
||||
$reports = $model->query($reports);
|
||||
|
||||
if (is_array($reports) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
message: 'Invalid data from stats query. The query must return an array.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new static(
|
||||
model: $model,
|
||||
reports: $reports,
|
||||
size: $size
|
||||
);
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
'reports' => $this->reports(),
|
||||
'size' => $this->size(),
|
||||
];
|
||||
}
|
||||
|
||||
public function reports(): array
|
||||
{
|
||||
$reports = [];
|
||||
|
||||
foreach ($this->reports as $stat) {
|
||||
// if not already a Stat object, convert it
|
||||
if ($stat instanceof Stat === false) {
|
||||
try {
|
||||
$stat = Stat::from(
|
||||
input: $stat,
|
||||
model: $this->model
|
||||
);
|
||||
} catch (InvalidArgumentException) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$reports[] = $stat->props();
|
||||
}
|
||||
|
||||
return $reports;
|
||||
}
|
||||
|
||||
public function size(): string
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
}
|
||||
62
public/kirby/src/Panel/Ui/Upload.php
Normal file
62
public/kirby/src/Panel/Ui/Upload.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Kirby\Panel\Ui;
|
||||
|
||||
/**
|
||||
* @package Kirby Panel
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
* @since 5.1.0
|
||||
*/
|
||||
class Upload
|
||||
{
|
||||
public function __construct(
|
||||
protected string $api,
|
||||
protected string|null $accept = null,
|
||||
protected array $attributes = [],
|
||||
protected int|null $max = null,
|
||||
protected bool $multiple = true,
|
||||
protected array|bool|null $preview = null,
|
||||
protected int|null $sort = null,
|
||||
protected string|null $template = null,
|
||||
) {
|
||||
}
|
||||
|
||||
protected function attributes(): array
|
||||
{
|
||||
return [
|
||||
...$this->attributes,
|
||||
'sort' => $this->sort,
|
||||
'template' => $this->template()
|
||||
];
|
||||
}
|
||||
|
||||
protected function max(): int|null
|
||||
{
|
||||
return $this->multiple() === false ? 1 : $this->max;
|
||||
}
|
||||
|
||||
protected function multiple(): bool
|
||||
{
|
||||
return $this->multiple === true && ($this->max === null || $this->max > 1);
|
||||
}
|
||||
|
||||
public function props(): array
|
||||
{
|
||||
return [
|
||||
'accept' => $this->accept,
|
||||
'api' => $this->api,
|
||||
'attributes' => $this->attributes(),
|
||||
'max' => $this->max(),
|
||||
'multiple' => $this->multiple(),
|
||||
'preview' => $this->preview,
|
||||
];
|
||||
}
|
||||
|
||||
protected function template(): string|null
|
||||
{
|
||||
return $this->template === 'default' ? null : $this->template;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue